emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] scratch/org-mode-merge 5cecd27 1/2: Update Org to v9.0.9


From: pank
Subject: [Emacs-diffs] scratch/org-mode-merge 5cecd27 1/2: Update Org to v9.0.9
Date: Thu, 22 Jun 2017 06:16:55 -0400 (EDT)

branch: scratch/org-mode-merge
commit 5cecd275820df825c51bf9a27fcc7e35f30ff273
Author: Rasmus <address@hidden>
Commit: Rasmus <address@hidden>

    Update Org to v9.0.9
    
    Please see etc/ORG-NEWS for details.
---
 doc/misc/org.texi                         |  9875 ++++++++-------
 etc/ORG-NEWS                              |  1406 ++-
 etc/org/OrgOdtStyles.xml                  |    20 +
 etc/org/README                            |     2 +-
 etc/org/library-of-babel.org              |   584 +
 etc/refcards/orgcard.tex                  |    27 +-
 etc/schema/od-manifest-schema-v1.2-os.rnc |    88 +
 etc/schema/od-schema-v1.2-os.rnc          |  6280 ++++++++++
 lisp/org/ob-C.el                          |   423 +-
 lisp/org/ob-J.el                          |   186 +
 lisp/org/ob-R.el                          |   270 +-
 lisp/org/ob-abc.el                        |    92 +
 lisp/org/ob-asymptote.el                  |    46 +-
 lisp/org/ob-awk.el                        |    47 +-
 lisp/org/ob-calc.el                       |    20 +-
 lisp/org/ob-clojure.el                    |   109 +-
 lisp/org/ob-comint.el                     |   112 +-
 lisp/org/ob-coq.el                        |    78 +
 lisp/org/ob-core.el                       |  2816 +++--
 lisp/org/ob-css.el                        |     8 +-
 lisp/org/ob-ditaa.el                      |    36 +-
 lisp/org/ob-dot.el                        |    17 +-
 lisp/org/ob-ebnf.el                       |    83 +
 lisp/org/ob-emacs-lisp.el                 |    55 +-
 lisp/org/ob-eval.el                       |    34 +-
 lisp/org/ob-exp.el                        |   528 +-
 lisp/org/ob-forth.el                      |    87 +
 lisp/org/ob-fortran.el                    |    61 +-
 lisp/org/ob-gnuplot.el                    |    76 +-
 lisp/org/ob-groovy.el                     |   116 +
 lisp/org/ob-haskell.el                    |    57 +-
 lisp/org/ob-io.el                         |    46 +-
 lisp/org/ob-java.el                       |    46 +-
 lisp/org/ob-js.el                         |    28 +-
 lisp/org/ob-keys.el                       |     7 +-
 lisp/org/ob-latex.el                      |   159 +-
 lisp/org/ob-ledger.el                     |     7 +-
 lisp/org/ob-lilypond.el                   |   186 +-
 lisp/org/ob-lisp.el                       |    94 +-
 lisp/org/ob-lob.el                        |   179 +-
 lisp/org/ob-lua.el                        |   403 +
 lisp/org/ob-makefile.el                   |     8 +-
 lisp/org/ob-matlab.el                     |     2 +-
 lisp/org/ob-maxima.el                     |    19 +-
 lisp/org/ob-mscgen.el                     |    10 +-
 lisp/org/ob-ocaml.el                      |    85 +-
 lisp/org/ob-octave.el                     |    82 +-
 lisp/org/ob-org.el                        |     8 +-
 lisp/org/ob-perl.el                       |    31 +-
 lisp/org/ob-picolisp.el                   |    14 +-
 lisp/org/ob-plantuml.el                   |    27 +-
 lisp/org/ob-processing.el                 |   195 +
 lisp/org/ob-python.el                     |   111 +-
 lisp/org/ob-ref.el                        |   230 +-
 lisp/org/ob-ruby.el                       |   128 +-
 lisp/org/ob-sass.el                       |     9 +-
 lisp/org/ob-scala.el                      |    42 +-
 lisp/org/ob-scheme.el                     |    45 +-
 lisp/org/ob-screen.el                     |    20 +-
 lisp/org/ob-sed.el                        |   107 +
 lisp/org/ob-sh.el                         |   217 -
 lisp/org/ob-shell.el                      |   283 +
 lisp/org/ob-shen.el                       |     9 +-
 lisp/org/ob-sql.el                        |   205 +-
 lisp/org/ob-sqlite.el                     |    23 +-
 lisp/org/ob-stan.el                       |    84 +
 lisp/org/ob-table.el                      |    44 +-
 lisp/org/ob-tangle.el                     |   396 +-
 lisp/org/ob.el                            |     2 +-
 lisp/org/org-agenda.el                    |  3097 ++---
 lisp/org/org-archive.el                   |   425 +-
 lisp/org/org-attach.el                    |   154 +-
 lisp/org/org-bbdb.el                      |   110 +-
 lisp/org/org-bibtex.el                    |   161 +-
 lisp/org/org-capture.el                   |  1117 +-
 lisp/org/org-clock.el                     |  1953 +--
 lisp/org/org-colview.el                   |  2305 ++--
 lisp/org/org-compat.el                    |   713 +-
 lisp/org/org-crypt.el                     |   141 +-
 lisp/org/org-ctags.el                     |   101 +-
 lisp/org/org-datetree.el                  |   276 +-
 lisp/org/org-docview.el                   |    32 +-
 lisp/org/org-element.el                   |  5859 +++++----
 lisp/org/org-entities.el                  |  1006 +-
 lisp/org/org-eshell.el                    |     9 +-
 lisp/org/org-eww.el                       |   175 +
 lisp/org/org-faces.el                     |   553 +-
 lisp/org/org-feed.el                      |   161 +-
 lisp/org/org-footnote.el                  |  1206 +-
 lisp/org/org-gnus.el                      |    62 +-
 lisp/org/org-habit.el                     |   120 +-
 lisp/org/org-id.el                        |    28 +-
 lisp/org/org-indent.el                    |   293 +-
 lisp/org/org-info.el                      |    97 +-
 lisp/org/org-inlinetask.el                |    50 +-
 lisp/org/org-irc.el                       |    26 +-
 lisp/org/org-lint.el                      |  1225 ++
 lisp/org/org-list.el                      |  1519 ++-
 lisp/org/org-macro.el                     |   259 +-
 lisp/org/org-macs.el                      |   183 +-
 lisp/org/org-mhe.el                       |    43 +-
 lisp/org/org-mobile.el                    |   299 +-
 lisp/org/org-mouse.el                     |   145 +-
 lisp/org/org-pcomplete.el                 |   108 +-
 lisp/org/org-plot.el                      |   233 +-
 lisp/org/org-protocol.el                  |   357 +-
 lisp/org/org-rmail.el                     |    26 +-
 lisp/org/org-src.el                       |  1545 +--
 lisp/org/org-table.el                     |  4618 +++----
 lisp/org/org-timer.el                     |   376 +-
 lisp/org/org-version.el                   |    10 +-
 lisp/org/org-w3m.el                       |    16 +-
 lisp/org/org.el                           | 18439 +++++++++++++++-------------
 lisp/org/ox-ascii.el                      |  1124 +-
 lisp/org/ox-beamer.el                     |   398 +-
 lisp/org/ox-html.el                       |  2344 ++--
 lisp/org/ox-icalendar.el                  |   441 +-
 lisp/org/ox-latex.el                      |  2518 ++--
 lisp/org/ox-man.el                        |   479 +-
 lisp/org/ox-md.el                         |   364 +-
 lisp/org/ox-odt.el                        |  1776 ++-
 lisp/org/ox-org.el                        |   152 +-
 lisp/org/ox-publish.el                    |   707 +-
 lisp/org/ox-texinfo.el                    |   949 +-
 lisp/org/ox.el                            |  4473 ++++---
 125 files changed, 55488 insertions(+), 37098 deletions(-)

diff --git a/doc/misc/org.texi b/doc/misc/org.texi
index fca5185..272788b 100644
--- a/doc/misc/org.texi
+++ b/doc/misc/org.texi
@@ -4,7 +4,8 @@
 @settitle The Org Manual
 @include docstyle.texi
 
address@hidden VERSION 8.2.9
address@hidden VERSION 9.0.9
address@hidden DATE 2017-06-22
 
 @c Version and Contact Info
 @set MAINTAINERSITE @uref{http://orgmode.org,maintainers web page}
@@ -284,8 +285,8 @@ modify this GNU manual.''
 
 @subtitle Release @value{VERSION}
 @author by Carsten Dominik
-with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan
-Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou.
+with contributions by Bastien Guerry, Nicolas Goaziou, Eric Schulte,
+Jambunathan K, Dan Davison, Thomas Dye, David O'Toole, and Philip Rooke.
 
 @c The following two commands start the copyright page.
 @page
@@ -293,13 +294,14 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and 
Nicolas Goaziou.
 @insertcopying
 @end titlepage
 
address@hidden Output the short table of contents at the beginning.
address@hidden
+
 @c Output the table of contents at the beginning.
 @contents
 
 @ifnottex
address@hidden FIXME These hand-written next,prev,up node pointers make editing 
a lot
address@hidden harder.  There should be no need for them, makeinfo can do it
address@hidden automatically for any document with a normal structure.
+
 @node Top, Introduction, (dir), (dir)
 @top Org Mode Manual
 
@@ -308,23 +310,23 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and 
Nicolas Goaziou.
 
 @menu
 * Introduction::                Getting started
-* Document Structure::          A tree works like your brain
+* Document structure::          A tree works like your brain
 * Tables::                      Pure magic for quick formatting
 * Hyperlinks::                  Notes in context
-* TODO Items::                  Every tree branch can be a TODO item
+* TODO items::                  Every tree branch can be a TODO item
 * Tags::                        Tagging headlines and matching sets of tags
-* Properties and Columns::      Storing information about an entry
-* Dates and Times::             Making items useful for planning
+* Properties and columns::      Storing information about an entry
+* Dates and times::             Making items useful for planning
 * Capture - Refile - Archive::  The ins and outs for projects
-* Agenda Views::                Collecting information into views
+* Agenda views::                Collecting information into views
 * Markup::                      Prepare text for rich export
 * Exporting::                   Sharing and publishing notes
 * Publishing::                  Create a web site of linked Org files
-* Working With Source Code::    Export, evaluate, and tangle code blocks
+* Working with source code::    Export, evaluate, and tangle code blocks
 * Miscellaneous::               All the rest which did not fit elsewhere
 * Hacking::                     How to hack your way around
 * MobileOrg::                   Viewing and capture on a mobile device
-* History and Acknowledgments::  How Org came into being
+* History and acknowledgments::  How Org came into being
 * GNU Free Documentation License::  The license for this documentation.
 * Main Index::                  An index of Org's concepts and features
 * Key Index::                   Key bindings and where they are described
@@ -363,11 +365,6 @@ Visibility cycling
 * Initial visibility::          Setting the initial visibility state
 * Catching invisible edits::    Preventing mistakes when editing invisible 
parts
 
-Global and local cycling
-
-* Initial visibility::          Setting the initial visibility state
-* Catching invisible edits::    Preventing mistakes when editing invisible 
parts
-
 Tables
 
 * Built-in table editor::       Simple tables
@@ -434,7 +431,7 @@ Tags
 
 * Tag inheritance::             Tags use the tree structure of the outline
 * Setting tags::                How to assign tags to a headline
-* Tag groups::                  Use one tag to search for several tags
+* Tag hierarchy::               Create a hierarchy of tags
 * Tag searches::                Searching for combinations of tags
 
 Properties and columns
@@ -464,8 +461,7 @@ Dates and times
 * Deadlines and scheduling::    Planning your work
 * Clocking work time::          Tracking how long you spend on a task
 * Effort estimates::            Planning work effort in advance
-* Relative timer::              Notes with a running timer
-* Countdown timer::             Starting a countdown timer for a task
+* Timers::                      Notes with a running timer
 
 Creating timestamps
 
@@ -487,7 +483,7 @@ Capture - Refile - Archive
 
 * Capture::                     Capturing new stuff
 * Attachments::                 Add files to tasks
-* RSS Feeds::                   Getting input from RSS feeds
+* RSS feeds::                   Getting input from RSS feeds
 * Protocols::                   External (e.g., Browser) access to Emacs and 
Org
 * Refile and copy::             Moving/copying a tree from one place to another
 * Archiving::                   What to do with finished projects
@@ -517,7 +513,7 @@ Agenda views
 * Presentation and sorting::    How agenda items are prepared for display
 * Agenda commands::             Remote editing of Org trees
 * Custom agenda views::         Defining special searches and views
-* Exporting Agenda Views::      Writing a view to a file
+* Exporting agenda views::      Writing a view to a file
 * Agenda column view::          Using column view for collected entries
 
 The built-in agenda views
@@ -540,114 +536,127 @@ Custom agenda views
 
 * Storing searches::            Type once, use often
 * Block agenda::                All the stuff you need in a single buffer
-* Setting Options::             Changing the rules
+* Setting options::             Changing the rules
 
 Markup for rich export
 
-* Structural markup elements::  The basic structure as seen by the exporter
+* Paragraphs::                  The basic unit of text
+* Emphasis and monospace::      Bold, italic, etc.
+* Horizontal rules::            Make a line
 * Images and tables::           Images, tables and caption mechanism
 * Literal examples::            Source code examples with special formatting
-* Include files::               Include additional files into a document
-* Index entries::               Making an index
-* Macro replacement::           Use macros to create templates
+* Special symbols::             Greek letters and other symbols
+* Subscripts and superscripts::  Simple syntax for raising/lowering text
 * Embedded @LaTeX{}::           LaTeX can be freely used inside Org documents
-* Special blocks::              Containers targeted at export back-ends
-
-Structural markup elements
-
-* Document title::              Where the title is taken from
-* Headings and sections::       The document structure as seen by the exporter
-* Table of contents::           The if and where of the table of contents
-* Lists::                       Lists
-* Paragraphs::                  Paragraphs
-* Footnote markup::             Footnotes
-* Emphasis and monospace::      Bold, italic, etc.
-* Horizontal rules::            Make a line
-* Comment lines::               What will *not* be exported
 
 Embedded @LaTeX{}
 
-* Special symbols::             Greek letters and other symbols
-* Subscripts and superscripts::  Simple syntax for raising/lowering text
 * @LaTeX{} fragments::          Complex formulas made easy
 * Previewing @LaTeX{} fragments::  What will this snippet look like?
 * CDLaTeX mode::                Speed up entering of formulas
 
 Exporting
 
-* The Export Dispatcher::       The main exporter interface
-* Export back-ends::            Built-in export formats
-* Export settings::             Generic export settings
+* The export dispatcher::       The main interface
+* Export settings::             Common export settings
+* Table of contents::           The if and where of the table of contents
+* Include files::               Include additional files into a document
+* Macro replacement::           Use macros to create templates
+* Comment lines::               What will not be exported
 * ASCII/Latin-1/UTF-8 export::  Exporting to flat files with encoding
 * Beamer export::               Exporting as a Beamer presentation
 * HTML export::                 Exporting to HTML
-* @LaTeX{} and PDF export::     Exporting to @LaTeX{}, and processing to PDF
+* @LaTeX{} export::             Exporting to @LaTeX{}, and processing to PDF
 * Markdown export::             Exporting to Markdown
 * OpenDocument Text export::    Exporting to OpenDocument Text
 * Org export::                  Exporting to Org
 * Texinfo export::              Exporting to Texinfo
 * iCalendar export::            Exporting to iCalendar
 * Other built-in back-ends::    Exporting to a man page
-* Export in foreign buffers::   Author tables and lists in Org syntax
 * Advanced configuration::      Fine-tuning the export output
+* Export in foreign buffers::   Author tables and lists in Org syntax
+
+Beamer export
+
+* Beamer export commands::      For creating Beamer documents.
+* Beamer specific export settings::  For customizing Beamer export.
+* Sectioning Frames and Blocks in Beamer::  For composing Beamer slides.
+* Beamer specific syntax::      For using in Org documents.
+* Editing support::             For using helper functions.
+* A Beamer example::            A complete presentation.
 
 HTML export
 
-* HTML Export commands::        How to invoke HTML export
-* HTML doctypes::               Org can export to various (X)HTML flavors
-* HTML preamble and postamble::  How to insert a preamble and a postamble
-* Quoting HTML tags::           Using direct HTML in Org mode
-* Links in HTML export::        How links will be interpreted and formatted
-* Tables in HTML export::       How to modify the formatting of tables
-* Images in HTML export::       How to insert figures into HTML output
-* Math formatting in HTML export::  Beautiful math also on the web
-* Text areas in HTML export::   An alternative way to show an example
-* CSS support::                 Changing the appearance of the output
-* JavaScript support::          Info and Folding in a web browser
-
address@hidden and PDF export
-
-* @LaTeX{} export commands::    How to export to LaTeX and PDF
-* Header and sectioning::       Setting up the export file structure
-* Quoting @LaTeX{} code::       Incorporating literal @LaTeX{} code
-* @LaTeX{} specific attributes::  Controlling @LaTeX{} output
+* HTML Export commands::        Invoking HTML export
+* HTML Specific export settings::  Settings for HTML export
+* HTML doctypes::               Exporting various (X)HTML flavors
+* HTML preamble and postamble::  Inserting preamble and postamble
+* Quoting HTML tags::           Using direct HTML in Org files
+* Links in HTML export::        Interpreting and formatting links
+* Tables in HTML export::       Formatting and modifying tables
+* Images in HTML export::       Inserting figures with HTML output
+* Math formatting in HTML export::  Handling math equations
+* Text areas in HTML export::   Showing an alternate approach, an example
+* CSS support::                 Styling HTML output
+* JavaScript support::          Folding scripting in the web browser
+
address@hidden export
+
+* @LaTeX{} export commands::    For producing @LaTeX{} and PDF documents.
+* @LaTeX{} specific export settings::  Unique to this @LaTeX{} back-end.
+* @LaTeX{} header and sectioning::  For file structure.
+* Quoting @LaTeX{} code::       Directly in the Org document.
+* Tables in @LaTeX{} export::   Attributes specific to tables.
+* Images in @LaTeX{} export::   Attributes specific to images.
+* Plain lists in @LaTeX{} export::  Attributes specific to lists.
+* Source blocks in @LaTeX{} export::  Attributes specific to source code 
blocks.
+* Example blocks in @LaTeX{} export::  Attributes specific to example blocks.
+* Special blocks in @LaTeX{} export::  Attributes specific to special blocks.
+* Horizontal rules in @LaTeX{} export::  Attributes specific to horizontal 
rules.
 
 OpenDocument Text export
 
-* Pre-requisites for ODT export::  What packages ODT exporter relies on
-* ODT export commands::         How to invoke ODT export
-* Extending ODT export::        How to produce @samp{doc}, @samp{pdf} files
-* Applying custom styles::      How to apply custom styles to the output
-* Links in ODT export::         How links will be interpreted and formatted
-* Tables in ODT export::        How Tables are exported
-* Images in ODT export::        How to insert images
-* Math formatting in ODT export::  How @LaTeX{} fragments are formatted
-* Labels and captions in ODT export::  How captions are rendered
-* Literal examples in ODT export::  How source and example blocks are formatted
-* Advanced topics in ODT export::  Read this if you are a power user
+* Pre-requisites for ODT export::  Required packages.
+* ODT export commands::         Invoking export.
+* ODT specific export settings::  Configuration options.
+* Extending ODT export::        Producing @file{.doc}, @file{.pdf} files.
+* Applying custom styles::      Styling the output.
+* Links in ODT export::         Handling and formatting links.
+* Tables in ODT export::        Org table conversions.
+* Images in ODT export::        Inserting images.
+* Math formatting in ODT export::  Formatting @LaTeX{} fragments.
+* Labels and captions in ODT export::  Rendering objects.
+* Literal examples in ODT export::  For source code and example blocks.
+* Advanced topics in ODT export::  For power users.
 
 Math formatting in ODT export
 
-* Working with @LaTeX{} math snippets::  How to embed @LaTeX{} math fragments
-* Working with MathML or OpenDocument formula files::  How to embed equations 
in native format
+* Working with @LaTeX{} math snippets::  Embedding in @LaTeX{} format.
+* Working with MathML or OpenDocument formula files::  Embedding in native 
format.
 
 Advanced topics in ODT export
 
-* Configuring a document converter::  How to register a document converter
-* Working with OpenDocument style files::  Explore the internals
-* Creating one-off styles::     How to produce custom highlighting etc
-* Customizing tables in ODT export::  How to define and use Table templates
-* Validating OpenDocument XML::  How to debug corrupt OpenDocument files
+* Configuring a document converter::  Registering a document converter.
+* Working with OpenDocument style files::  Exploring internals.
+* Creating one-off styles::     Customizing styles, highlighting.
+* Customizing tables in ODT export::  Defining table templates.
+* Validating OpenDocument XML::  Debugging corrupted OpenDocument files.
 
 Texinfo export
 
-* Texinfo export commands::     How to invoke Texinfo export
-* Document preamble::           File header, title and copyright page
-* Headings and sectioning structure:: Building document structure
-* Indices::                     Creating indices
-* Quoting Texinfo code::        Incorporating literal Texinfo code
-* Texinfo specific attributes:: Controlling Texinfo output
-* An example::
+* Texinfo export commands::     Invoking commands.
+* Texinfo specific export settings::  Setting the environment.
+* Texinfo file header::         Generating the header.
+* Texinfo title and copyright page::  Creating preamble pages.
+* Info directory file::     Installing a manual in Info file hierarchy.
+* Headings and sectioning structure::  Building document structure.
+* Indices::                     Creating indices.
+* Quoting Texinfo code::        Incorporating literal Texinfo code.
+* Plain lists in Texinfo export::  List attributes.
+* Tables in Texinfo export::    Table attributes.
+* Images in Texinfo export::    Image attributes.
+* Special blocks in Texinfo export::  Special block attributes.
+* A Texinfo example::           Processing Org to Texinfo.
 
 Publishing
 
@@ -694,36 +703,32 @@ Header arguments
 
 Using header arguments
 
-* System-wide header arguments::  Set global default values
-* Language-specific header arguments::  Set default values by language
-* Header arguments in Org mode properties::  Set default values for a buffer 
or heading
-* Language-specific header arguments in Org mode properties::  Set 
language-specific default values for a buffer or heading
-* Code block specific header arguments::  The most common way to set values
-* Header arguments in function calls::  The most specific level
+* System-wide header arguments::  Set globally, language-specific
+* Language-specific header arguments::  Set in the Org file's headers
+* Header arguments in Org mode properties::  Set in the Org file
+* Language-specific mode properties::
+* Code block specific header arguments::  The most commonly used method
+* Arguments in function calls::  The most specific level, takes highest 
priority
 
 Specific header arguments
 
-* var::                         Pass arguments to code blocks
-* results::                     Specify the type of results and how they will
-                                be collected and handled
-* file::                        Specify a path for file output
+* var::                         Pass arguments to @samp{src} code blocks
+* results::                     Specify results type; how to collect
+* file::                        Specify a path for output file
 * file-desc::                   Specify a description for file results
-* dir::                         Specify the default (possibly remote)
-                                directory for code block execution
-* exports::                     Export code and/or results
-* tangle::                      Toggle tangling and specify file name
-* mkdirp::                      Toggle creation of parent directories of target
-                                files during tangling
-* comments::                    Toggle insertion of comments in tangled
-                                code files
-* padline::                     Control insertion of padding lines in tangled
-                                code files
-* no-expand::                   Turn off variable assignment and noweb
-                                expansion during tangling
+* file-ext::                    Specify an extension for file output
+* output-dir::                  Specify a directory for output file
+* dir::                         Specify the default directory for code block 
execution
+* exports::                     Specify exporting code, results, both, none
+* tangle::                      Toggle tangling; or specify file name
+* mkdirp::                      Toggle for parent directory creation for 
target files during tangling
+* comments::                    Toggle insertion of comments in tangled code 
files
+* padline::                     Control insertion of padding lines in tangled 
code files
+* no-expand::                   Turn off variable assignment and noweb 
expansion during tangling
 * session::                     Preserve the state of code evaluation
 * noweb::                       Toggle expansion of noweb references
 * noweb-ref::                   Specify block's noweb reference resolution 
target
-* noweb-sep::                   String used to separate noweb references
+* noweb-sep::                   String to separate noweb references
 * cache::                       Avoid re-evaluating unchanged code blocks
 * sep::                         Delimiter for writing tabular results outside 
Org
 * hlines::                      Handle horizontal lines in tables
@@ -733,22 +738,22 @@ Specific header arguments
 * tangle-mode::                 Set permission of tangled files
 * eval::                        Limit evaluation of specific code blocks
 * wrap::                        Mark source block evaluation results
-* post::                        Post processing of code block results
-* prologue::                    Text to prepend to code block body
-* epilogue::                    Text to append to code block body
+* post::                        Post processing of results of code block 
evaluation
+* prologue::                    Text to prepend to body of code block
+* epilogue::                    Text to append to body of code block
 
 Miscellaneous
 
-* Completion::                  M-TAB knows what you need
-* Easy Templates::              Quick insertion of structural elements
+* Completion::                  M-TAB guesses completions
+* Easy templates::              Quick insertion of structural elements
 * Speed keys::                  Electric commands at the beginning of a 
headline
 * Code evaluation security::    Org mode files evaluate inline code
-* Customization::               Adapting Org to your taste
+* Customization::               Adapting Org to changing tastes
 * In-buffer settings::          Overview of the #+KEYWORDS
 * The very busy C-c C-c key::   When in doubt, press C-c C-c
 * Clean view::                  Getting rid of leading stars in the outline
 * TTY keys::                    Using Org on a tty
-* Interaction::                 Other Emacs packages
+* Interaction::                 With other Emacs packages
 * org-crypt::                   Encrypting Org files
 
 Interaction with other packages
@@ -780,14 +785,14 @@ Tables and lists in arbitrary syntax
 
 MobileOrg
 
-* Setting up the staging area::  Where to interact with the mobile device
+* Setting up the staging area::  For the mobile device
 * Pushing to MobileOrg::        Uploading Org files and agendas
 * Pulling from MobileOrg::      Integrating captured and flagged items
 
 @end detailmenu
 @end menu
 
address@hidden Introduction, Document Structure, Top, Top
address@hidden Introduction
 @chapter Introduction
 @cindex introduction
 
@@ -799,79 +804,65 @@ MobileOrg
 * Conventions::                 Typesetting conventions in the manual
 @end menu
 
address@hidden Summary, Installation, Introduction, Introduction
address@hidden Summary
 @section Summary
 @cindex summary
 
-Org is a mode for keeping notes, maintaining TODO lists, and doing
-project planning with a fast and effective plain-text system.
-
-Org develops organizational tasks around NOTES files that contain
-lists or information about projects as plain text.  Org is
-implemented on top of Outline mode, which makes it possible to keep the
-content of large files well structured.  Visibility cycling and
-structure editing help to work with the tree.  Tables are easily created
-with a built-in table editor.  Org supports TODO items, deadlines,
-timestamps, and scheduling.  It dynamically compiles entries into an
-agenda that utilizes and smoothly integrates much of the Emacs calendar
-and diary.  Plain text URL-like links connect to websites, emails,
-Usenet messages, BBDB entries, and any files related to the projects.
-For printing and sharing notes, an Org file can be exported as a
-structured ASCII file, as HTML, or (TODO and agenda items only) as an
-iCalendar file.  It can also serve as a publishing tool for a set of
-linked web pages.
-
-As a project planning environment, Org works by adding metadata to outline
-nodes.  Based on this data, specific entries can be extracted in queries and
-create dynamic @i{agenda views}.
-
-Org mode contains the Org Babel environment which allows you to work with
-embedded source code blocks in a file, to facilitate code evaluation,
-documentation, and literate programming techniques.
-
-Org's automatic, context-sensitive table editor with spreadsheet
-capabilities can be integrated into any major mode by activating the
-minor Orgtbl mode.  Using a translation step, it can be used to maintain
-tables in arbitrary file types, for example in @LaTeX{}.  The structure
-editing and list creation capabilities can be used outside Org with
-the minor Orgstruct mode.
-
-Org keeps simple things simple.  When first fired up, it should
-feel like a straightforward, easy to use outliner.  Complexity is not
-imposed, but a large amount of functionality is available when you need
-it.  Org is a toolbox and can be used in different ways and for different
-ends, for example:
-
address@hidden
address@hidden@bullet{} an outline extension with visibility cycling and 
structure editing}
address@hidden@bullet{} an ASCII system and table editor for taking structured 
notes}
address@hidden@bullet{} a TODO list editor}
address@hidden@bullet{} a full agenda and planner with deadlines and work 
scheduling}
address@hidden GTD, Getting Things Done
address@hidden@bullet{} an environment in which to implement David Allen's GTD 
system}
address@hidden@bullet{} a simple hypertext system, with HTML and @LaTeX{} 
export}
address@hidden@bullet{} a publishing tool to create a set of interlinked web 
pages}
address@hidden@bullet{} an environment for literate programming}
address@hidden example
+Org is a mode for keeping notes, maintaining TODO lists, and project planning
+with a fast and effective plain-text system.  It also is an authoring system
+with unique support for literate programming and reproducible research.
+
+Org is implemented on top of Outline mode, which makes it possible to keep
+the content of large files well structured.  Visibility cycling and structure
+editing help to work with the tree.  Tables are easily created with a
+built-in table editor.  Plain text URL-like links connect to websites,
+emails, Usenet messages, BBDB entries, and any files related to the projects.
+
+Org develops organizational tasks around notes files that contain lists or
+information about projects as plain text.  Project planning and task
+management makes use of metadata which is part of an outline node.  Based on
+this data, specific entries can be extracted in queries and create dynamic
address@hidden views} that also integrate the Emacs calendar and diary.  Org can
+be used to implement many different project planning schemes, such as David
+Allen's GTD system.
+
+Org files can serve as a single source authoring system with export to many
+different formats such as HTML, @LaTeX{}, Open Document, and Markdown.  New
+export backends can be derived from existing ones, or defined from scratch.
+
+Org files can include source code blocks, which makes Org uniquely suited for
+authoring technical documents with code examples. Org source code blocks are
+fully functional; they can be evaluated in place and their results can be
+captured in the file.  This makes it possible to create a single file
+reproducible research compendium.
+
+Org keeps simple things simple.  When first fired up, it should feel like a
+straightforward, easy to use outliner.  Complexity is not imposed, but a
+large amount of functionality is available when needed.  Org is a toolbox.
+Many users actually run only a (very personal) fraction of Org's capabilities, 
and
+know that there is more whenever they need it.
+
+All of this is achieved with strictly plain text files, the most portable and
+future-proof file format.  Org runs in Emacs.  Emacs is one of the most
+widely ported programs, so that Org mode is available on every major
+platform.
 
 @cindex FAQ
 There is a website for Org which provides links to the newest
 version of Org, as well as additional information, frequently asked
 questions (FAQ), links to tutorials, etc.  This page is located at
 @uref{http://orgmode.org}.
-
 @cindex print edition
-The version 7.3 of this manual is available as a
address@hidden://www.network-theory.co.uk/org/manual/, paperback book from 
Network
-Theory Ltd.}
 
address@hidden
+An earlier version (7.3) of this manual is available as a
address@hidden://www.network-theory.co.uk/org/manual/, paperback book from
+Network Theory Ltd.}
 
address@hidden
 
address@hidden Installation, Activation, Summary, Introduction
address@hidden Installation
 @section Installation
 @cindex installation
address@hidden XEmacs
 
 Org is part of recent distributions of GNU Emacs, so you normally don't need
 to install it.  If, for one reason or another, you want to install Org on top
@@ -895,7 +886,7 @@ been visited, i.e., where no Org built-in function have 
been loaded.
 Otherwise autoload Org functions will mess up the installation.
 
 Then, to make sure your Org configuration is taken into account, initialize
-the package system with @code{(package-initialize)} in your @file{.emacs}
+the package system with @code{(package-initialize)} in your Emacs init file
 before setting any Org option.  If you want to use Org's package repository,
 check out the @uref{http://orgmode.org/elpa.html, Org ELPA page}.
 
@@ -903,7 +894,7 @@ check out the @uref{http://orgmode.org/elpa.html, Org ELPA 
page}.
 
 You can download Org latest release from @uref{http://orgmode.org/, Org's
 website}.  In this case, make sure you set the load-path correctly in your
address@hidden:
+Emacs init file:
 
 @lisp
 (add-to-list 'load-path "~/path/to/orgdir/lisp")
@@ -945,7 +936,7 @@ For more detailed explanations on Org's build system, 
please check the Org
 Build System page on @uref{http://orgmode.org/worg/dev/org-build-system.html,
 Worg}.
 
address@hidden Activation, Feedback, Installation, Introduction
address@hidden Activation
 @section Activation
 @cindex activation
 @cindex autoload
@@ -957,14 +948,6 @@ Worg}.
 @findex org-store-link
 @findex org-iswitchb
 
-Since Emacs 22.2, files with the @file{.org} extension use Org mode by
-default.  If you are using an earlier version of Emacs, add this line to your
address@hidden file:
-
address@hidden
-(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode))
address@hidden lisp
-
 Org mode buffers need font-lock to be turned on: this is the default in
 address@hidden you don't use font-lock globally, turn it on in Org buffer
 with @code{(add-hook 'org-mode-hook 'turn-on-font-lock)}}.
@@ -979,15 +962,15 @@ suggested bindings for these keys, please modify the keys 
to your own
 liking.
 @lisp
 (global-set-key "\C-cl" 'org-store-link)
-(global-set-key "\C-cc" 'org-capture)
 (global-set-key "\C-ca" 'org-agenda)
+(global-set-key "\C-cc" 'org-capture)
 (global-set-key "\C-cb" 'org-iswitchb)
 @end lisp
 
 @cindex Org mode, turning on
-With this setup, all files with extension @samp{.org} will be put
-into Org mode.  As an alternative, make the first line of a file look
-like this:
+Files with the @file{.org} extension use Org mode by default.  To turn on Org
+mode in a file that does not have the extension @file{.org}, make the first
+line of a file look like this:
 
 @example
 MY PROJECTS    -*- mode: org; -*-
@@ -999,17 +982,12 @@ the file's name is.  See also the variable
 @code{org-insert-mode-line-in-empty-file}.
 
 Many commands in Org work on the region if the region is @i{active}.  To make
-use of this, you need to have @code{transient-mark-mode}
-(@code{zmacs-regions} in XEmacs) turned on.  In Emacs 23 this is the default,
-in Emacs 22 you need to do this yourself with
address@hidden
-(transient-mark-mode 1)
address@hidden lisp
address@hidden If you do not like @code{transient-mark-mode}, you can create an
-active region by using the mouse to select a region, or pressing
+use of this, you need to have @code{transient-mark-mode} turned on, which is
+the default.  If you do not like @code{transient-mark-mode}, you can create
+an active region by using the mouse to select a region, or pressing
 @address@hidden twice before moving the cursor.
 
address@hidden Feedback, Conventions, Activation, Introduction
address@hidden Feedback
 @section Feedback
 @cindex feedback
 @cindex bug reports
@@ -1018,6 +996,8 @@ active region by using the mouse to select a region, or 
pressing
 
 If you find problems with Org, or if you have questions, remarks, or ideas
 about it, please mail to the Org mailing list @email{emacs-orgmode@@gnu.org}.
+You can subscribe to the list
address@hidden://lists.gnu.org/mailman/listinfo/emacs-orgmode, on this web 
page}.
 If you are not a member of the mailing list, your mail will be passed to the
 list after a moderator has approved address@hidden consider subscribing
 to the mailing list, in order to minimize the work the mailing list
@@ -1028,13 +1008,13 @@ version of Org available---if you are running an 
outdated version, it is
 quite possible that the bug has been fixed already.  If the bug persists,
 prepare a report and provide as much information as possible, including the
 version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org
-(@kbd{M-x org-version RET}), as well as the Org related setup in
address@hidden  The easiest way to do this is to use the command
+(@kbd{M-x org-version RET}), as well as the Org related setup in the Emacs
+init file.  The easiest way to do this is to use the command
 @example
 @kbd{M-x org-submit-bug-report RET}
 @end example
 @noindent which will put all this information into an Emacs mail buffer so
-that you only need to add your description.  If you re not sending the Email
+that you only need to add your description.  If you are not sending the Email
 from within Emacs, please copy and paste the content into your Email program.
 
 Sometimes you might face a problem due to an error in your Emacs or Org mode
@@ -1097,8 +1077,7 @@ To do this, use
 or select @code{Org -> Refresh/Reload -> Reload Org uncompiled} from the
 menu.
 @item
-Go to the @code{Options} menu and select @code{Enter Debugger on Error}
-(XEmacs has this option in the @code{Troubleshooting} sub-menu).
+Go to the @code{Options} menu and select @code{Enter Debugger on Error}.
 @item
 Do whatever you have to do to hit the error.  Don't forget to
 document the steps you take.
@@ -1108,7 +1087,7 @@ screen.  Save this buffer to a file (for example using 
@kbd{C-x C-w}) and
 attach it to your bug report.
 @end enumerate
 
address@hidden Conventions,  , Feedback, Introduction
address@hidden Conventions
 @section Typesetting conventions used in this manual
 
 @subsubheading TODO keywords, tags, properties, etc.
@@ -1132,21 +1111,20 @@ special meaning are written with all capitals.
 @end table
 
 Moreover, Org uses @i{option keywords} (like @code{#+TITLE} to set the title)
-and @i{environment keywords} (like @code{#+BEGIN_HTML} to start a @code{HTML}
-environment).  They are written in uppercase in the manual to enhance its
-readability, but you can use lowercase in your Org address@hidden
-templates insert lowercase keywords and Babel dynamically inserts
address@hidden
+and @i{environment keywords} (like @code{#+BEGIN_EXPORT html} to start
+a @code{HTML} environment).  They are written in uppercase in the manual to
+enhance its readability, but you can use lowercase in your Org file.
 
address@hidden Keybindings and commands
address@hidden Key bindings and commands
 @kindex C-c a
 @findex org-agenda
 @kindex C-c c
 @findex org-capture
 
-The manual suggests two global keybindings: @kbd{C-c a} for @code{org-agenda}
-and @kbd{C-c c} for @code{org-capture}.  These are only suggestions, but the
-rest of the manual assumes that you are using these keybindings.
+The manual suggests a few global key bindings, in particular @kbd{C-c a} for
address@hidden and @kbd{C-c c} for @code{org-capture}.  These are only
+suggestions, but the rest of the manual assumes that these key bindings are in
+place in order to list commands by key access.
 
 Also, the manual lists both the keys and the corresponding commands for
 accessing a functionality.  Org mode often uses the same key for different
@@ -1159,7 +1137,7 @@ will be listed to call 
@code{org-table-move-column-right}.  If you prefer,
 you can compile the manual without the command names by unsetting the flag
 @code{cmdnames} in @file{org.texi}.
 
address@hidden Document Structure, Tables, Introduction, Top
address@hidden Document structure
 @chapter Document structure
 @cindex document structure
 @cindex structure of document
@@ -1182,7 +1160,7 @@ edit the structure of the document.
 * Org syntax::                  Formal description of Org's syntax
 @end menu
 
address@hidden Outlines, Headlines, Document Structure, Document Structure
address@hidden Outlines
 @section Outlines
 @cindex outlines
 @cindex Outline mode
@@ -1196,7 +1174,7 @@ currently being worked on.  Org greatly simplifies the 
use of
 outlines by compressing the entire show/hide functionality into a single
 command, @command{org-cycle}, which is bound to the @key{TAB} key.
 
address@hidden Headlines, Visibility cycling, Outlines, Document Structure
address@hidden Headlines
 @section Headlines
 @cindex headlines
 @cindex outline tree
@@ -1209,7 +1187,7 @@ start with one or more stars, on the left address@hidden 
the variables
 @code{org-special-ctrl-a/e}, @code{org-special-ctrl-k}, and
 @code{org-ctrl-k-protect-subtree} to configure special behavior of @kbd{C-a},
 @kbd{C-e}, and @kbd{C-k} in headlines.} @footnote{Clocking only works with
-headings indented less then 30 stars.}.  For example:
+headings indented less than 30 stars.}.  For example:
 
 @example
 * Top level headline
@@ -1222,7 +1200,12 @@ headings indented less then 30 stars.}.  For example:
 * Another top level headline
 @end example
 
address@hidden Some people find the many stars too noisy and would prefer an
address@hidden org-footnote-section
address@hidden Note that a headline named after @code{org-footnote-section},
+which defaults to @samp{Footnotes}, is considered as special.  A subtree with
+this headline will be silently ignored by exporting functions.
+
+Some people find the many stars too noisy and would prefer an
 outline that has whitespace followed by a single star as headline
 starters.  @ref{Clean view}, describes a setup to realize this.
 
@@ -1233,7 +1216,7 @@ least two empty lines, one empty line will remain visible 
after folding
 the subtree, in order to structure the collapsed view.  See the
 variable @code{org-cycle-separator-lines} to modify this behavior.
 
address@hidden Visibility cycling, Motion, Headlines, Document Structure
address@hidden Visibility cycling
 @section Visibility cycling
 @cindex cycling, visibility
 @cindex visibility cycling
@@ -1247,7 +1230,7 @@ variable @code{org-cycle-separator-lines} to modify this 
behavior.
 * Catching invisible edits::    Preventing mistakes when editing invisible 
parts
 @end menu
 
address@hidden Global and local cycling, Initial visibility, Visibility 
cycling, Visibility cycling
address@hidden Global and local cycling
 @subsection Global and local cycling
 
 Outlines make it possible to hide parts of the text in the buffer.
@@ -1299,7 +1282,7 @@ tables, @address@hidden jumps to the previous field.
 @orgcmd{C-u C-u @key{TAB},org-set-startup-visibility}
 Switch back to the startup visibility of the buffer (@pxref{Initial 
visibility}).
 @cindex show all, command
address@hidden C-u C-u @key{TAB},show-all}
address@hidden C-u C-u @key{TAB},outline-show-all}
 Show all, including drawers.
 @cindex revealing context
 @orgcmd{C-c C-r,org-reveal}
@@ -1310,37 +1293,25 @@ exposed by a sparse tree command (@pxref{Sparse trees}) 
or an agenda command
 level, all sibling headings.  With a double prefix argument, also show the
 entire subtree of the parent.
 @cindex show branches, command
address@hidden C-k,show-branches}
address@hidden C-k,outline-show-branches}
 Expose all the headings of the subtree, CONTENT view for just one subtree.
 @cindex show children, command
address@hidden @key{TAB},show-children}
address@hidden @key{TAB},outline-show-children}
 Expose all direct children of the subtree.  With a numeric prefix argument N,
 expose all children down to level address@hidden
 @orgcmd{C-c C-x b,org-tree-to-indirect-buffer}
-Show the current subtree in an indirect address@hidden indirect
-buffer
address@hidden
-(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual})
address@hidden ifinfo
address@hidden
-(see the Emacs manual for more information about indirect buffers)
address@hidden ifnotinfo
-will contain the entire buffer, but will be narrowed to the current
-tree.  Editing the indirect buffer will also change the original buffer,
-but without affecting visibility in that buffer.}.  With a numeric
-prefix argument N, go up to level N and then take that tree.  If N is
-negative then go up that many levels.  With a @kbd{C-u} prefix, do not remove
-the previously used indirect buffer.
+Show the current subtree in an indirect address@hidden indirect buffer
+(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual}) will contain the entire
+buffer, but will be narrowed to the current tree.  Editing the indirect
+buffer will also change the original buffer, but without affecting visibility
+in that buffer.}.  With a numeric prefix argument N, go up to level N and
+then take that tree.  If N is negative then go up that many levels.  With a
address@hidden prefix, do not remove the previously used indirect buffer.
 @orgcmd{C-c C-x v,org-copy-visible}
 Copy the @i{visible} text in the region into the kill ring.
 @end table
 
address@hidden
-* Initial visibility::          Setting the initial visibility state
-* Catching invisible edits::    Preventing mistakes when editing invisible 
parts
address@hidden menu
-
address@hidden Initial visibility, Catching invisible edits, Global and local 
cycling, Visibility cycling
address@hidden Initial visibility
 @subsection Initial visibility
 
 @cindex visibility, initialize
@@ -1366,14 +1337,10 @@ following lines anywhere in the buffer:
 #+STARTUP: showeverything
 @end example
 
-The startup visibility options are ignored when the file is open for the
-first time during the agenda generation: if you want the agenda to honor
-the startup visibility, set @code{org-agenda-inhibit-startup} to @code{nil}.
-
 @cindex property, VISIBILITY
 @noindent
 Furthermore, any entries with a @samp{VISIBILITY} property (@pxref{Properties
-and Columns}) will get their visibility adapted accordingly.  Allowed values
+and columns}) will get their visibility adapted accordingly.  Allowed values
 for this property are @code{folded}, @code{children}, @code{content}, and
 @code{all}.
 
@@ -1384,7 +1351,7 @@ requested by startup options and @samp{VISIBILITY} 
properties in individual
 entries.
 @end table
 
address@hidden Catching invisible edits,  , Initial visibility, Visibility 
cycling
address@hidden Catching invisible edits
 @subsection Catching invisible edits
 
 @vindex org-catch-invisible-edits
@@ -1395,7 +1362,7 @@ confused on what has been edited and how to undo the 
mistake.  Setting
 docstring of this option on how Org should catch invisible edits and process
 them.
 
address@hidden Motion, Structure editing, Visibility cycling, Document Structure
address@hidden Motion
 @section Motion
 @cindex motion, between headlines
 @cindex jumping, to headlines
@@ -1403,9 +1370,9 @@ them.
 The following commands jump to other headlines in the buffer.
 
 @table @asis
address@hidden C-n,outline-next-visible-heading}
address@hidden C-n,org-next-visible-heading}
 Next heading.
address@hidden C-p,outline-previous-visible-heading}
address@hidden C-p,org-previous-visible-heading}
 Previous heading.
 @orgcmd{C-c C-f,org-forward-same-level}
 Next heading same level.
@@ -1435,7 +1402,7 @@ q            @r{Quit}
 See also the option @code{org-goto-interface}.
 @end table
 
address@hidden Structure editing, Sparse trees, Motion, Document Structure
address@hidden Structure editing
 @section Structure editing
 @cindex structure editing
 @cindex headline, promotion and demotion
@@ -1451,24 +1418,23 @@ See also the option @code{org-goto-interface}.
 @table @asis
 @address@hidden,org-insert-heading}
 @vindex org-M-RET-may-split-line
-Insert a new heading/item with the same level than the one at point.
-If the cursor is in a plain list item, a new item is created
-(@pxref{Plain lists}).  To prevent this behavior in lists, call the
-command with a prefix argument.  When this command is used in the
-middle of a line, the line is split and the rest of the line becomes
-the new item or address@hidden you do not want the line to be
-split, customize the variable @code{org-M-RET-may-split-line}.}.  If
-the command is used at the @emph{beginning} of a headline, the new
-headline is created before the current line.  If the command is used
-at the @emph{end} of a folded subtree (i.e., behind the ellipses at
-the end of a headline), then a headline will be
-inserted after the end of the subtree.  Calling this command with
address@hidden C-u} will unconditionally respect the headline's content and
-create a new item at the end of the parent subtree.
+Insert a new heading/item with the same level as the one at point.
+
+If the command is used at the @emph{beginning} of a line, and if there is
+a heading or a plain list item (@pxref{Plain lists}) at point, the new
+heading/item is created @emph{before} the current line.  When used at the
+beginning of a regular line of text, turn that line into a heading.
+
+When this command is used in the middle of a line, the line is split and the
+rest of the line becomes the new item or headline.  If you do not want the
+line to be split, customize @code{org-M-RET-may-split-line}.
+
+Calling the command with a @kbd{C-u} prefix unconditionally inserts a new
+heading at the end of the current subtree, thus preserving its contents.
+With a double @kbd{C-u C-u} prefix, the new heading is created at the end of
+the parent subtree instead.
 @address@hidden,org-insert-heading-respect-content}
-Just like @address@hidden, except when adding a new heading below the
-current heading, the new heading is placed after the body instead of before
-it.  This command works from anywhere in the entry.
+Insert a new heading at the end of the current subtree.
 @address@hidden,org-insert-todo-heading}
 @vindex org-treat-insert-todo-heading-as-state-change
 Insert new TODO entry with same level as current heading.  See also the
@@ -1572,33 +1538,29 @@ inside a table (@pxref{Tables}), the Meta-Cursor keys 
have different
 functionality.
 
 
address@hidden Sparse trees, Plain lists, Structure editing, Document Structure
address@hidden Sparse trees
 @section Sparse trees
 @cindex sparse trees
 @cindex trees, sparse
 @cindex folding, sparse trees
 @cindex occur, command
 
address@hidden org-show-hierarchy-above
address@hidden org-show-following-heading
address@hidden org-show-siblings
address@hidden org-show-entry-below
address@hidden org-show-context-detail
 An important feature of Org mode is the ability to construct @emph{sparse
 trees} for selected information in an outline tree, so that the entire
 document is folded as much as possible, but the selected information is made
 visible along with the headline structure above address@hidden also the
-variables @code{org-show-hierarchy-above}, @code{org-show-following-heading},
address@hidden, and @code{org-show-entry-below} for detailed
-control on how much context is shown around each match.}.  Just try it out
-and you will see immediately how it works.
+variable @code{org-show-context-detail} to decide how much context is shown
+around each match.}.  Just try it out and you will see immediately how it
+works.
 
-Org mode contains several commands creating such trees, all these
+Org mode contains several commands for creating such trees, all these
 commands can be accessed through a dispatcher:
 
 @table @asis
 @orgcmd{C-c /,org-sparse-tree}
 This prompts for an extra key to select a sparse-tree creating command.
address@hidden / r,org-occur}
address@hidden / r,C-c / /,org-occur}
 @vindex org-remove-highlights-with-change
 Prompts for a regexp and shows a sparse tree with all matches.  If
 the match is in a headline, the headline is made visible.  If the match is in
@@ -1639,13 +1601,11 @@ tags, or properties and will be discussed later in this 
manual.
 @cindex printing sparse trees
 @cindex visible text, printing
 To print a sparse tree, you can use the Emacs command
address@hidden which does not print invisible parts
-of the document @footnote{This does not work under XEmacs, because
-XEmacs uses selective display for outlining, not text properties.}.
-Or you can use @kbd{C-c C-e C-v} to export only the visible part of
-the document and print the resulting file.
address@hidden which does not print invisible parts of the
+document.  Or you can use @kbd{C-c C-e C-v} to export only the visible part
+of the document and print the resulting file.
 
address@hidden Plain lists, Drawers, Sparse trees, Document Structure
address@hidden Plain lists
 @section Plain lists
 @cindex plain lists
 @cindex lists, plain
@@ -1714,25 +1674,23 @@ In that case, all items are closed.  Here is an example:
    But in the end, no individual scenes matter but the film as a whole.
    Important actors in this film are:
    - @b{Elijah Wood} :: He plays Frodo
-   - @b{Sean Austin} :: He plays Sam, Frodo's friend.  I still remember
+   - @b{Sean Astin} :: He plays Sam, Frodo's friend.  I still remember
      him very well from his role as Mikey Walsh in @i{The Goonies}.
 @end group
 @end example
 
 Org supports these lists by tuning filling and wrapping commands to deal with
-them address@hidden only changes the filling settings for Emacs.  For
-XEmacs, you should use Kyle E. Jones' @file{filladapt.el}.  To turn this on,
-put into @file{.emacs}: @code{(require 'filladapt)}}, and by exporting them
-properly (@pxref{Exporting}).  Since indentation is what governs the
-structure of these lists, many structural constructs like @code{#+BEGIN_...}
-blocks can be indented to signal that they belong to a particular item.
+them correctly, and by exporting them properly (@pxref{Exporting}).  Since
+indentation is what governs the structure of these lists, many structural
+constructs like @code{#+BEGIN_...} blocks can be indented to signal that they
+belong to a particular item.
 
 @vindex org-list-demote-modify-bullet
 @vindex org-list-indent-offset
 If you find that using a different bullet for a sub-list (than that used for
 the current list-level) improves readability, customize the variable
 @code{org-list-demote-modify-bullet}.  To get a greater difference of
-indentation between items and theirs sub-items, customize
+indentation between items and their sub-items, customize
 @code{org-list-indent-offset}.
 
 @vindex org-list-automatic-rules
@@ -1824,10 +1782,10 @@ Cycle the entire list level through the different 
itemize/enumerate bullets
 (@samp{-}, @samp{+}, @samp{*}, @samp{1.}, @samp{1)}) or a subset of them,
 depending on @code{org-plain-list-ordered-item-terminator}, the type of list,
 and its indentation.  With a numeric prefix argument N, select the Nth bullet
-from this list.  If there is an active region when calling this, selected
-text will be changed into an item.  With a prefix argument, all lines will be
-converted to list items.  If the first line already was a list item, any item
-marker will be removed from the list.  Finally, even without an active
+from this list.  If there is an active region when calling this, all selected
+lines are converted to list items.  With a prefix argument, selected text is
+changed into a single item.  If the first line already was a list item, any
+item marker will be removed from the list.  Finally, even without an active
 region, a normal line will be converted into a list item.
 @kindex C-c *
 @item C-c *
@@ -1853,20 +1811,17 @@ numerically, alphabetically, by time, by checked status 
for check lists,
 or by a custom function.
 @end table
 
address@hidden Drawers, Blocks, Plain lists, Document Structure
address@hidden Drawers
 @section Drawers
 @cindex drawers
address@hidden #+DRAWERS
 @cindex visibility cycling, drawers
 
address@hidden org-drawers
 @cindex org-insert-drawer
 @kindex C-c C-x d
 Sometimes you want to keep information associated with an entry, but you
-normally don't want to see it.  For this, Org mode has @emph{drawers}.
-Drawers need to be configured with the option @address@hidden
-can define additional drawers on a per-file basis with a line like
address@hidden: HIDDEN STATE}}.  Drawers look like this:
+normally don't want to see it.  For this, Org mode has @emph{drawers}.  They
+can contain anything but a headline and another drawer.  Drawers look like
+this:
 
 @example
 ** This is a headline
@@ -1880,18 +1835,21 @@ can define additional drawers on a per-file basis with 
a line like
 You can interactively insert drawers at point by calling
 @code{org-insert-drawer}, which is bound to @key{C-c C-x d}.  With an active
 region, this command will put the region inside the drawer.  With a prefix
-argument, this command calls @code{org-insert-property-drawer} and add a
-property drawer right below the current headline.  Completion over drawer
-keywords is also possible using @key{M-TAB}.
+argument, this command calls @code{org-insert-property-drawer} and add
+a property drawer right below the current headline.  Completion over drawer
+keywords is also possible using @address@hidden@footnote{Many desktops
+intercept @address@hidden to switch windows.  Use @kbd{C-M-i} or
address@hidden@key{ESC} @key{TAB}} instead for completion 
(@pxref{Completion}).}.
 
 Visibility cycling (@pxref{Visibility cycling}) on the headline will hide and
 show the entry, but keep the drawer collapsed to a single line.  In order to
 look inside the drawer, you need to move the cursor to the drawer line and
 press @key{TAB} there.  Org mode uses the @code{PROPERTIES} drawer for
-storing properties (@pxref{Properties and Columns}), and you can also arrange
+storing properties (@pxref{Properties and columns}), and you can also arrange
 for state change notes (@pxref{Tracking TODO state changes}) and clock times
 (@pxref{Clocking work time}) to be stored in a drawer @code{LOGBOOK}.  If you
-want to store a quick note in the LOGBOOK drawer, in a similar way to state 
changes, use
+want to store a quick note in the LOGBOOK drawer, in a similar way to state
+changes, use
 
 @table @kbd
 @kindex C-c C-z
@@ -1900,12 +1858,13 @@ Add a time-stamped note to the LOGBOOK drawer.
 @end table
 
 @vindex org-export-with-drawers
address@hidden org-export-with-properties
 You can select the name of the drawers which should be exported with
 @code{org-export-with-drawers}.  In that case, drawer contents will appear in
-export output.  Property drawers are not affected by this variable and are
-never exported.
+export output.  Property drawers are not affected by this variable: configure
address@hidden instead.
 
address@hidden Blocks, Footnotes, Drawers, Document Structure
address@hidden Blocks
 @section Blocks
 
 @vindex org-hide-block-startup
@@ -1924,18 +1883,17 @@ or on a per-file basis by using
 #+STARTUP: nohideblocks
 @end example
 
address@hidden Footnotes, Orgstruct mode, Blocks, Document Structure
address@hidden Footnotes
 @section Footnotes
 @cindex footnotes
 
-Org mode supports the creation of footnotes.  In contrast to the
address@hidden package, Org mode's footnotes are designed for work on
-a larger document, not only for one-off documents like emails.
+Org mode supports the creation of footnotes.
 
 A footnote is started by a footnote marker in square brackets in column 0, no
 indentation allowed.  It ends at the next footnote definition, headline, or
 after two consecutive empty lines.  The footnote reference is simply the
-marker in square brackets, inside text.  For example:
+marker in square brackets, inside text.  Markers always start with
address@hidden:}.  For example:
 
 @example
 The Org homepage[fn:1] now looks a lot better than it used to.
@@ -1944,23 +1902,16 @@ The Org homepage[fn:1] now looks a lot better than it 
used to.
 @end example
 
 Org mode extends the number-based syntax to @emph{named} footnotes and
-optional inline definition.  Using plain numbers as markers (as
address@hidden does) is supported for backward compatibility, but not
-encouraged because of possible conflicts with @LaTeX{} snippets 
(@pxref{Embedded
address@hidden).  Here are the valid references:
+optional inline definition.  Here are the valid references:
 
 @table @code
address@hidden [1]
-A plain numeric footnote marker.  Compatible with @file{footnote.el}, but not
-recommended because something like @samp{[1]} could easily be part of a code
-snippet.
 @item [fn:name]
 A named footnote reference, where @code{name} is a unique label word, or, for
 simplicity of automatic creation, a number.
address@hidden [fn:: This is the inline definition of this footnote]
address@hidden [fn::This is the inline definition of this footnote]
 A @LaTeX{}-like anonymous footnote where the definition is given directly at 
the
 reference point.
address@hidden [fn:name: a definition]
address@hidden [fn:name:a definition]
 An inline definition of a footnote, which also specifies a name for the note.
 Since Org allows multiple references to the same note, you can then use
 @code{[fn:name]} to create additional references.
@@ -2007,9 +1958,7 @@ r   @r{Renumber the simple @code{fn:N} footnotes.  
Automatic renumbering}
 S   @r{Short for first @code{r}, then @code{s} action.}
 n   @r{Normalize the footnotes by collecting all definitions (including}
     @r{inline definitions) into a special section, and then numbering them}
-    @r{in sequence.  The references will then also be numbers.  This is}
-    @r{meant to be the final step before finishing a document (e.g., sending}
-    @r{off an email).}
+    @r{in sequence.  The references will then also be numbers.}
 d   @r{Delete the footnote at point, and all definitions of and references}
     @r{to it.}
 @end example
@@ -2029,9 +1978,17 @@ location with a prefix argument, offer the same menu as 
@kbd{C-c C-x f}.
 @item C-c C-o  @r{or} mouse-1/2
 Footnote labels are also links to the corresponding definition/reference, and
 you can use the usual commands to follow these links.
+
address@hidden org-edit-footnote-reference
address@hidden C-c '
address@hidden C-c '
address@hidden C-c '
+Edit the footnote definition corresponding to the reference at point in
+a seperate window.  The window can be closed by pressing @kbd{C-c '}.
+
 @end table
 
address@hidden Orgstruct mode, Org syntax, Footnotes, Document Structure
address@hidden Orgstruct mode
 @section The Orgstruct minor mode
 @cindex Orgstruct mode
 @cindex minor mode for structure editing
@@ -2066,7 +2023,7 @@ Lisp files, you will be able to fold and unfold headlines 
in Emacs Lisp
 commented lines.  Some commands like @code{org-demote} are disabled when the
 prefix is set, but folding/unfolding will work correctly.
 
address@hidden Org syntax,  , Orgstruct mode, Document Structure
address@hidden Org syntax
 @section Org syntax
 @cindex Org syntax
 
@@ -2088,7 +2045,11 @@ abstract structure.  The export engine relies on the 
information stored in
 this list.  Most interactive commands (e.g., for structure editing) also
 rely on the syntactic meaning of the surrounding context.
 
address@hidden Tables, Hyperlinks, Document Structure, Top
address@hidden syntax checker
address@hidden linter
+You can check syntax in your documents using @code{org-lint} command.
+
address@hidden Tables
 @chapter Tables
 @cindex tables
 @cindex editing tables
@@ -2106,7 +2067,7 @@ calculations are supported using the Emacs @file{calc} 
package
 * Org-Plot::                    Plotting from org tables
 @end menu
 
address@hidden Built-in table editor, Column width and alignment, Tables, Tables
address@hidden Built-in table editor
 @section The built-in table editor
 @cindex table editor, built-in
 
@@ -2155,12 +2116,13 @@ unpredictable for you, configure the options
 @table @kbd
 @tsubheading{Creation and conversion}
 @orgcmd{C-c |,org-table-create-or-convert-from-region}
-Convert the active region to table.  If every line contains at least one
+Convert the active region to a table.  If every line contains at least one
 TAB character, the function assumes that the material is tab separated.
 If every line contains a comma, comma-separated values (CSV) are assumed.
 If not, lines are split at whitespace into fields.  You can use a prefix
 argument to force a specific separator: @kbd{C-u} forces CSV, @kbd{C-u
-C-u} forces TAB, and a numeric argument N indicates that at least N
+C-u} forces TAB, @kbd{C-u C-u C-u} will prompt for a regular expression to
+match the separator, and a numeric argument N indicates that at least N
 consecutive spaces, or alternatively a TAB will be the separator.
 @*
 If there is no active region, this command creates an empty Org
@@ -2171,7 +2133,10 @@ table.  But it is easier just to start typing, like
 @orgcmd{C-c C-c,org-table-align}
 Re-align the table and don't move to another field.
 @c
address@hidden<TAB>,org-table-next-field}
address@hidden SPC,org-table-blank-field}
+Blank the field at point.
address@hidden
address@hidden,org-table-next-field}
 Re-align the table, move to the next field.  Creates a new row if
 necessary.
 @c
@@ -2224,8 +2189,10 @@ point is before the first column, you will be prompted 
for the sorting
 column.  If there is an active region, the mark specifies the first line
 and the sorting column, while point should be in the last line to be
 included into the sorting.  The command prompts for the sorting type
-(alphabetically, numerically, or by time).  When called with a prefix
-argument, alphabetic sorting will be case-sensitive.
+(alphabetically, numerically, or by time).  You can sort in normal or
+reverse order.  You can also supply your own key extraction and comparison
+functions.  When called with a prefix argument, alphabetic sorting will be
+case-sensitive.
 
 @tsubheading{Regions}
 @orgcmd{C-c C-x M-w,org-table-copy-region}
@@ -2322,7 +2289,7 @@ it off with
 @noindent Then the only table command that still works is
 @kbd{C-c C-c} to do a manual re-align.
 
address@hidden Column width and alignment, Column groups, Built-in table 
editor, Tables
address@hidden Column width and alignment
 @section Column width and alignment
 @cindex narrow columns in tables
 @cindex alignment in tables
@@ -2333,11 +2300,11 @@ of number-like versus non-number fields in the column.
 
 Sometimes a single field or a few fields need to carry more text, leading to
 inconveniently wide columns.  Or maybe you want to make a table with several
-columns having a fixed width, regardless of content.  To address@hidden
-feature does not work on XEmacs.} the width of a column, one field anywhere
-in the column may contain just the string @samp{<N>} where @samp{N} is an
-integer specifying the width of the column in characters.  The next re-align
-will then set the width of this column to this value.
+columns having a fixed width, regardless of content.  To set the width of
+a column, one field anywhere in the column may contain just the string
address@hidden<N>} where @samp{N} is an integer specifying the width of the 
column in
+characters.  The next re-align will then set the width of this column to this
+value.
 
 @example
 @group
@@ -2374,7 +2341,7 @@ on a per-file basis with:
 @end example
 
 If you would like to overrule the automatic alignment of number-rich columns
-to the right and of string-rich column to the left, you can use @samp{<r>},
+to the right and of string-rich columns to the left, you can use @samp{<r>},
 @samp{<c>address@hidden does not work inside Emacs, but it does have an
 effect when exporting to HTML.} or @samp{<l>} in a similar fashion.  You may
 also combine alignment and field width like this: @samp{<r10>}.
@@ -2382,30 +2349,29 @@ also combine alignment and field width like this: 
@samp{<r10>}.
 Lines which only contain these formatting cookies will be removed
 automatically when exporting the document.
 
address@hidden Column groups, Orgtbl mode, Column width and alignment, Tables
address@hidden Column groups
 @section Column groups
 @cindex grouping columns in tables
 
-When Org exports tables, it does so by default without vertical
-lines because that is visually more satisfying in general.  Occasionally
-however, vertical lines can be useful to structure a table into groups
-of columns, much like horizontal lines can do for groups of rows.  In
-order to specify column groups, you can use a special row where the
-first field contains only @samp{/}.  The further fields can either
-contain @samp{<} to indicate that this column should start a group,
address@hidden>} to indicate the end of a column, or @samp{<>} (no space 
between @samp{<}
-and @samp{>}) to make a column
-a group of its own.  Boundaries between column groups will upon export be
-marked with vertical lines.  Here is an example:
-
address@hidden
-| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
-|---+-----+-----+-----+---------+------------|
-| / |   < |     |   > |       < |          > |
-| 1 |   1 |   1 |   1 |       1 |          1 |
-| 2 |   4 |   8 |  16 |  1.4142 |     1.1892 |
-| 3 |   9 |  27 |  81 |  1.7321 |     1.3161 |
-|---+-----+-----+-----+---------+------------|
+When Org exports tables, it does so by default without vertical lines because
+that is visually more satisfying in general.  Occasionally however, vertical
+lines can be useful to structure a table into groups of columns, much like
+horizontal lines can do for groups of rows.  In order to specify column
+groups, you can use a special row where the first field contains only
address@hidden/}.  The further fields can either contain @samp{<} to indicate 
that
+this column should start a group, @samp{>} to indicate the end of a group, or
address@hidden<>} (no space between @samp{<} and @samp{>}) to make a column a 
group
+of its own.  Boundaries between column groups will upon export be marked with
+vertical lines.  Here is an example:
+
address@hidden
+| N | N^2 | N^3 | N^4 | ~sqrt(n)~ | ~sqrt[4](N)~ |
+|---+-----+-----+-----+-----------+--------------|
+| / |   < |     |   > |         < |            > |
+| 1 |   1 |   1 |   1 |         1 |            1 |
+| 2 |   4 |   8 |  16 |    1.4142 |       1.1892 |
+| 3 |   9 |  27 |  81 |    1.7321 |       1.3161 |
+|---+-----+-----+-----+-----------+--------------|
 #+TBLFM: $2=$1^2::$3=$1^3::$4=$1^4::$5=sqrt($1)::$6=sqrt(sqrt(($1)))
 @end example
 
@@ -2418,7 +2384,7 @@ every vertical line you would like to have:
 | /  | <   |     |     | <       |            |
 @end example
 
address@hidden Orgtbl mode, The spreadsheet, Column groups, Tables
address@hidden Orgtbl mode
 @section The Orgtbl minor mode
 @cindex Orgtbl mode
 @cindex minor mode for tables
@@ -2439,7 +2405,7 @@ construct @LaTeX{} tables with the underlying ease and 
power of
 Orgtbl mode, including spreadsheet capabilities.  For details, see
 @ref{Tables in arbitrary syntax}.
 
address@hidden The spreadsheet, Org-Plot, Orgtbl mode, Tables
address@hidden The spreadsheet
 @section The spreadsheet
 @cindex calculations, in tables
 @cindex spreadsheet capabilities
@@ -2468,7 +2434,7 @@ formula, moving these references by arrow keys
 * Advanced features::           Field and column names, parameters and 
automatic recalc
 @end menu
 
address@hidden References, Formula syntax for Calc, The spreadsheet, The 
spreadsheet
address@hidden References
 @subsection References
 @cindex references
 
@@ -2554,7 +2520,7 @@ format at least for the first field (i.e the reference 
must start with
 @example
 $1..$3        @r{first three fields in the current row}
 $P..$Q        @r{range, using column names (see under Advanced)}
-$<<<..$>>     @r{start in third column, continue to the one but last}
+$<<<..$>>     @r{start in third column, continue to the last but one}
 @@2$1..@@4$3    @r{6 fields between these two fields (same as @code{A2..C4})}
 @@-1$-2..@@-1   @r{3 fields in the row above, starting from 2 columns on the 
left}
 @@I..II        @r{between first and second hline, short for @code{@@I..@@II}}
@@ -2572,21 +2538,28 @@ for Calc}.
 @cindex row, of field coordinates
 @cindex column, of field coordinates
 
-For Calc formulas and Lisp formulas @code{@@#} and @code{$#} can be used to
-get the row or column number of the field where the formula result goes.
-The traditional Lisp formula equivalents are @code{org-table-current-dline}
-and @code{org-table-current-column}.  Examples:
+One of the very first actions during evaluation of Calc formulas and Lisp
+formulas is to substitute @code{@@#} and @code{$#} in the formula with the
+row or column number of the field where the current result will go to.  The
+traditional Lisp formula equivalents are @code{org-table-current-dline} and
address@hidden  Examples:
 
address@hidden
-if(@@# % 2, $#, string(""))   @r{column number on odd lines only}
-$3 = remote(FOO, @@@@#$2)      @r{copy column 2 from table FOO into}
-                             @r{column 3 of the current table}
address@hidden example
address@hidden @code
address@hidden if(@@# % 2, $#, string(""))
+Insert column number on odd rows, set field to empty on even rows.
address@hidden $2 = '(identity remote(FOO, @@@@#$1))
+Copy text or values of each row of column 1 of the table named @code{FOO}
+into column 2 of the current table.
address@hidden @@3 = 2 * remote(FOO, @@1$$#)
+Insert the doubled value of each column of row 1 of the table named
address@hidden into row 3 of the current table.
address@hidden table
 
address@hidden For the second example, table FOO must have at least as many rows
-as the current table.  Note that this is address@hidden computation time 
scales as
-O(N^2) because table FOO is parsed for each field to be copied.} for large
-number of rows.
address@hidden For the second/third example, the table named @code{FOO} must 
have
+at least as many rows/columns as the current table.  Note that this is
address@hidden computation time scales as O(N^2) because the table
+named @code{FOO} is parsed for each field to be read.} for large number of
+rows/columns.
 
 @subsubheading Named references
 @cindex named references
@@ -2608,7 +2581,7 @@ line like
 @noindent
 @vindex constants-unit-system
 @pindex constants.el
-Also properties (@pxref{Properties and Columns}) can be used as
+Also properties (@pxref{Properties and columns}) can be used as
 constants in table formulas: for a property @samp{:Xyz:} use the name
 @samp{$PROP_Xyz}, and the property will be searched in the current
 outline entry and in the hierarchy above it.  If you have the
@@ -2647,7 +2620,13 @@ table in that entry.  REF is an absolute field or range 
reference as
 described above for example @code{@@3$3} or @code{$somename}, valid in the
 referenced table.
 
address@hidden Formula syntax for Calc, Formula syntax for Lisp, References, 
The spreadsheet
+Indirection of NAME-OR-ID: When NAME-OR-ID has the format @code{@@ROW$COLUMN}
+it will be substituted with the name or ID found in this field of the current
+table.  For example @code{remote($1, @@>$2)} => @code{remote(year_2013,
+@@>$1)}.  The format @code{B3} is not supported because it can not be
+distinguished from a plain table name or ID.
+
address@hidden Formula syntax for Calc
 @subsection Formula syntax for Calc
 @cindex formula syntax, Calc
 @cindex syntax, of formulas
@@ -2762,7 +2741,7 @@ should be padded with 0 to the full size.
 You can add your own Calc functions defined in Emacs Lisp with @code{defmath}
 and use them in formula syntax for Calc.
 
address@hidden Formula syntax for Lisp, Durations and time values, Formula 
syntax for Calc, The spreadsheet
address@hidden Formula syntax for Lisp
 @subsection Emacs Lisp forms as formulas
 @cindex Lisp forms, as table formulas
 
@@ -2798,7 +2777,7 @@ Add columns 1 and 2, equivalent to Calc's @code{$1+$2}.
 Compute the sum of columns 1 to 4, like Calc's @code{vsum($1..$4)}.
 @end table
 
address@hidden Durations and time values, Field and range formulas, Formula 
syntax for Lisp, The spreadsheet
address@hidden Durations and time values
 @subsection Durations and time values
 @cindex Duration, computing
 @cindex Time, computing
@@ -2817,7 +2796,7 @@ formulas or Elisp formulas:
 @end group
 @end example
 
-Input duration values must be of the form @code{[HH:MM[:SS]}, where seconds
+Input duration values must be of the form @code{HH:MM[:SS]}, where seconds
 are optional.  With the @code{T} flag, computed durations will be displayed
 as @code{HH:MM:SS} (see the first formula above).  With the @code{t} flag,
 computed durations will be displayed according to the value of the option
@@ -2828,7 +2807,7 @@ example above).
 Negative duration values can be manipulated as well, and integers will be
 considered as seconds in addition and subtraction.
 
address@hidden Field and range formulas, Column formulas, Durations and time 
values, The spreadsheet
address@hidden Field and range formulas
 @subsection Field and range formulas
 @cindex field formula
 @cindex range formula
@@ -2845,13 +2824,13 @@ current field will be replaced with the result.
 Formulas are stored in a special line starting with @samp{#+TBLFM:} directly
 below the table.  If you type the equation in the 4th field of the 3rd data
 line in the table, the formula will look like @samp{@@3$4=$1+$2}.  When
-inserting/deleting/swapping column and rows with the appropriate commands,
+inserting/deleting/swapping columns and rows with the appropriate commands,
 @i{absolute references} (but not relative ones) in stored formulas are
-modified in order to still reference the same field.  To avoid this from
-happening, in particular in range references, anchor ranges at the table
-borders (using @code{@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines
-using the @code{@@I} notation.  Automatic adaptation of field references does
-of course not happen if you edit the table structure with normal editing
+modified in order to still reference the same field.  To avoid this, in
+particular in range references, anchor ranges at the table borders (using
address@hidden@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines using the
address@hidden@@I} notation.  Automatic adaptation of field references does of 
course
+not happen if you edit the table structure with normal editing
 commands---then you must fix the equations yourself.
 
 Instead of typing an equation into the field, you may also use the following
@@ -2884,7 +2863,7 @@ can also be used to assign a formula to some but not all 
fields in a row.
 Named field, see @ref{Advanced features}.
 @end table
 
address@hidden Column formulas, Lookup functions, Field and range formulas, The 
spreadsheet
address@hidden Column formulas
 @subsection Column formulas
 @cindex column formula
 @cindex formula, for table column
@@ -2908,7 +2887,7 @@ and the current field replaced with the result.  If the 
field contains only
 @samp{=}, the previously stored formula for this column is used.  For each
 column, Org will only remember the most recently used formula.  In the
 @samp{#+TBLFM:} line, column formulas will look like @samp{$4=$1+$2}.  The
-left-hand side of a column formula can not be the name of column, it must be
+left-hand side of a column formula cannot be the name of column, it must be
 the numeric column reference or @code{$>}.
 
 Instead of typing an equation into the field, you may also use the
@@ -2923,7 +2902,7 @@ stores it.  With a numeric prefix argument(e.g., @kbd{C-5 
C-c =}) the command
 will apply it to that many consecutive fields in the current column.
 @end table
 
address@hidden Lookup functions, Editing and debugging formulas, Column 
formulas, The spreadsheet
address@hidden Lookup functions
 @subsection Lookup functions
 @cindex lookup functions in tables
 @cindex table lookup functions
@@ -2967,7 +2946,7 @@ matching cells, rank results, group data etc.  For 
practical examples
 see @uref{http://orgmode.org/worg/org-tutorials/org-lookups.html, this
 tutorial on Worg}.
 
address@hidden Editing and debugging formulas, Updating the table, Lookup 
functions, The spreadsheet
address@hidden Editing and debugging formulas
 @subsection Editing and debugging formulas
 @cindex formula editing
 @cindex editing, of table formulas
@@ -3026,7 +3005,9 @@ a Lisp formula, format the formula according to Emacs 
Lisp rules.
 Another @key{TAB} collapses the formula back again.  In the open
 formula, @key{TAB} re-indents just like in Emacs Lisp mode.
 @address@hidden,lisp-complete-symbol}
-Complete Lisp symbols, just like in Emacs Lisp mode.
+Complete Lisp symbols, just like in Emacs Lisp address@hidden desktops
+intercept @address@hidden to switch windows.  Use @kbd{C-M-i} or
address@hidden@key{ESC} @key{TAB}} instead for completion (@pxref{Completion}).}
 @kindex address@hidden
 @kindex address@hidden
 @kindex address@hidden
@@ -3118,7 +3099,7 @@ turn on formula debugging in the @code{Tbl} menu and 
repeat the
 calculation, for example by pressing @kbd{C-u C-u C-c = @key{RET}} in a
 field.  Detailed information will be displayed.
 
address@hidden Updating the table, Advanced features, Editing and debugging 
formulas, The spreadsheet
address@hidden Updating the table
 @subsection Updating the table
 @cindex recomputing table fields
 @cindex updating, table
@@ -3155,7 +3136,7 @@ Iterate all tables in the current buffer, in order to 
converge table-to-table
 dependencies.
 @end table
 
address@hidden Advanced features,  , Updating the table, The spreadsheet
address@hidden Advanced features
 @subsection Advanced features
 
 If you want the recalculation of fields to happen automatically, or if you
@@ -3260,17 +3241,23 @@ functions.
 @end group
 @end example
 
address@hidden Org-Plot,  , The spreadsheet, Tables
address@hidden Org-Plot
 @section Org-Plot
 @cindex graph, in tables
 @cindex plot tables using Gnuplot
 @cindex #+PLOT
 
-Org-Plot can produce 2D and 3D graphs of information stored in org tables
-using @file{Gnuplot} @uref{http://www.gnuplot.info/} and @file{gnuplot-mode}
+Org-Plot can produce graphs of information stored in org tables, either
+graphically or in ASCII-art.
+
address@hidden Graphical plots using @file{Gnuplot}
+
+Org-Plot produces 2D and 3D graphs using @file{Gnuplot}
address@hidden://www.gnuplot.info/} and @file{gnuplot-mode}
 @uref{http://xafs.org/BruceRavel/GnuplotMode}.  To see this in action, ensure
 that you have both Gnuplot and Gnuplot mode installed on your system, then
-call @code{org-plot/gnuplot} on the following table.
+call @kbd{C-c " g} or @kbd{M-x org-plot/gnuplot @key{RET}} on the following
+table.
 
 @example
 @group
@@ -3288,8 +3275,8 @@ call @code{org-plot/gnuplot} on the following table.
 Notice that Org Plot is smart enough to apply the table's headers as labels.
 Further control over the labels, type, content, and appearance of plots can
 be exercised through the @code{#+PLOT:} lines preceding a table.  See below
-for a complete list of Org-plot options.  For more information and examples
-see the Org-plot tutorial at
+for a complete list of Org-plot options.  The @code{#+PLOT:} lines are
+optional.  For more information and examples see the Org-plot tutorial at
 @uref{http://orgmode.org/worg/org-tutorials/org-plot.html}.
 
 @subsubheading Plot Options
@@ -3345,7 +3332,48 @@ may still want to specify the plot type, as that can 
impact the content of
 the data file.
 @end table
 
address@hidden Hyperlinks, TODO Items, Tables, Top
address@hidden ASCII bar plots
+
+While the cursor is on a column, typing @kbd{C-c " a} or
address@hidden orgtbl-ascii-plot @key{RET}} create a new column containing an
+ASCII-art bars plot.  The plot is implemented through a regular column
+formula.  When the source column changes, the bar plot may be updated by
+refreshing the table, for example typing @kbd{C-u C-c *}.
+
address@hidden
address@hidden
+| Sede          | Max cites |              |
+|---------------+-----------+--------------|
+| Chile         |    257.72 | WWWWWWWWWWWW |
+| Leeds         |    165.77 | WWWWWWWh     |
+| Sao Paolo     |     71.00 | WWW;         |
+| Stockholm     |    134.19 | WWWWWW:      |
+| Morelia       |    257.56 | WWWWWWWWWWWH |
+| Rochefourchat |      0.00 |              |
+#+TBLFM: $3='(orgtbl-ascii-draw $2 0.0 257.72 12)
address@hidden group
address@hidden example
+
+The formula is an elisp call:
address@hidden
+(orgtbl-ascii-draw COLUMN MIN MAX WIDTH)
address@hidden lisp
+
address@hidden @code
address@hidden COLUMN
+  is a reference to the source column.
+
address@hidden MIN MAX
+  are the minimal and maximal values displayed.  Sources values
+  outside this range are displayed as @samp{too small}
+  or @samp{too large}.
+
address@hidden WIDTH
+  is the width in characters of the bar-plot.  It defaults to @samp{12}.
+
address@hidden table
+
address@hidden Hyperlinks
 @chapter Hyperlinks
 @cindex hyperlinks
 
@@ -3363,7 +3391,7 @@ other files, Usenet articles, emails, and much more.
 * Custom searches::             When the default search is not enough
 @end menu
 
address@hidden Link format, Internal links, Hyperlinks, Hyperlinks
address@hidden Link format
 @section Link format
 @cindex link format
 @cindex format, of links
@@ -3394,7 +3422,7 @@ missing bracket hides the link internals again.  To show 
the
 internal structure of all links, use the menu entry
 @code{Org->Hyperlinks->Literal links}.
 
address@hidden Internal links, External links, Link format, Hyperlinks
address@hidden Internal links
 @section Internal links
 @cindex internal links
 @cindex links, internal
@@ -3419,8 +3447,8 @@ a @i{dedicated target}: the same string in double angular 
brackets, like
 @cindex #+NAME
 If no dedicated target exists, the link will then try to match the exact name
 of an element within the buffer.  Naming is done with the @code{#+NAME}
-keyword, which has to be put the line before the element it refers to, as in
-the following example
+keyword, which has to be put in the line before the element it refers to, as
+in the following example
 
 @example
 #+NAME: My Target
@@ -3465,7 +3493,7 @@ earlier.
 * Radio targets::               Make targets trigger links in plain text
 @end menu
 
address@hidden Radio targets,  , Internal links, Internal links
address@hidden Radio targets
 @subsection Radio targets
 @cindex radio targets
 @cindex targets, radio
@@ -3481,7 +3509,7 @@ for radio targets only when the file is first loaded into 
Emacs.  To
 update the target list during editing, press @kbd{C-c C-c} with the
 cursor on or at a target.
 
address@hidden External links, Handling links, Internal links, Hyperlinks
address@hidden External links
 @section External links
 @cindex links, external
 @cindex external links
@@ -3504,42 +3532,44 @@ string followed by a colon.  There can be no space 
after the colon.  The
 following list shows examples for each link type.
 
 @example
-http://www.astro.uva.nl/~dominik          @r{on the web}
-doi:10.1000/182                           @r{DOI for an electronic resource}
-file:/home/dominik/images/jupiter.jpg     @r{file, absolute path}
-/home/dominik/images/jupiter.jpg          @r{same as above}
-file:papers/last.pdf                      @r{file, relative path}
-./papers/last.pdf                         @r{same as above}
-file:/myself@@some.where:papers/last.pdf   @r{file, path on remote machine}
-/myself@@some.where:papers/last.pdf        @r{same as above}
-file:sometextfile::NNN                    @r{file, jump to line number}
-file:projects.org                         @r{another Org file}
-file:projects.org::some words             @r{text search in Org address@hidden
+http://www.astro.uva.nl/~dominik             @r{on the web}
+doi:10.1000/182                              @r{DOI for an electronic resource}
+file:/home/dominik/images/jupiter.jpg        @r{file, absolute path}
+/home/dominik/images/jupiter.jpg             @r{same as above}
+file:papers/last.pdf                         @r{file, relative path}
+./papers/last.pdf                            @r{same as above}
+file:/ssh:myself@@some.where:papers/last.pdf  @r{file, path on remote machine}
+/ssh:myself@@some.where:papers/last.pdf       @r{same as above}
+file:sometextfile::NNN                       @r{file, jump to line number}
+file:projects.org                            @r{another Org file}
+file:projects.org::some words                @r{text search in Org 
address@hidden
 The actual behavior of the search will depend on the value of
 the option @code{org-link-search-must-match-exact-headline}.  If its value
-is @code{nil}, then a fuzzy text search will be done.  If it is t, then only 
the
-exact headline will be matched.  If the value is @code{'query-to-create},
-then an exact headline will be searched; if it is not found, then the user
-will be queried to create it.}
-file:projects.org::*task title            @r{heading search in Org file}
-file+sys:/path/to/file                    @r{open via OS, like double-click}
-file+emacs:/path/to/file                  @r{force opening by Emacs}
-docview:papers/last.pdf::NNN              @r{open in doc-view mode at page}
-id:B7423F4D-2E8A-471B-8810-C40F074717E9   @r{Link to heading by ID}
-news:comp.emacs                           @r{Usenet link}
-mailto:adent@@galaxy.net                   @r{Mail link}
-mhe:folder                                @r{MH-E folder link}
-mhe:folder#id                             @r{MH-E message link}
-rmail:folder                              @r{RMAIL folder link}
-rmail:folder#id                           @r{RMAIL message link}
-gnus:group                                @r{Gnus group link}
-gnus:group#id                             @r{Gnus article link}
-bbdb:R.*Stallman                          @r{BBDB link (with regexp)}
-irc:/irc.com/#emacs/bob                   @r{IRC link}
-info:org#External links                   @r{Info node link}
-shell:ls *.org                            @r{A shell command}
-elisp:org-agenda                          @r{Interactive Elisp command}
-elisp:(find-file-other-frame "Elisp.org") @r{Elisp form to evaluate}
+is @code{nil}, then a fuzzy text search will be done.  If it is @code{t}, then 
only
+the exact headline will be matched, ignoring spaces and cookies.  If the
+value is @code{query-to-create}, then an exact headline will be searched; if
+it is not found, then the user will be queried to create it.}
+file:projects.org::*task title               @r{heading search in Org 
address@hidden
+Headline searches always match the exact headline, ignoring
+spaces and cookies.  If the headline is not found and the value of the option
address@hidden is @code{query-to-create},
+then the user will be queried to create it.}
+docview:papers/last.pdf::NNN                 @r{open in doc-view mode at page}
+id:B7423F4D-2E8A-471B-8810-C40F074717E9      @r{Link to heading by ID}
+news:comp.emacs                              @r{Usenet link}
+mailto:adent@@galaxy.net                      @r{Mail link}
+mhe:folder                                   @r{MH-E folder link}
+mhe:folder#id                                @r{MH-E message link}
+rmail:folder                                 @r{RMAIL folder link}
+rmail:folder#id                              @r{RMAIL message link}
+gnus:group                                   @r{Gnus group link}
+gnus:group#id                                @r{Gnus article link}
+bbdb:R.*Stallman                             @r{BBDB link (with regexp)}
+irc:/irc.com/#emacs/bob                      @r{IRC link}
+info:org#External links                      @r{Info node or index link}
+shell:ls *.org                               @r{A shell command}
+elisp:org-agenda                             @r{Interactive Elisp command}
+elisp:(find-file-other-frame "Elisp.org")    @r{Elisp form to evaluate}
 @end example
 
 @cindex VM links
@@ -3550,13 +3580,13 @@ to VM or Wanderlust messages are available when you 
load the corresponding
 libraries from the @code{contrib/} directory:
 
 @example
-vm:folder                                 @r{VM folder link}
-vm:folder#id                              @r{VM message link}
-vm://myself@@some.where.org/folder#id      @r{VM on remote machine}
-vm-imap:account:folder                    @r{VM IMAP folder link}
-vm-imap:account:folder#id                 @r{VM IMAP message link}
-wl:folder                                 @r{WANDERLUST folder link}
-wl:folder#id                              @r{WANDERLUST message link}
+vm:folder                                    @r{VM folder link}
+vm:folder#id                                 @r{VM message link}
+vm://myself@@some.where.org/folder#id         @r{VM on remote machine}
+vm-imap:account:folder                       @r{VM IMAP folder link}
+vm-imap:account:folder#id                    @r{VM IMAP message link}
+wl:folder                                    @r{WANDERLUST folder link}
+wl:folder#id                                 @r{WANDERLUST message link}
 @end example
 
 For customizing Org to add new link types @ref{Adding hyperlink types}.
@@ -3582,7 +3612,7 @@ as links.  If spaces must be part of the link (for 
example in
 @samp{bbdb:Richard Stallman}), or if you need to remove ambiguities
 about the end of the link, enclose them in square brackets.
 
address@hidden Handling links, Using links outside Org, External links, 
Hyperlinks
address@hidden Handling links
 @section Handling links
 @cindex links, handling
 
@@ -3614,9 +3644,9 @@ will be stored.  In addition or alternatively (depending 
on the value of
 be created and/or used to construct a address@hidden library
 @file{org-id.el} must first be loaded, either through @code{org-customize} by
 enabling @code{org-id} in @code{org-modules}, or by adding @code{(require
-'org-id)} in your @file{.emacs}.}. So using this command in Org buffers will
-potentially create two links: a human-readable from the custom ID, and one
-that is globally unique and works even if the entry is moved from file to
+'org-id)} in your Emacs init file.}.  So using this command in Org buffers
+will potentially create two links: a human-readable from the custom ID, and
+one that is globally unique and works even if the entry is moved from file to
 file.  Later, when inserting the link, you need to decide which one to use.
 
 @b{Email/News clients: VM, Rmail, Wanderlust, MH-E, address@hidden
@@ -3624,7 +3654,7 @@ Pretty much all Emacs mail clients are supported.  The 
link will point to the
 current article, or, in some GNUS buffers, to the group.  The description is
 constructed from the author and the subject.
 
address@hidden browsers: W3 and address@hidden
address@hidden browsers: Eww, W3 and address@hidden
 Here the link will be the current URL, with the page title as description.
 
 @b{Contacts: address@hidden
@@ -3656,7 +3686,8 @@ entry referenced by the current line.
 @cindex completion, of links
 @cindex inserting links
 @vindex org-keep-stored-link-after-insertion
-Insert a address@hidden Note that you don't have to use this command to
address@hidden org-link-parameters
+Insert a address@hidden that you don't have to use this command to
 insert a link.  Links in Org are plain text, and you can type or paste them
 straight into the buffer.  By using this command, the links are automatically
 enclosed in double brackets, and you will be asked for the optional
@@ -3679,11 +3710,12 @@ them with @key{up} and @key{down} (or @kbd{M-p/n}).
 valid link prefixes like @samp{http:} or @samp{ftp:}, including the prefixes
 defined through link abbreviations (@pxref{Link abbreviations}).  If you
 press @key{RET} after inserting only the @var{prefix}, Org will offer
-specific completion support for some link address@hidden works by
-calling a special function @code{org-PREFIX-complete-link}.}  For
-example, if you type @kbd{file @key{RET}}, file name completion (alternative
-access: @kbd{C-u C-c C-l}, see below) will be offered, and after @kbd{bbdb
address@hidden you can complete contact names.
+specific completion support for some link address@hidden works if
+a completion function is defined in the @samp{:complete} property of a link
+in @code{org-link-parameters}.}  For example, if you type @kbd{file
address@hidden, file name completion (alternative access: @kbd{C-u C-c C-l}, see
+below) will be offered, and after @kbd{bbdb @key{RET}} you can complete
+contact names.
 @orgkey C-u C-c C-l
 @cindex file name completion
 @cindex completion, of file names
@@ -3729,8 +3761,8 @@ the link at point.
 @kindex mouse-1
 @item mouse-2
 @itemx mouse-1
-On links, @kbd{mouse-2} will open the link just as @kbd{C-c C-o}
-would.  Under Emacs 22 and later, @kbd{mouse-1} will also follow a link.
+On links, @kbd{mouse-1} and @kbd{mouse-2} will open the link just as @kbd{C-c
+C-o} would.
 @c
 @kindex mouse-3
 @item mouse-3
@@ -3778,7 +3810,7 @@ to @kbd{C-n} and @kbd{C-p}
 @end lisp
 @end table
 
address@hidden Using links outside Org, Link abbreviations, Handling links, 
Hyperlinks
address@hidden Using links outside Org
 @section Using links outside Org
 
 You can insert and follow links that have Org syntax not only in
@@ -3791,7 +3823,7 @@ yourself):
 (global-set-key "\C-c o" 'org-open-at-point-global)
 @end lisp
 
address@hidden Link abbreviations, Search options, Using links outside Org, 
Hyperlinks
address@hidden Link abbreviations
 @section Link abbreviations
 @cindex link abbreviations
 @cindex abbreviation, links
@@ -3830,8 +3862,8 @@ url-encode the tag (see the example above, where we need 
to encode
 the URL parameter.)  Using @samp{%(my-function)} will pass the tag
 to a custom function, and replace it by the resulting string.
 
-If the replacement text don't contain any specifier, it will simply
-be appended to the string in order to create the link.
+If the replacement text doesn't contain any specifier, the tag will simply be
+appended in order to create the link.
 
 Instead of a string, you may also specify a function that will be
 called with the tag as the only argument to create the link.
@@ -3855,12 +3887,17 @@ can define them in the file with
 
 @noindent
 In-buffer completion (@pxref{Completion}) can be used after @samp{[} to
-complete link abbreviations.  You may also define a function
address@hidden that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
+complete link abbreviations.  You may also define a function that implements
+special (e.g., completion) support for inserting such a link with @kbd{C-c
+C-l}.  Such a function should not accept any arguments, and return the full
+link with prefix.  You can add a completion function to a link like this:
+
address@hidden
+(org-link-set-parameters ``type'' :complete #'some-function)
address@hidden lisp
+
 
address@hidden Search options, Custom searches, Link abbreviations, Hyperlinks
address@hidden Search options
 @section Search options in file links
 @cindex search option in file links
 @cindex file links, searching
@@ -3912,7 +3949,7 @@ to search the current file.  For example, 
@code{[[file:::find me]]} does
 a search for @samp{find me} in the current file, just as
 @samp{[[find me]]} would.
 
address@hidden Custom searches,  , Search options, Hyperlinks
address@hidden Custom searches
 @section Custom Searches
 @cindex custom search strings
 @cindex search strings, custom
@@ -3936,7 +3973,7 @@ variables for more information.  Org actually uses this 
mechanism
 for address@hidden database files, and you can use the corresponding code as
 an implementation example.  See the file @file{org-bibtex.el}.
 
address@hidden TODO Items, Tags, Hyperlinks, Top
address@hidden TODO items
 @chapter TODO items
 @cindex TODO items
 
@@ -3961,7 +3998,7 @@ methods to give you an overview of all the things that 
you have to do.
 * Checkboxes::                  Tick-off lists
 @end menu
 
address@hidden TODO basics, TODO extensions, TODO Items, TODO Items
address@hidden TODO basics
 @section Basic TODO functionality
 
 Any headline becomes a TODO item when it starts with the word
@@ -4022,7 +4059,7 @@ N, show the tree for the Nth keyword in the option 
@code{org-todo-keywords}.
 With two prefix arguments, find all TODO states, both un-done and done.
 @orgcmd{C-c a t,org-todo-list}
 Show the global TODO list.  Collects the TODO items (with not-DONE states)
-from all agenda files (@pxref{Agenda Views}) into a single buffer.  The new
+from all agenda files (@pxref{Agenda views}) into a single buffer.  The new
 buffer will be in @code{agenda-mode}, which provides commands to examine and
 manipulate the TODO entries from the new buffer (@pxref{Agenda commands}).
 @xref{Global TODO list}, for more information.
@@ -4035,7 +4072,7 @@ Insert a new TODO entry below the current one.
 Changing a TODO state can also trigger tag changes.  See the docstring of the
 option @code{org-todo-state-tags-triggers} for details.
 
address@hidden TODO extensions, Progress logging, TODO basics, TODO Items
address@hidden TODO extensions
 @section Extended use of TODO keywords
 @cindex extended TODO keywords
 
@@ -4059,7 +4096,7 @@ TODO items in particular (@pxref{Tags}).
 * TODO dependencies::           When one task needs to wait for others
 @end menu
 
address@hidden Workflow states, TODO types, TODO extensions, TODO extensions
address@hidden Workflow states
 @subsection TODO keywords as workflow states
 @cindex TODO workflow
 @cindex workflow states as TODO keywords
@@ -4090,7 +4127,7 @@ define many keywords, you can use in-buffer completion
 buffer.  Changing a TODO state can be logged with a timestamp, see
 @ref{Tracking TODO state changes}, for more information.
 
address@hidden TODO types, Multiple sets in one file, Workflow states, TODO 
extensions
address@hidden TODO types
 @subsection TODO keywords as types
 @cindex TODO types
 @cindex names as TODO keywords
@@ -4122,7 +4159,7 @@ Lucy has to do, you would use @kbd{C-3 C-c / t}.  To 
collect Lucy's items
 from all agenda files into a single buffer, you would use the numeric prefix
 argument as well when creating the global TODO list: @kbd{C-3 C-c a t}.
 
address@hidden Multiple sets in one file, Fast access to TODO states, TODO 
types, TODO extensions
address@hidden Multiple sets in one file
 @subsection Multiple keyword sets in one file
 @cindex TODO keyword sets
 
@@ -4164,14 +4201,14 @@ These keys jump from one TODO subset to the next.  In 
the above example,
 @kindex address@hidden
 @item address@hidden
 @itemx address@hidden
address@hidden@key{<left>}} and @address@hidden<right>}} and walk through 
@emph{all}
-keywords from all sets, so for example @address@hidden<right>}} would switch
address@hidden@key{left}} and @address@hidden and walk through @emph{all}
+keywords from all sets, so for example @address@hidden would switch
 from @code{DONE} to @code{REPORT} in the example above.  See also
 @ref{Conflicts}, for a discussion of the interaction with
 @code{shift-selection-mode}.
 @end table
 
address@hidden Fast access to TODO states, Per-file keywords, Multiple sets in 
one file, TODO extensions
address@hidden Fast access to TODO states
 @subsection Fast access to TODO states
 
 If you would like to quickly change an entry to an arbitrary TODO state
@@ -4196,7 +4233,7 @@ state through the tags interface (@pxref{Setting tags}), 
in case you like to
 mingle the two concepts.  Note that this means you need to come up with
 unique keys across both sets of keywords.}
 
address@hidden Per-file keywords, Faces for TODO keywords, Fast access to TODO 
states, TODO extensions
address@hidden Per-file keywords
 @subsection Setting up keywords for individual files
 @cindex keyword options
 @cindex per-file keywords
@@ -4205,11 +4242,10 @@ unique keys across both sets of keywords.}
 @cindex #+SEQ_TODO
 
 It can be very useful to use different aspects of the TODO mechanism in
-different files.  For file-local settings, you need to add special lines
-to the file which set the keywords and interpretation for that file
-only.  For example, to set one of the two examples discussed above, you
-need one of the following lines, starting in column zero anywhere in the
-file:
+different files.  For file-local settings, you need to add special lines to
+the file which set the keywords and interpretation for that file only.  For
+example, to set one of the two examples discussed above, you need one of the
+following lines anywhere in the file:
 
 @example
 #+TODO: TODO FEEDBACK VERIFY | DONE CANCELED
@@ -4243,7 +4279,7 @@ Org mode is activated after visiting a file.  @kbd{C-c 
C-c} with the
 cursor in a line starting with @samp{#+} is simply restarting Org mode
 for the current buffer.}.
 
address@hidden Faces for TODO keywords, TODO dependencies, Per-file keywords, 
TODO extensions
address@hidden Faces for TODO keywords
 @subsection Faces for TODO keywords
 @cindex faces, for TODO keywords
 
@@ -4271,10 +4307,11 @@ special face and use that.  A string is interpreted as 
a color.  The option
 @code{org-faces-easy-properties} determines if that color is interpreted as a
 foreground or a background color.
 
address@hidden TODO dependencies,  , Faces for TODO keywords, TODO extensions
address@hidden TODO dependencies
 @subsection TODO dependencies
 @cindex TODO dependencies
 @cindex dependencies, of TODO states
address@hidden TODO dependencies, NOBLOCKING
 
 @vindex org-enforce-todo-dependencies
 @cindex property, ORDERED
@@ -4303,6 +4340,16 @@ example:
 ** TODO c, needs to wait for (a) and (b)
 @end example
 
+You can ensure an entry is never blocked by using the @code{NOBLOCKING}
+property:
+
address@hidden
+* This entry is never blocked
+  :PROPERTIES:
+  :NOBLOCKING: t
+  :END:
address@hidden example
+
 @table @kbd
 @orgcmd{C-c C-x o,org-toggle-ordered-property}
 @vindex org-track-ordered-property-with-tag
@@ -4319,7 +4366,7 @@ Change TODO state, circumventing any state blocking.
 @vindex org-agenda-dim-blocked-tasks
 If you set the option @code{org-agenda-dim-blocked-tasks}, TODO entries
 that cannot be closed because of such dependencies will be shown in a dimmed
-font or even made invisible in agenda views (@pxref{Agenda Views}).
+font or even made invisible in agenda views (@pxref{Agenda views}).
 
 @cindex checkboxes and TODO dependencies
 @vindex org-enforce-todo-dependencies
@@ -4333,7 +4380,7 @@ between entries in different trees or files, check out 
the contributed
 module @file{org-depend.el}.
 
 @page
address@hidden Progress logging, Priorities, TODO extensions, TODO Items
address@hidden Progress logging
 @section Progress logging
 @cindex progress logging
 @cindex logging, of progress
@@ -4351,7 +4398,7 @@ work time}.
 * Tracking your habits::        How consistent have you been?
 @end menu
 
address@hidden Closing items, Tracking TODO state changes, Progress logging, 
Progress logging
address@hidden Closing items
 @subsection Closing items
 
 The most basic logging is to keep track of @emph{when} a certain TODO
@@ -4387,7 +4434,7 @@ In the timeline (@pxref{Timeline}) and in the agenda
 display the TODO items with a @samp{CLOSED} timestamp on each day,
 giving you an overview of what has been done.
 
address@hidden Tracking TODO state changes, Tracking your habits, Closing 
items, Progress logging
address@hidden Tracking TODO state changes
 @subsection Tracking TODO state changes
 @cindex drawer, for state change recording
 
@@ -4470,7 +4517,7 @@ settings like @code{TODO(!)}.  For example
   :END:
 @end example
 
address@hidden Tracking your habits,  , Tracking TODO state changes, Progress 
logging
address@hidden Tracking your habits
 @subsection Tracking your habits
 @cindex habits
 
@@ -4506,6 +4553,10 @@ actual habit with some history:
 @example
 ** TODO Shave
    SCHEDULED: <2009-10-17 Sat .+2d/4d>
+   :PROPERTIES:
+   :STYLE:    habit
+   :LAST_REPEAT: [2009-10-19 Mon 00:36]
+   :END:
    - State "DONE"       from "TODO"       [2009-10-15 Thu]
    - State "DONE"       from "TODO"       [2009-10-12 Mon]
    - State "DONE"       from "TODO"       [2009-10-10 Sat]
@@ -4516,10 +4567,6 @@ actual habit with some history:
    - State "DONE"       from "TODO"       [2009-09-19 Sat]
    - State "DONE"       from "TODO"       [2009-09-16 Wed]
    - State "DONE"       from "TODO"       [2009-09-12 Sat]
-   :PROPERTIES:
-   :STYLE:    habit
-   :LAST_REPEAT: [2009-10-19 Mon 00:36]
-   :END:
 @end example
 
 What this habit says is: I want to shave at most every 2 days (given by the
@@ -4570,7 +4617,7 @@ temporarily be disabled and they won't appear at all.  
Press @kbd{K} again to
 bring them back.  They are also subject to tag filtering, if you have habits
 which should only be done in certain contexts, for example.
 
address@hidden Priorities, Breaking down tasks, Progress logging, TODO Items
address@hidden Priorities
 @section Priorities
 @cindex priorities
 
@@ -4628,7 +4675,7 @@ priority):
 #+PRIORITIES: A C B
 @end example
 
address@hidden Breaking down tasks, Checkboxes, Priorities, TODO Items
address@hidden Breaking down tasks
 @section Breaking tasks down into subtasks
 @cindex tasks, breaking down
 @cindex statistics, for TODO items
@@ -4689,7 +4736,7 @@ Another possibility is the use of checkboxes to identify 
(a hierarchy of) a
 large number of subtasks (@pxref{Checkboxes}).
 
 
address@hidden Checkboxes,  , Breaking down tasks, TODO Items
address@hidden Checkboxes
 @section Checkboxes
 @cindex checkboxes
 
@@ -4698,7 +4745,7 @@ Every item in a plain address@hidden the exception of 
description
 lists.  But you can allow it by modifying @code{org-list-automatic-rules}
 accordingly.} (@pxref{Plain lists}) can be made into a checkbox by starting
 it with the string @samp{[ ]}.  This feature is similar to TODO items
-(@pxref{TODO Items}), but is more lightweight.  Checkboxes are not included
+(@pxref{TODO items}), but is more lightweight.  Checkboxes are not included
 in the global TODO list, so they are often great to split a task into a
 number of simple steps.  Or you can use them in a shopping list.  To toggle a
 checkbox, use @kbd{C-c C-c}, or use the mouse (thanks to Piotr Zielinski's
@@ -4755,11 +4802,12 @@ off a box while there are unchecked boxes above it.
 
 @table @kbd
 @orgcmd{C-c C-c,org-toggle-checkbox}
-Toggle checkbox status or (with prefix arg) checkbox presence at point.
-With a single prefix argument, add an empty checkbox or remove the current
address@hidden@kbd{C-u C-c C-c} on the @emph{first} item of a list with no 
checkbox
-will add checkboxes to the rest of the list.}.  With a double prefix argument, 
set it to @samp{[-]}, which is
-considered to be an intermediate state.
+Toggle checkbox status or (with prefix arg) checkbox presence at point.  With
+a single prefix argument, add an empty checkbox or remove the current
address@hidden@kbd{C-u C-c C-c} before the @emph{first} bullet in a list with
+no checkbox will add checkboxes to the rest of the list.}.  With a double
+prefix argument, set it to @samp{[-]}, which is considered to be an
+intermediate state.
 @orgcmd{C-c C-x C-b,org-toggle-checkbox}
 Toggle checkbox status or (with prefix arg) checkbox presence at point.  With
 double prefix argument, set it to @samp{[-]}, which is considered to be an
@@ -4770,8 +4818,10 @@ If there is an active region, toggle the first checkbox 
in the region
 and set all remaining boxes to the same status as the first.  With a prefix
 arg, add or remove the checkbox for all items in the region.
 @item
-If the cursor is in a headline, toggle checkboxes in the region between
-this headline and the next (so @emph{not} the entire subtree).
+If the cursor is in a headline, toggle the state of the first checkbox in the
+region between this headline and the next---so @emph{not} the entire
+subtree---and propagate this new state to all other checkboxes in the same
+area.
 @item
 If there is no active region, just toggle the checkbox at point.
 @end itemize
@@ -4795,7 +4845,7 @@ changing TODO states.  If you delete boxes/entries or 
add/change them by
 hand, use this command to get things back into sync.
 @end table
 
address@hidden Tags, Properties and Columns, TODO Items, Top
address@hidden Tags
 @chapter Tags
 @cindex tags
 @cindex headline tagging
@@ -4819,11 +4869,11 @@ You may specify special faces for specific tags using 
the option
 @menu
 * Tag inheritance::             Tags use the tree structure of the outline
 * Setting tags::                How to assign tags to a headline
-* Tag groups::                  Use one tag to search for several tags
+* Tag hierarchy::               Create a hierarchy of tags
 * Tag searches::                Searching for combinations of tags
 @end menu
 
address@hidden Tag inheritance, Setting tags, Tags, Tags
address@hidden Tag inheritance
 @section Tag inheritance
 @cindex tag inheritance
 @cindex inheritance, of tags
@@ -4842,11 +4892,11 @@ well.  For example, in the list
 @noindent
 the final heading will have the tags @samp{:work:}, @samp{:boss:},
 @samp{:notes:}, and @samp{:action:} even though the final heading is not
-explicitly marked with those tags.  You can also set tags that all entries in
-a file should inherit just as if these tags were defined in a hypothetical
-level zero that surrounds the entire file.  Use a line like address@hidden
-with all these in-buffer settings, pressing @kbd{C-c C-c} activates any
-changes in the line.}:
+explicitly marked with all those tags.  You can also set tags that all
+entries in a file should inherit just as if these tags were defined in
+a hypothetical level zero that surrounds the entire file.  Use a line like
address@hidden with all these in-buffer settings, pressing @kbd{C-c C-c}
+activates any changes in the line.}:
 
 @cindex #+FILETAGS
 @example
@@ -4877,7 +4927,7 @@ with inherited tags.  Set 
@code{org-agenda-use-tag-inheritance} to control
 this: the default value includes all agenda types, but setting this to 
@code{nil}
 can really speed up agenda generation.
 
address@hidden Setting tags, Tag groups, Tag inheritance, Tags
address@hidden Setting tags
 @section Setting tags
 @cindex setting tags
 @cindex tags, setting
@@ -4939,10 +4989,10 @@ By default Org mode uses the standard minibuffer 
completion facilities for
 entering tags.  However, it also implements another, quicker, tag selection
 method called @emph{fast tag selection}.  This allows you to select and
 deselect tags with just a single key press.  For this to work well you should
-assign unique letters to most of your commonly used tags.  You can do this
-globally by configuring the variable @code{org-tag-alist} in your
address@hidden file.  For example, you may find the need to tag many items in
-different files with @samp{:@@home:}.  In this case you can set something
+assign unique, case-sensitive, letters to most of your commonly used tags.
+You can do this globally by configuring the variable @code{org-tag-alist} in
+your Emacs init file.  For example, you may find the need to tag many items
+in different files with @samp{:@@home:}.  In this case you can set something
 like:
 
 @lisp
@@ -5004,14 +5054,15 @@ If at least one tag has a selection key then pressing 
@kbd{C-c C-c} will
 automatically present you with a special interface, listing inherited tags,
 the tags of the current headline, and a list of all valid tags with
 corresponding address@hidden will automatically be assigned to tags which
-have no configured keys.}.  In this interface, you can use the following
-keys:
+have no configured keys.}.
+
+Pressing keys assigned to tags will add or remove them from the list of tags
+in the current line.  Selecting a tag in a group of mutually exclusive tags
+will turn off any other tags from that group.
+
+In this interface, you can also use the following special keys:
 
 @table @kbd
address@hidden a-z...
-Pressing keys assigned to tags will add or remove them from the list of
-tags in the current line.  Selecting a tag in a group of mutually
-exclusive tags will turn off any other tags from that group.
 @kindex @key{TAB}
 @item @key{TAB}
 Enter a tag in the minibuffer, even if the tag is not in the predefined
@@ -5021,16 +5072,21 @@ You can also add several tags: just separate them with 
a comma.
 @kindex @key{SPC}
 @item @key{SPC}
 Clear all tags for this line.
+
 @kindex @key{RET}
 @item @key{RET}
 Accept the modified set.
+
 @item C-g
 Abort without installing changes.
+
 @item q
 If @kbd{q} is not assigned to a tag, it aborts like @kbd{C-g}.
+
 @item !
 Turn off groups of mutually exclusive tags.  Use this to (as an
 exception) assign several tags from such a group.
+
 @item C-c
 Toggle auto-exit after the next change (see below).
 If you are using expert mode, the first @kbd{C-c} will display the
@@ -5058,41 +5114,104 @@ instead of @kbd{C-c C-c}).  If you set the variable to 
the value
 @code{expert}, the special window is not even shown for single-key tag
 selection, it comes up only when you press an extra @kbd{C-c}.
 
address@hidden Tag groups, Tag searches, Setting tags, Tags
address@hidden Tag groups
address@hidden Tag hierarchy
address@hidden Tag hierarchy
 
 @cindex group tags
 @cindex tags, groups
-In a set of mutually exclusive tags, the first tag can be defined as a
address@hidden tag}.  When you search for a group tag, it will return matches
-for all members in the group.  In an agenda view, filtering by a group tag
-will display headlines tagged with at least one of the members of the
-group.  This makes tag searches and filters even more flexible.
address@hidden tag hierarchy
+Tags can be defined in hierarchies.  A tag can be defined as a @emph{group
+tag} for a set of other tags.  The group tag can be seen as the ``broader
+term'' for its set of tags.  Defining multiple @emph{group tags} and nesting
+them creates a tag hierarchy.
+
+One use-case is to create a taxonomy of terms (tags) that can be used to
+classify nodes in a document or set of documents.
+
+When you search for a group tag, it will return matches for all members in
+the group and its subgroups.  In an agenda view, filtering by a group tag
+will display or hide headlines tagged with at least one of the members of the
+group or any of its subgroups.  This makes tag searches and filters even more
+flexible.
+
+You can set group tags by using brackets and inserting a colon between the
+group tag and its related tags---beware that all whitespaces are mandatory so
+that Org can parse this line correctly:
 
-You can set group tags by inserting a colon between the group tag and other
-tags---beware that all whitespaces are mandatory so that Org can parse this
-line correctly:
address@hidden
+#+TAGS: [ GTD : Control Persp ]
address@hidden example
+
+In this example, @samp{GTD} is the @emph{group tag} and it is related to two
+other tags: @samp{Control}, @samp{Persp}.  Defining @samp{Control} and
address@hidden as group tags creates an hierarchy of tags:
 
 @example
-#+TAGS: @{ @@read : @@read_book @@read_ebook @}
+#+TAGS: [ Control : Context Task ]
+#+TAGS: [ Persp : Vision Goal AOF Project ]
 @end example
 
-In this example, @samp{@@read} is a @emph{group tag} for a set of three
-tags: @samp{@@read}, @samp{@@read_book} and @samp{@@read_ebook}.
+That can conceptually be seen as a hierarchy of tags:
+
address@hidden
+- GTD
+  - Persp
+    - Vision
+    - Goal
+    - AOF
+    - Project
+  - Control
+    - Context
+    - Task
address@hidden example
 
-You can also use the @code{:grouptags} keyword directly when setting
address@hidden:
+You can use the @code{:startgrouptag}, @code{:grouptags} and
address@hidden:endgrouptag} keyword directly when setting @code{org-tag-alist}
+directly:
 
 @lisp
-(setq org-tag-alist '((:startgroup . nil)
-                      ("@@read" . nil)
-                      (:grouptags . nil)
-                      ("@@read_book" . nil)
-                      ("@@read_ebook" . nil)
-                      (:endgroup . nil)))
+(setq org-tag-alist '((:startgrouptag)
+                      ("GTD")
+                      (:grouptags)
+                      ("Control")
+                      ("Persp")
+                      (:endgrouptag)
+                      (:startgrouptag)
+                      ("Control")
+                      (:grouptags)
+                      ("Context")
+                      ("Task")
+                      (:endgrouptag)))
 @end lisp
 
-You cannot nest group tags or use a group tag as a tag in another group.
+The tags in a group can be mutually exclusive if using the same group syntax
+as is used for grouping mutually exclusive tags together; using curly
+brackets.
+
address@hidden
+#+TAGS: @{ Context : @@Home @@Work @@Call @}
address@hidden example
+
+When setting @code{org-tag-alist} you can use @code{:startgroup} &
address@hidden:endgroup} instead of @code{:startgrouptag} & @code{:endgrouptag} 
to
+make the tags mutually exclusive.
+
+Furthermore, the members of a @emph{group tag} can also be regular
+expressions, creating the possibility of a more dynamic and rule-based
+tag structure.  The regular expressions in the group must be specified
+within @{ @}.  Here is an expanded example:
+
address@hidden
+#+TAGS: [ Vision : @{V@@@address@hidden ]
+#+TAGS: [ Goal : @{G@@@address@hidden ]
+#+TAGS: [ AOF : @{AOF@@@address@hidden ]
+#+TAGS: [ Project : @{P@@@address@hidden ]
address@hidden example
+
+Searching for the tag @samp{Project} will now list all tags also including
+regular expression matches for @samp{P@@@.+}, and similarly for tag searches on
address@hidden, @samp{Goal} and @samp{AOF}.  For example, this would work well
+for a project tagged with a common project-identifier, e.g. 
@samp{P@@2014_OrgTags}.
 
 @kindex C-c C-x q
 @vindex org-group-tags
@@ -5100,7 +5219,7 @@ If you want to ignore group tags temporarily, toggle 
group tags support
 with @command{org-toggle-tags-groups}, bound to @kbd{C-c C-x q}.  If you
 want to disable tag groups completely, set @code{org-group-tags} to @code{nil}.
 
address@hidden Tag searches,  , Tag groups, Tags
address@hidden Tag searches
 @section Tag searches
 @cindex tag searches
 @cindex searching for tags
@@ -5126,13 +5245,13 @@ only TODO items and force checking subitems (see the 
option
 These commands all prompt for a match string which allows basic Boolean logic
 like @samp{+boss+urgent-project1}, to find entries with tags @samp{boss} and
 @samp{urgent}, but not @samp{project1}, or @samp{Kathy|Sally} to find entries
-which are tagged, like @samp{Kathy} or @samp{Sally}.  The full syntax of the 
search
-string is rich and allows also matching against TODO keywords, entry levels
-and properties.  For a complete description with many examples, see
address@hidden tags and properties}.
+tagged as @samp{Kathy} or @samp{Sally}.  The full syntax of the search string
+is rich and allows also matching against TODO keywords, entry levels and
+properties.  For a complete description with many examples, see @ref{Matching
+tags and properties}.
 
 
address@hidden Properties and Columns, Dates and Times, Tags, Top
address@hidden Properties and columns
 @chapter Properties and columns
 @cindex properties
 
@@ -5162,16 +5281,18 @@ Properties can be conveniently edited and viewed in 
column view
 * Property API::                Properties for Lisp programmers
 @end menu
 
address@hidden Property syntax, Special properties, Properties and Columns, 
Properties and Columns
address@hidden Property syntax
 @section Property syntax
 @cindex property syntax
 @cindex drawer, for properties
 
 Properties are key-value pairs.  When they are associated with a single entry
-or with a tree they need to be inserted into a special
-drawer (@pxref{Drawers}) with the name @code{PROPERTIES}.  Each property
-is specified on a single line, with the key (surrounded by colons)
-first, and the value after it.  Here is an example:
+or with a tree they need to be inserted into a special drawer
+(@pxref{Drawers}) with the name @code{PROPERTIES}, which has to be located
+right below a headline, and its planning line (@pxref{Deadlines and
+scheduling}) when applicable.  Each property is specified on a single line,
+with the key (surrounded by colons) first, and the value after it.  Keys are
+case-insensitives.  Here is an example:
 
 @example
 * CD collection
@@ -5187,7 +5308,7 @@ first, and the value after it.  Here is an example:
 @end example
 
 Depending on the value of @code{org-use-property-inheritance}, a property set
-this way will either be associated with a single entry, or the sub-tree
+this way will either be associated with a single entry, or the subtree
 defined by the entry, see @ref{Property inheritance}.
 
 You may define the allowed values for a particular property @samp{:Xyz:}
@@ -5215,7 +5336,7 @@ file, use a line like
 @end example
 
 Contrary to properties set from a special drawer, you have to refresh the
-buffer with @kbd{C-c C-c} to activate this changes.
+buffer with @kbd{C-c C-c} to activate this change.
 
 If you want to add to the value of an existing property, append a @code{+} to
 the property name.  The following results in the property @code{var} having
@@ -5284,58 +5405,52 @@ Compute the property at point, using the operator and 
scope from the
 nearest column format definition.
 @end table
 
address@hidden Special properties, Property searches, Property syntax, 
Properties and Columns
address@hidden Special properties
 @section Special properties
 @cindex properties, special
 
 Special properties provide an alternative access method to Org mode features,
 like the TODO state or the priority of an entry, discussed in the previous
-chapters.  This interface exists so that you can include these states in a
-column view (@pxref{Column view}), or to use them in queries.  The following
-property names are special and (except for @code{:CATEGORY:}) should not be
-used as keys in the properties drawer:
+chapters.  This interface exists so that you can include these states in
+a column view (@pxref{Column view}), or to use them in queries.  The
+following property names are special and should not be used as keys in the
+properties drawer:
 
address@hidden property, special, ID
address@hidden property, special, TODO
address@hidden property, special, TAGS
 @cindex property, special, ALLTAGS
address@hidden property, special, CATEGORY
address@hidden property, special, PRIORITY
address@hidden property, special, BLOCKED
address@hidden property, special, CLOCKSUM
address@hidden property, special, CLOCKSUM_T
address@hidden property, special, CLOSED
 @cindex property, special, DEADLINE
address@hidden property, special, FILE
address@hidden property, special, ITEM
address@hidden property, special, PRIORITY
 @cindex property, special, SCHEDULED
address@hidden property, special, CLOSED
address@hidden property, special, TAGS
 @cindex property, special, TIMESTAMP
 @cindex property, special, TIMESTAMP_IA
address@hidden property, special, CLOCKSUM
address@hidden property, special, CLOCKSUM_T
address@hidden property, special, BLOCKED
address@hidden guessing that ITEM is needed in this area; also, should this 
list be sorted?
address@hidden property, special, ITEM
address@hidden property, special, FILE
address@hidden property, special, TODO
 @example
-ID           @r{A globally unique ID used for synchronization during}
-             @r{iCalendar or MobileOrg export.}
-TODO         @r{The TODO keyword of the entry.}
-TAGS         @r{The tags defined directly in the headline.}
 ALLTAGS      @r{All tags, including inherited ones.}
-CATEGORY     @r{The category of an entry.}
-PRIORITY     @r{The priority of the entry, a string with a single letter.}
-DEADLINE     @r{The deadline time string, without the angular brackets.}
-SCHEDULED    @r{The scheduling timestamp, without the angular brackets.}
-CLOSED       @r{When was this entry closed?}
-TIMESTAMP    @r{The first keyword-less timestamp in the entry.}
-TIMESTAMP_IA @r{The first inactive timestamp in the entry.}
+BLOCKED      @r{"t" if task is currently blocked by children or siblings.}
 CLOCKSUM     @r{The sum of CLOCK intervals in the subtree.  
@code{org-clock-sum}}
              @r{must be run first to compute the values in the current buffer.}
 CLOCKSUM_T   @r{The sum of CLOCK intervals in the subtree for today.}
              @address@hidden must be run first to compute the}
              @r{values in the current buffer.}
-BLOCKED      @r{"t" if task is currently blocked by children or siblings}
-ITEM         @r{The headline of the entry.}
+CLOSED       @r{When was this entry closed?}
+DEADLINE     @r{The deadline time string, without the angular brackets.}
 FILE         @r{The filename the entry is located in.}
+ITEM         @r{The headline of the entry.}
+PRIORITY     @r{The priority of the entry, a string with a single letter.}
+SCHEDULED    @r{The scheduling timestamp, without the angular brackets.}
+TAGS         @r{The tags defined directly in the headline.}
+TIMESTAMP    @r{The first keyword-less timestamp in the entry.}
+TIMESTAMP_IA @r{The first inactive timestamp in the entry.}
+TODO         @r{The TODO keyword of the entry.}
 @end example
 
address@hidden Property searches, Property inheritance, Special properties, 
Properties and Columns
address@hidden Property searches
 @section Property searches
 @cindex properties, searching
 @cindex searching, of properties
@@ -5372,7 +5487,7 @@ value.  If you enclose the value in curly braces, it is 
interpreted as
 a regular expression and matched against the property values.
 @end table
 
address@hidden Property inheritance, Column view, Property searches, Properties 
and Columns
address@hidden Property inheritance
 @section Property Inheritance
 @cindex properties, inheritance
 @cindex inheritance, of properties
@@ -5416,7 +5531,7 @@ The LOGGING property may define logging settings for an 
entry or a
 subtree (@pxref{Tracking TODO state changes}).
 @end table
 
address@hidden Column view, Property API, Property inheritance, Properties and 
Columns
address@hidden Column view
 @section Column view
 
 A great way to view and edit properties in an outline tree is
@@ -5430,7 +5545,7 @@ view (@address@hidden address@hidden, or simply @kbd{c} 
while column view
 is active), but you can still open, read, and edit the entry below each
 headline.  Or, you can switch to column view after executing a sparse
 tree command and in this way get a table only for the selected items.
-Column view also works in agenda buffers (@pxref{Agenda Views}) where
+Column view also works in agenda buffers (@pxref{Agenda views}) where
 queries have collected selected items, possibly from a number of files.
 
 @menu
@@ -5439,7 +5554,7 @@ queries have collected selected items, possibly from a 
number of files.
 * Capturing column view::       A dynamic block for column view
 @end menu
 
address@hidden Defining columns, Using column view, Column view, Column view
address@hidden Defining columns
 @subsection Defining columns
 @cindex column view, for properties
 @cindex properties, column view
@@ -5452,7 +5567,7 @@ done by defining a column format line.
 * Column attributes::           Appearance and content of a column
 @end menu
 
address@hidden Scope of column definitions, Column attributes, Defining 
columns, Defining columns
address@hidden Scope of column definitions
 @subsubsection Scope of column definitions
 
 To define a column format for an entire file, use a line like
@@ -5479,7 +5594,7 @@ you can define columns on level 1 that are general enough 
for all
 sublevels, and more specific columns further down, when you edit a
 deeper part of the tree.
 
address@hidden Column attributes,  , Scope of column definitions, Defining 
columns
address@hidden Column attributes
 @subsubsection Column attributes
 A column definition sets the attributes of a column.  The general
 definition looks like this:
@@ -5501,38 +5616,45 @@ optional.  The individual parts have the following 
meaning:
 @var{title}           @r{The header text for the column.  If omitted, the 
property}
                 @r{name is used.}
 @address@hidden@}  @r{The summary type.  If specified, the column values for}
-                @r{parent nodes are computed from the children.}
+                @r{parent nodes are computed from the address@hidden
+                more than one summary type apply to the property, the parent
+                values are computed according to the first of them.}.}
                 @r{Supported summary types are:}
                 @address@hidden       @r{Sum numbers in this column.}
                 @{+;address@hidden  @r{Like @samp{+}, but format result with 
@samp{%.1f}.}
                 @address@hidden       @r{Currency, short for @samp{+;%.2f}.}
-                @{:@}       @r{Sum times, HH:MM, plain numbers are hours.}
-                @address@hidden       @r{Checkbox status, @samp{[X]} if all 
children are @samp{[X]}.}
-                @{X/@}      @r{Checkbox status, @samp{[n/m]}.}
-                @address@hidden      @r{Checkbox status, @samp{[n%]}.}
                 @address@hidden     @r{Smallest number in column.}
                 @address@hidden     @r{Largest number.}
                 @address@hidden    @r{Arithmetic mean of numbers.}
+                @address@hidden       @r{Checkbox status, @samp{[X]} if all 
children are @samp{[X]}.}
+                @{X/@}      @r{Checkbox status, @samp{[n/m]}.}
+                @address@hidden      @r{Checkbox status, @samp{[n%]}.}
+                @{:@}       @r{Sum times, HH:MM, plain numbers are
+                address@hidden time can also be a duration, using effort
+                modifiers defined in @code{org-effort-durations}, e.g.,
+                @samp{3d 1h}.  If any value in the column is as such, the
+                summary will also be an effort duration.}.}
                 @{:address@hidden    @r{Smallest time value in column.}
                 @{:address@hidden    @r{Largest time value.}
                 @{:address@hidden   @r{Arithmetic mean of time values.}
-                @{@@address@hidden    @r{Minimum age (in 
days/hours/mins/seconds).}
+                @{@@address@hidden    @r{Minimum address@hidden age is defined 
as
+                a duration since a given time-stamp (@pxref{Timestamps}).  It
+                can  also be expressed as days, hours, minutes and seconds,
+                identified by @samp{d}, @samp{h}, @samp{m} and @samp{s}
+                suffixes, all mandatory, e.g., @samp{0d 13h 0m 10s}.} (in
+                days/hours/mins/seconds).}
                 @{@@address@hidden    @r{Maximum age (in 
days/hours/mins/seconds).}
                 @{@@address@hidden   @r{Arithmetic mean of ages (in 
days/hours/mins/seconds).}
-                @address@hidden    @r{Add low-high estimates.}
+                @address@hidden    @r{Add @samp{low-high} estimates.}
 @end example
 
address@hidden
-Be aware that you can only have one summary type for any property you
-include.  Subsequent columns referencing the same property will all display the
-same summary information.
-
 The @code{est+} summary type requires further explanation.  It is used for
-combining estimates, expressed as low-high ranges.  For example, instead
-of estimating a particular task will take 5 days, you might estimate it as
-5--6 days if you're fairly confident you know how much work is required, or
-1--10 days if you don't really know what needs to be done.  Both ranges
-average at 5.5 days, but the first represents a more predictable delivery.
+combining estimates, expressed as @samp{low-high} ranges or plain numbers.
+For example, instead of estimating a particular task will take 5 days, you
+might estimate it as 5--6 days if you're fairly confident you know how much
+work is required, or 1--10 days if you don't really know what needs to be
+done.  Both ranges average at 5.5 days, but the first represents a more
+predictable delivery.
 
 When combining a set of such estimates, simply adding the lows and highs
 produces an unrealistically wide result.  Instead, @code{est+} adds the
@@ -5546,6 +5668,10 @@ full job more realistically, at 10--15 days.
 Numbers are right-aligned when a format specifier with an explicit width like
 @code{%5d} or @code{%5.1f} is used.
 
address@hidden org-columns-summary-types
+You can also define custom summary types by setting
address@hidden, which see.
+
 Here is an example for a complete columns definition, along with allowed
 values.
 
@@ -5574,7 +5700,7 @@ an @samp{[X]} status if all children have been checked.  
The
 sums of CLOCK intervals in the subtree, either for all clocks or just for
 today.
 
address@hidden Using column view, Capturing column view, Defining columns, 
Column view
address@hidden Using column view
 @subsection Using column view
 
 @table @kbd
@@ -5582,14 +5708,15 @@ today.
 @orgcmd{C-c C-x C-c,org-columns}
 @vindex org-columns-default-format
 Turn on column view.  If the cursor is before the first headline in the file,
-column view is turned on for the entire file, using the @code{#+COLUMNS}
-definition.  If the cursor is somewhere inside the outline, this command
-searches the hierarchy, up from point, for a @code{:COLUMNS:} property that
-defines a format.  When one is found, the column view table is established
-for the tree starting at the entry that contains the @code{:COLUMNS:}
-property.  If no such property is found, the format is taken from the
address@hidden line or from the variable @code{org-columns-default-format},
-and column view is established for the current entry and its subtree.
+or the function called with the universal prefix argument, column view is
+turned on for the entire file, using the @code{#+COLUMNS} definition.  If the
+cursor is somewhere inside the outline, this command searches the hierarchy,
+up from point, for a @code{:COLUMNS:} property that defines a format.  When
+one is found, the column view table is established for the tree starting at
+the entry that contains the @code{:COLUMNS:} property.  If no such property
+is found, the format is taken from the @code{#+COLUMNS} line or from the
+variable @code{org-columns-default-format}, and column view is established
+for the current entry and its subtree.
 @orgcmd{r,org-columns-redo}
 Recreate the column view, to include recent changes made in the buffer.
 @orgcmd{g,org-columns-redo}
@@ -5620,7 +5747,7 @@ View the full value of this property.  This is useful if 
the width of
 the column is smaller than that of the value.
 @orgcmd{a,org-columns-edit-allowed}
 Edit the list of allowed values for this property.  If the list is found
-in the hierarchy, the modified values is stored there.  If no list is
+in the hierarchy, the modified value is stored there.  If no list is
 found, the new value is stored in the first entry that is part of the
 current column view.
 @tsubheading{Modifying the table structure}
@@ -5632,7 +5759,7 @@ Insert a new column, to the left of the current column.
 Delete the current column.
 @end table
 
address@hidden Capturing column view,  , Using column view, Column view
address@hidden Capturing column view
 @subsection Capturing column view
 
 Since column view is just an overlay over a buffer, it cannot be
@@ -5677,6 +5804,8 @@ When set to a number, don't capture entries below this 
level.
 @item :skip-empty-rows
 When set to @code{t}, skip rows where the only non-empty specifier of the
 column view is @code{ITEM}.
address@hidden :indent
+When address@hidden, indent each @code{ITEM} field according to its level.
 
 @end table
 
@@ -5709,7 +5838,7 @@ distributed with the main distribution of Org (visit
 properties from entries in a certain scope, and arbitrary Lisp expressions to
 process these values before inserting them into a table or a dynamic block.
 
address@hidden Property API,  , Column view, Properties and Columns
address@hidden Property API
 @section The Property API
 @cindex properties, API
 @cindex API, for properties
@@ -5719,7 +5848,7 @@ be used by Emacs Lisp programs to work with properties 
and to implement
 features based on them.  For more information see @ref{Using the
 property API}.
 
address@hidden Dates and Times, Capture - Refile - Archive, Properties and 
Columns, Top
address@hidden Dates and times
 @chapter Dates and times
 @cindex dates
 @cindex times
@@ -5729,7 +5858,7 @@ property API}.
 To assist project planning, TODO items can be labeled with a date and/or
 a time.  The specially formatted string carrying the date and time
 information is called a @emph{timestamp} in Org mode.  This may be a
-little confusing because timestamp is often used as indicating when
+little confusing because timestamp is often used to indicate when
 something was created or last changed.  However, in Org mode this term
 is used in a much wider sense.
 
@@ -5739,12 +5868,11 @@ is used in a much wider sense.
 * Deadlines and scheduling::    Planning your work
 * Clocking work time::          Tracking how long you spend on a task
 * Effort estimates::            Planning work effort in advance
-* Relative timer::              Notes with a running timer
-* Countdown timer::             Starting a countdown timer for a task
+* Timers::                      Notes with a running timer
 @end menu
 
 
address@hidden Timestamps, Creating timestamps, Dates and Times, Dates and Times
address@hidden Timestamps
 @section Timestamps, deadlines, and scheduling
 @cindex timestamps
 @cindex ranges, time
@@ -5795,10 +5923,10 @@ following will show up in the agenda every Wednesday:
 For more complex date specifications, Org mode supports using the special
 sexp diary entries implemented in the Emacs calendar/diary
 address@hidden working with the standard diary sexp functions, you
-need to be very careful with the order of the arguments.  That order depend
+need to be very careful with the order of the arguments.  That order depends
 evilly on the variable @code{calendar-date-style} (or, for older Emacs
 versions, @code{european-calendar-style}).  For example, to specify a date
-December 12, 2005, the call might look like @code{(diary-date 12 1 2005)} or
+December 1, 2005, the call might look like @code{(diary-date 12 1 2005)} or
 @code{(diary-date 1 12 2005)} or @code{(diary-date 2005 12 1)}, depending on
 the settings.  This has been the source of much confusion.  Org mode users
 can resort to special versions of these functions like @code{org-date} or
@@ -5838,7 +5966,7 @@ angular ones.  These timestamps are inactive in the sense 
that they do
 
 @end table
 
address@hidden Creating timestamps, Deadlines and scheduling, Timestamps, Dates 
and Times
address@hidden Creating timestamps
 @section Creating timestamps
 @cindex creating timestamps
 @cindex timestamps, creating
@@ -5909,7 +6037,7 @@ the following column).
 * Custom time format::          Making dates look different
 @end menu
 
address@hidden The date/time prompt, Custom time format, Creating timestamps, 
Creating timestamps
address@hidden The date/time prompt
 @subsection The date/time prompt
 @cindex date, reading in minibuffer
 @cindex time, reading in minibuffer
@@ -5948,7 +6076,7 @@ feb 15        @result{} @b{2007}-02-15
 sep 12 9      @result{} 2009-09-12
 12:45         @result{} @address@hidden@b{13} 12:45
 22 sept 0:34  @result{} @b{2006}-09-22 00:34
-w4            @result{} ISO week for of the current year @b{2006}
+w4            @result{} ISO week four of the current year @b{2006}
 2012 w4 fri   @result{} Friday of ISO week 4 in 2012
 2012-w04-5    @result{} Same as above
 @end example
@@ -6017,14 +6145,18 @@ from the minibuffer:
 @kindex address@hidden
 @kindex address@hidden
 @kindex @key{RET}
address@hidden address@hidden
address@hidden address@hidden
+
 @example
address@hidden           @r{Choose date at cursor in calendar.}
-mouse-1        @r{Select date by clicking on it.}
address@hidden/@key{left}     @r{One day forward/backward.}
address@hidden/@key{up}     @r{One week forward/backward.}
address@hidden/@key{left}   @r{One month forward/backward.}
-> / <          @r{Scroll calendar forward/backward by one month.}
-M-v / C-v      @r{Scroll calendar forward/backward by 3 months.}
address@hidden              @r{Choose date at cursor in calendar.}
+mouse-1            @r{Select date by clicking on it.}
address@hidden/@key{left}   @r{One day forward/backward.}
address@hidden/@key{up}      @r{One week forward/backward.}
address@hidden/@key{left} @r{One month forward/backward.}
+> / <              @r{Scroll calendar forward/backward by one month.}
+M-v / C-v          @r{Scroll calendar forward/backward by 3 months.}
address@hidden/@key{up}    @r{Scroll calendar forward/backward by one year.}
 @end example
 
 @vindex org-read-date-display-live
@@ -6035,7 +6167,7 @@ on, the current interpretation of your input will be 
displayed live in the
 address@hidden you find this distracting, turn the display off with
 @code{org-read-date-display-live}.}.
 
address@hidden Custom time format,  , The date/time prompt, Creating timestamps
address@hidden Custom time format
 @subsection Custom time format
 @cindex custom date/time format
 @cindex time format, custom
@@ -6083,10 +6215,12 @@ format is shorter, things do work as expected.
 @end itemize
 
 
address@hidden Deadlines and scheduling, Clocking work time, Creating 
timestamps, Dates and Times
address@hidden Deadlines and scheduling
 @section Deadlines and scheduling
 
-A timestamp may be preceded by special keywords to facilitate planning:
+A timestamp may be preceded by special keywords to facilitate planning.  Both
+the timestamp and the keyword have to be positioned immediatly after the task
+they refer to.
 
 @table @var
 @item DEADLINE
@@ -6110,9 +6244,9 @@ until the entry is marked address@hidden  An example:
 @end example
 
 You can specify a different lead time for warnings for a specific
-deadlines using the following syntax.  Here is an example with a warning
+deadline using the following syntax.  Here is an example with a warning
 period of 5 days @code{DEADLINE: <2004-02-29 Sun -5d>}.  This warning is
-deactivated if the task get scheduled and you set
+deactivated if the task gets scheduled and you set
 @code{org-agenda-skip-deadline-prewarning-if-scheduled} to @code{t}.
 
 @item SCHEDULED
@@ -6172,28 +6306,25 @@ sexp entry matches.
 * Repeated tasks::              Items that show up again and again
 @end menu
 
address@hidden Inserting deadline/schedule, Repeated tasks, Deadlines and 
scheduling, Deadlines and scheduling
address@hidden Inserting deadline/schedule
 @subsection Inserting deadlines or schedules
 
-The following commands allow you to quickly address@hidden @samp{SCHEDULED} and
address@hidden dates are inserted on the line right below the headline.  Don't 
put
-any text between this line and the headline.} a deadline or to schedule
+The following commands allow you to quickly insert a deadline or to schedule
 an item:
 
 @table @kbd
 @c
 @orgcmd{C-c C-d,org-deadline}
-Insert @samp{DEADLINE} keyword along with a stamp.  The insertion will happen
-in the line directly following the headline.  Any CLOSED timestamp will be
-removed.  When called with a prefix arg, an existing deadline will be removed
-from the entry.  Depending on the variable @address@hidden corresponding
address@hidden keywords @code{logredeadline}, @code{lognoteredeadline},
-and @code{nologredeadline}}, a note will be taken when changing an existing
+Insert @samp{DEADLINE} keyword along with a stamp.  Any CLOSED timestamp will
+be removed.  When called with a prefix arg, an existing deadline will be
+removed from the entry.  Depending on the variable
address@hidden@footnote{with corresponding @code{#+STARTUP}
+keywords @code{logredeadline}, @code{lognoteredeadline}, and
address@hidden, a note will be taken when changing an existing
 deadline.
 
 @orgcmd{C-c C-s,org-schedule}
-Insert @samp{SCHEDULED} keyword along with a stamp.  The insertion will
-happen in the line directly following the headline.  Any CLOSED timestamp
+Insert @samp{SCHEDULED} keyword along with a stamp.  Any CLOSED timestamp
 will be removed.  When called with a prefix argument, remove the scheduling
 date from the entry.  Depending on the variable
 @address@hidden corresponding @code{#+STARTUP}
@@ -6201,14 +6332,6 @@ keywords @code{logreschedule}, @code{lognotereschedule}, 
and
 @code{nologreschedule}}, a note will be taken when changing an existing
 scheduling time.
 @c
address@hidden C-x C-k,org-mark-entry-for-agenda-action}
address@hidden k a
address@hidden k s
-Mark the current entry for agenda action.  After you have marked the entry
-like this, you can open the agenda or the calendar to find an appropriate
-date.  With the cursor on the selected date, press @kbd{k s} or @kbd{k d} to
-schedule the marked item.
address@hidden
 @orgcmd{C-c / d,org-check-deadlines}
 @cindex sparse tree, for deadlines
 @vindex org-deadline-warning-days
@@ -6230,7 +6353,7 @@ setting the date by indicating a relative time: e.g., +1d 
will set
 the date to the next day after today, and --1w will set the date
 to the previous week before any current timestamp.
 
address@hidden Repeated tasks,  , Inserting deadline/schedule, Deadlines and 
scheduling
address@hidden Repeated tasks
 @subsection Repeated tasks
 @cindex tasks, repeated
 @cindex repeated tasks
@@ -6271,6 +6394,9 @@ switch the date like this:
    DEADLINE: <2005-11-01 Tue +1m>
 @end example
 
+To mark a task with a repeater as @code{DONE}, use @kbd{C-- 1 C-c C-t}
+(i.e., @code{org-todo} with a numeric prefix argument of -1.)
+
 @vindex org-log-repeat
 A address@hidden can change this using the option
 @code{org-log-repeat}, or the @code{#+STARTUP} options @code{logrepeat},
@@ -6299,6 +6425,13 @@ special repeaters  @samp{++} and @samp{.+}.  For example:
    but also by as many weeks as it takes to get this date into
    the future.  However, it stays on a Sunday, even if you called
    and marked it done on Saturday.
+** TODO Empty kitchen trash
+   DEADLINE: <2008-02-08 Fri 20:00 ++1d>
+   Marking this DONE will shift the date by at least one day, and
+   also by as many days as it takes to get the timestamp into the
+   future.  Since there is a time in the timestamp, the next
+   deadline in the future will be on today's date if you
+   complete the task before 20:00.
 ** TODO Check the batteries in the smoke detectors
    DEADLINE: <2005-11-01 Tue .+1m>
    Marking this DONE will shift the date to one month after
@@ -6310,7 +6443,9 @@ You may have both scheduling and deadline information for 
a specific task.
 If the repeater is set for the scheduling information only, you probably want
 the repeater to be ignored after the deadline.  If so, set the variable
 @code{org-agenda-skip-scheduled-if-deadline-is-shown} to
address@hidden  If you want both scheduling and deadline
address@hidden  However, any scheduling information without
+a repeater is no longer relevant once the task is done, and thus, removed
+upon repeating the task.  If you want both scheduling and deadline
 information to repeat after the same interval, set the same repeater for both
 timestamps.
 
@@ -6319,7 +6454,7 @@ subtree, with dates shifted in each copy.  The command 
@kbd{C-c C-x c} was
 created for this purpose, it is described in @ref{Structure editing}.
 
 
address@hidden Clocking work time, Effort estimates, Deadlines and scheduling, 
Dates and Times
address@hidden Clocking work time
 @section Clocking work time
 @cindex clocking time
 @cindex time clocking
@@ -6330,10 +6465,9 @@ you stop working on that task, or when you mark the task 
done, the clock is
 stopped and the corresponding time interval is recorded.  It also computes
 the total time spent on each address@hidden only works if all
 headings are indented with less than 30 stars.  This is a hardcoded
-limitation of @code{lmax} in @code{org-clock-sum}.} of a project.  And it
-remembers a
-history or tasks recently clocked, to that you can jump quickly between a
-number of tasks absorbing your time.
+limitation of @code{lmax} in @code{org-clock-sum}.} of a project.
+And it remembers a history or tasks recently clocked, so that you can jump
+quickly between a number of tasks absorbing your time.
 
 To save the clock history across Emacs sessions, use
 @lisp
@@ -6352,7 +6486,7 @@ what to do with it.
 * Resolving idle time::         Resolving time when you've been idle
 @end menu
 
address@hidden Clocking commands, The clock table, Clocking work time, Clocking 
work time
address@hidden Clocking commands
 @subsection Clocking commands
 
 @table @kbd
@@ -6387,7 +6521,7 @@ reset of the task @footnote{as recorded by the 
@code{LAST_REPEAT} property}
 will be shown.  More control over what time is shown can be exercised with
 the @code{CLOCK_MODELINE_TOTAL} property.  It may have the values
 @code{current} to show only the current clocking instance, @code{today} to
-show all time clocked on this tasks today (see also the variable
+show all time clocked on this task today (see also the variable
 @code{org-extend-today-until}), @code{all} to include all time, or
 @code{auto} which is the address@hidden also the variable
 @address@hidden Clicking with @kbd{mouse-1} onto the
@@ -6397,7 +6531,7 @@ mode line entry will pop up a menu with clocking options.
 @vindex org-log-note-clock-out
 Stop the clock (clock-out).  This inserts another timestamp at the same
 location where the clock was last started.  It also directly computes
-the resulting time in inserts it after the time range as @samp{=>
+the resulting time and inserts it after the time range as @samp{=>
 HH:MM}.  See the variable @code{org-log-note-clock-out} for the
 possibility to record an additional note together with the clock-out
 address@hidden corresponding in-buffer setting is:
@@ -6449,10 +6583,10 @@ the agenda (@pxref{Weekly/daily agenda}) to show which 
tasks have been
 worked on or closed during a day.
 
 @strong{Important:} note that both @code{org-clock-out} and
address@hidden can have a global keybinding and will not
address@hidden can have a global key binding and will not
 modify the window disposition.
 
address@hidden The clock table, Resolving idle time, Clocking commands, 
Clocking work time
address@hidden The clock table
 @subsection The clock table
 @cindex clocktable, dynamic block
 @cindex report, of clocked time
@@ -6492,7 +6626,7 @@ buffer with the @kbd{C-c C-x C-r} command:
 @end example
 @noindent
 @vindex org-clocktable-defaults
-The @samp{BEGIN} line and specify a number of options to define the scope,
+The @samp{BEGIN} line specifies a number of options to define the scope,
 structure, and formatting of the report.  Defaults for all these options can
 be configured in the variable @code{org-clocktable-defaults}.
 
@@ -6512,7 +6646,7 @@ be selected:
              file-with-archives    @r{current file and its archives}
              agenda-with-archives  @r{all agenda files, including archives}
 :block       @r{The time block to consider.  This block is specified either}
-             @r{absolute, or relative to the current time and may be any of}
+             @r{absolutely, or relative to the current time and may be any of}
              @r{these formats:}
              2007-12-31    @r{New year eve 2007}
              2007-12       @r{December 2007}
@@ -6523,6 +6657,7 @@ be selected:
              thisweek, lastweek, address@hidden     @r{a relative week}
              thismonth, lastmonth, address@hidden  @r{a relative month}
              thisyear, lastyear, address@hidden     @r{a relative year}
+             untilnow
              @r{Use @address@hidden/@key{right}} keys to shift the time 
interval.}
 :tstart      @r{A time string specifying when to start considering times.}
              @r{Relative times like @code{"<-2w>"} can also be used.  See}
@@ -6541,7 +6676,7 @@ be selected:
              @address@hidden tags and properties} for the match syntax.}
 @end example
 
-Then there are options which determine the formatting of the table.  There
+Then there are options which determine the formatting of the table.  These
 options are interpreted by the function @code{org-clocktable-write-default},
 but you can specify your own function using the @code{:formatter} parameter.
 @example
@@ -6555,6 +6690,8 @@ but you can specify your own function using the 
@code{:formatter} parameter.
 :tcolumns    @r{Number of columns to be used for times.  If this is smaller}
              @r{than @code{:maxlevel}, lower levels will be lumped into one 
column.}
 :level       @r{Should a level number column be included?}
+:sort        @r{A cons cell like containing the column to sort and a sorting 
type.}
+             @r{E.g., @code{:sort (1 . ?a)} sorts the first column 
alphabetically.}
 :compact     @r{Abbreviation for @code{:level nil :indent t :narrow 40! 
:tcolumns 1}}
              @r{All are overwritten except if there is an explicit 
@code{:narrow}}
 :timestamp   @r{A timestamp for the entry, when available.  Look for 
SCHEDULED,}
@@ -6600,7 +6737,7 @@ would be
 #+END: clocktable
 @end example
 
address@hidden Resolving idle time,  , The clock table, Clocking work time
address@hidden Resolving idle time
 @subsection Resolving idle time and continuous clocking
 
 @subsubheading Resolving idle time
@@ -6616,7 +6753,7 @@ applying it to another one.
 @vindex org-clock-idle-time
 By customizing the variable @code{org-clock-idle-time} to some integer, such
 as 10 or 15, Emacs can alert you when you get back to your computer after
-being idle for that many address@hidden computers using macOS,
+being idle for that many address@hidden computers using Mac OS X,
 idleness is based on actual user idleness, not just Emacs' idle time.  For
 X11, you can install a utility program @file{x11idle.c}, available in the
 @code{contrib/scripts} directory of the Org git distribution, or install the
@@ -6685,20 +6822,18 @@ last clocked entry for this session, and start the new 
clock from there.
 If you only want this from time to time, use three universal prefix arguments
 with @code{org-clock-in} and two @kbd{C-u C-u} with @code{org-clock-in-last}.
 
address@hidden Effort estimates, Relative timer, Clocking work time, Dates and 
Times
address@hidden Effort estimates
 @section Effort estimates
 @cindex effort estimates
 
 @cindex property, Effort
address@hidden org-effort-property
 If you want to plan your work in a very detailed way, or if you need to
 produce offers with quotations of the estimated work effort, you may want to
 assign effort estimates to entries.  If you are also clocking your work, you
-may later want to compare the planned effort with the actual working time, a
-great way to improve planning estimates.  Effort estimates are stored in a
-special property @address@hidden may change the property being
-used with the variable @code{org-effort-property}.}.  You can set the effort
-for an entry with the following commands:
+may later want to compare the planned effort with the actual working time,
+a great way to improve planning estimates.  Effort estimates are stored in
+a special property @code{EFFORT}.  You can set the effort for an entry with
+the following commands:
 
 @table @kbd
 @orgcmd{C-c C-x e,org-set-effort}
@@ -6748,61 +6883,57 @@ with the @kbd{/} key in the agenda (@pxref{Agenda 
commands}).  If you have
 these estimates defined consistently, two or three key presses will narrow
 down the list to stuff that fits into an available time slot.
 
address@hidden Relative timer, Countdown timer, Effort estimates, Dates and 
Times
address@hidden Taking notes with a relative timer
address@hidden Timers
address@hidden Taking notes with a timer
 @cindex relative timer
address@hidden countdown timer
address@hidden ;
+
+Org provides two types of timers.  There is a relative timer that counts up,
+which can be useful when taking notes during, for example, a meeting or
+a video viewing.  There is also a countdown timer.
+
+The relative and countdown are started with separate commands.
 
-When taking notes during, for example, a meeting or a video viewing, it can
-be useful to have access to times relative to a starting time.  Org provides
-such a relative timer and make it easy to create timed notes.
address@hidden @kbd
address@hidden C-x 0,org-timer-start}
+Start or reset the relative timer.  By default, the timer is set to 0.  When
+called with a @kbd{C-u} prefix, prompt the user for a starting offset.  If
+there is a timer string at point, this is taken as the default, providing a
+convenient way to restart taking notes after a break in the process.  When
+called with a double prefix argument @kbd{C-u C-u}, change all timer strings
+in the active region by a certain amount.  This can be used to fix timer
+strings if the timer was not started at exactly the right moment.
address@hidden C-x ;,org-timer-set-timer}
+Start a countdown timer.  The user is prompted for a duration.
address@hidden sets the default countdown value.  Giving
+a numeric prefix argument overrides this default value.  This command is
+available as @kbd{;} in agenda buffers.
address@hidden table
+
+Once started, relative and countdown timers are controlled with the same
+commands.
 
 @table @kbd
 @orgcmd{C-c C-x .,org-timer}
-Insert a relative time into the buffer.  The first time you use this, the
-timer will be started.  When called with a prefix argument, the timer is
-restarted.
+Insert the value of the current relative or countdown timer into the buffer.
+If no timer is running, the relative timer will be started.  When called with
+a prefix argument, the relative timer is restarted.
 @orgcmd{C-c C-x -,org-timer-item}
-Insert a description list item with the current relative time.  With a prefix
-argument, first reset the timer to 0.
+Insert a description list item with the value of the current relative or
+countdown timer.  With a prefix argument, first reset the relative timer to
+0.
 @address@hidden,org-insert-heading}
 Once the timer list is started, you can also use @address@hidden to insert
 new timer items.
address@hidden for key sequences with a comma, command name macros fail :(
address@hidden C-c C-x ,
address@hidden C-c C-x ,
-Pause the timer, or continue it if it is already paused
-(@command{org-timer-pause-or-continue}).
address@hidden removed the sentence because it is redundant to the following 
item
address@hidden C-u C-c C-x ,
address@hidden C-u C-c C-x ,
address@hidden C-x @comma{},org-timer-pause-or-continue}
+Pause the timer, or continue it if it is already paused.
address@hidden C-x _,org-timer-stop}
 Stop the timer.  After this, you can only start a new timer, not continue the
 old one.  This command also removes the timer from the mode line.
address@hidden C-x 0,org-timer-start}
-Reset the timer without inserting anything into the buffer.  By default, the
-timer is reset to 0.  When called with a @kbd{C-u} prefix, reset the timer to
-specific starting offset.  The user is prompted for the offset, with a
-default taken from a timer string at point, if any, So this can be used to
-restart taking notes after a break in the process.  When called with a double
-prefix argument @kbd{C-u C-u}, change all timer strings in the active region
-by a certain amount.  This can be used to fix timer strings if the timer was
-not started at exactly the right moment.
 @end table
 
address@hidden Countdown timer,  , Relative timer, Dates and Times
address@hidden Countdown timer
address@hidden Countdown timer
address@hidden C-c C-x ;
address@hidden ;
-
-Calling @code{org-timer-set-timer} from an Org mode buffer runs a countdown
-timer.  Use @kbd{;} from agenda buffers, @key{C-c C-x ;} everywhere else.
-
address@hidden prompts the user for a duration and displays a
-countdown timer in the modeline.  @code{org-timer-default-timer} sets the
-default countdown value.  Giving a prefix numeric argument overrides this
-default value.
-
address@hidden Capture - Refile - Archive, Agenda Views, Dates and Times, Top
address@hidden Capture - Refile - Archive
 @chapter Capture - Refile - Archive
 @cindex capture
 
@@ -6816,13 +6947,13 @@ trees to an archive file keeps the system compact and 
fast.
 @menu
 * Capture::                     Capturing new stuff
 * Attachments::                 Add files to tasks
-* RSS Feeds::                   Getting input from RSS feeds
+* RSS feeds::                   Getting input from RSS feeds
 * Protocols::                   External (e.g., Browser) access to Emacs and 
Org
 * Refile and copy::             Moving/copying a tree from one place to another
 * Archiving::                   What to do with finished projects
 @end menu
 
address@hidden Capture, Attachments, Capture - Refile - Archive, Capture - 
Refile - Archive
address@hidden Capture
 @section Capture
 @cindex capture
 
@@ -6849,7 +6980,7 @@ customization.
 * Capture templates::           Define the outline of different note types
 @end menu
 
address@hidden Setting up capture, Using capture, Capture, Capture
address@hidden Setting up capture
 @subsection Setting up capture
 
 The following customization sets a default target file for notes, and defines
@@ -6864,12 +6995,12 @@ suggestion.}  for capturing new material.
 @end group
 @end smalllisp
 
address@hidden Using capture, Capture templates, Setting up capture, Capture
address@hidden Using capture
 @subsection Using capture
 
 @table @kbd
 @orgcmd{C-c c,org-capture}
-Call the command @code{org-capture}.  Note that this keybinding is global and
+Call the command @code{org-capture}.  Note that this key binding is global and
 not active by default: you need to install it.  If you have templates
 @cindex date tree
 defined @pxref{Capture templates}, it will offer these templates for
@@ -6921,7 +7052,7 @@ automatically be created unless you set 
@code{org-capture-bookmark} to
 To insert the capture at point in an Org buffer, call @code{org-capture} with
 a @code{C-0} prefix argument.
 
address@hidden Capture templates,  , Using capture, Capture
address@hidden Capture templates
 @subsection Capture templates
 @cindex templates, for Capture
 
@@ -6980,7 +7111,7 @@ like this:
 * Templates in contexts::       Only show a template in a specific context
 @end menu
 
address@hidden Template elements, Template expansion, Capture templates, 
Capture templates
address@hidden Template elements
 @subsubsection Template elements
 
 Now lets look at the elements of a template definition.  Each entry in
@@ -7032,7 +7163,9 @@ files, targets usually define a node.  Entries will 
become children of this
 node.  Other types will be added to the table or list in the body of this
 node.  Most target specifications contain a file name.  If that file name is
 the empty string, it defaults to @code{org-default-notes-file}.  A file can
-also be given as a variable, function, or Emacs Lisp form.
+also be given as a variable or as a function called with no argument.  When
+an absolute path is not specified for a target, it is taken as relative to
address@hidden
 
 Valid values are:
 
@@ -7061,6 +7194,13 @@ one matched.}.
 @item (file+datetree+prompt "path/to/file")
 Will create a heading in a date tree, but will prompt for the date.
 
address@hidden (file+weektree "path/to/file")
+Will create a heading in a week tree for today's date.  Week trees are sorted
+by week and not by month unlike datetrees.
+
address@hidden (file+weektree+prompt "path/to/file")
+Will create a heading in a week tree, but will prompt for the date.
+
 @item (file+function "path/to/file" function-finding-location)
 A function to find the right location in the file.
 
@@ -7068,8 +7208,8 @@ A function to find the right location in the file.
 File to the entry that is currently being clocked.
 
 @item (function function-finding-location)
-Most general way, write your own function to find both
-file and location.
+Most general way: write your own function which both visits
+the file and moves point to the right location.
 @end table
 
 @item template
@@ -7117,9 +7257,10 @@ narrow it so that you only see the new material.
 
 @item :table-line-pos
 Specification of the location in the table where the new line should be
-inserted.  It should be a string like @code{"II-3"} meaning that the new
-line should become the third line before the second horizontal separator
-line.
+inserted. It can be a string, a variable holding a string or a function
+returning a string. The string should look like @code{"II-3"} meaning that
+the new line should become the third line before the second horizontal
+separator line.
 
 @item :kill-buffer
 If the target file was not yet visited when capture was invoked, kill the
@@ -7127,7 +7268,7 @@ buffer again after capture is completed.
 @end table
 @end table
 
address@hidden Template expansion, Templates in contexts, Template elements, 
Capture templates
address@hidden Template expansion
 @subsubsection Template expansion
 
 In the template itself, special @address@hidden you need one of
@@ -7169,7 +7310,7 @@ dynamic insertion of content.  The templates are expanded 
in the order given her
             @r{You may specify a default value and a completion table with}
             @address@hidden|default|completion2|address@hidden
             @r{The arrow keys access a prompt-specific history.}
-%\n         @r{Insert the text entered at the nth 
address@hidden@address@hidden, where @code{n} is}
+%\1 @dots{} %\N @r{Insert the text entered at the Nth 
address@hidden@address@hidden, where @code{N} is}
             @r{a number, starting from 1.}
 %?          @r{After completing the template, position cursor here.}
 @end smallexample
@@ -7187,15 +7328,15 @@ Link type                        |  Available keywords
 
---------------------------------+----------------------------------------------
 bbdb                             |  %:name %:company
 irc                              |  %:server %:port %:nick
-vm, vm-imap, wl, mh, mew, rmail  |  %:type %:subject %:message-id
-                                 |  %:from %:fromname %:fromaddress
+vm, vm-imap, wl, mh, mew, rmail, |  %:type %:subject %:message-id
+gnus, notmuch                    |  %:from %:fromname %:fromaddress
                                  |  %:to   %:toname   %:toaddress
                                  |  %:date @r{(message date header field)}
                                  |  %:date-timestamp @r{(date as active 
timestamp)}
                                  |  %:date-timestamp-inactive @r{(date as 
inactive timestamp)}
                                  |  %:fromto @r{(either "to NAME" or "from 
NAME")@footnote{This will always be the other, not the user.  See the variable 
@code{org-from-is-user-regexp}.}}
 gnus                             |  %:group, @r{for messages also all email 
fields}
-w3, w3m                          |  %:url
+eww, w3, w3m                     |  %:url
 info                             |  %:file %:node
 calendar                         |  %:date
 @end smallexample
@@ -7207,7 +7348,7 @@ To place the cursor after template expansion use:
 %?          @r{After completing the template, position cursor here.}
 @end smallexample
 
address@hidden Templates in contexts,  , Template expansion, Capture templates
address@hidden Templates in contexts
 @subsubsection Templates in contexts
 
 @vindex org-capture-templates-contexts
@@ -7231,7 +7372,7 @@ template.  In that case, add this command key like this:
 
 See the docstring of the variable for more information.
 
address@hidden Attachments, RSS Feeds, Capture, Capture - Refile - Archive
address@hidden Attachments
 @section Attachments
 @cindex attachments
 
@@ -7319,7 +7460,7 @@ same directory for attachments as the parent does.
 @end table
 @end table
 
address@hidden RSS Feeds, Protocols, Attachments, Capture - Refile - Archive
address@hidden RSS feeds
 @section RSS feeds
 @cindex RSS feeds
 @cindex Atom feeds
@@ -7357,17 +7498,12 @@ Prompt for a feed name and go to the inbox configured 
for this feed.
 
 Under the same headline, Org will create a drawer @samp{FEEDSTATUS} in which
 it will store information about the status of items in the feed, to avoid
-adding the same item several times.  You should add @samp{FEEDSTATUS} to the
-list of drawers in that file:
-
address@hidden
-#+DRAWERS: LOGBOOK PROPERTIES FEEDSTATUS
address@hidden example
+adding the same item several times.
 
 For more information, including how to read atom feeds, see
 @file{org-feed.el} and the docstring of @code{org-feed-alist}.
 
address@hidden Protocols, Refile and copy, RSS Feeds, Capture - Refile - Archive
address@hidden Protocols
 @section Protocols for external access
 @cindex protocols, for external access
 @cindex emacsserver
@@ -7381,7 +7517,7 @@ a remote website you are looking at with the browser.  See
 @uref{http://orgmode.org/worg/org-contrib/org-protocol.php} for detailed
 documentation and setup instructions.
 
address@hidden Refile and copy, Archiving, Protocols, Capture - Refile - Archive
address@hidden Refile and copy
 @section Refile and copy
 @cindex refiling notes
 @cindex copying notes
@@ -7438,7 +7574,7 @@ setting @code{org-refile-use-cache}.  To make the command 
see new possible
 targets, you have to clear the cache with this command.
 @end table
 
address@hidden Archiving,  , Refile and copy, Capture - Refile - Archive
address@hidden Archiving
 @section Archiving
 @cindex archiving
 
@@ -7459,7 +7595,7 @@ Archive the current entry using the command specified in 
the variable
 * Internal archiving::          Switch off a tree but keep it in the file
 @end menu
 
address@hidden Moving subtrees, Internal archiving, Archiving, Archiving
address@hidden Moving subtrees
 @subsection Moving a tree to the archive file
 @cindex external archiving
 
@@ -7477,6 +7613,10 @@ the archive.  To do this, each subtree is checked for 
open TODO entries.
 If none are found, the command offers to move it to the archive
 location.  If the cursor is @emph{not} on a headline when this command
 is invoked, the level 1 trees will be checked.
address@hidden C-u C-c C-x C-s}
+As above, but check subtree for timestamps instead of TODO entries.  The
+command will offer to archive the subtree if it @emph{does} contain a
+timestamp, and that timestamp is in the past.
 @end table
 
 @cindex archive locations
@@ -7488,14 +7628,7 @@ For information and examples on how to specify the file 
and the heading,
 see the documentation string of the variable
 @code{org-archive-location}.
 
-There is also an in-buffer option for setting this variable, for
address@hidden backward compatibility, the following also works:
-If there are several such lines in a file, each specifies the archive
-location for the text below it.  The first such line also applies to any
-text before its definition.  However, using this method is
address@hidden deprecated as it is incompatible with the outline
-structure of the document.  The correct method for setting multiple
-archive locations in a buffer is using properties.}:
+There is also an in-buffer option for setting this variable, for example:
 
 @cindex #+ARCHIVE
 @example
@@ -7506,7 +7639,7 @@ archive locations in a buffer is using properties.}:
 @noindent
 If you would like to have a special ARCHIVE location for a single entry
 or a (sub)tree, give the entry an @code{:ARCHIVE:} property with the
-location as the value (@pxref{Properties and Columns}).
+location as the value (@pxref{Properties and columns}).
 
 @vindex org-archive-save-context-info
 When a subtree is moved, it receives a number of special properties that
@@ -7516,14 +7649,15 @@ outline path the archiving time etc.  Configure the 
variable
 added.
 
 
address@hidden Internal archiving,  , Moving subtrees, Archiving
address@hidden Internal archiving
 @subsection Internal archiving
 
-If you want to just switch off (for agenda views) certain subtrees without
-moving them to a different file, you can use the @code{ARCHIVE tag}.
address@hidden archive tag
+If you want to just switch off---for agenda views---certain subtrees without
+moving them to a different file, you can use the archive tag.
 
-A headline that is marked with the ARCHIVE tag (@pxref{Tags}) stays at
-its location in the outline tree, but behaves in the following way:
+A headline that is marked with the @samp{:ARCHIVE:} tag (@pxref{Tags}) stays
+at its location in the outline tree, but behaves in the following way:
 @itemize @minus
 @item
 @vindex org-cycle-open-archived-trees
@@ -7539,7 +7673,7 @@ archived subtrees are not exposed, unless you configure 
the option
 @code{org-sparse-tree-open-archived-trees}.
 @item
 @vindex org-agenda-skip-archived-trees
-During agenda view construction (@pxref{Agenda Views}), the content of
+During agenda view construction (@pxref{Agenda views}), the content of
 archived trees is ignored unless you configure the option
 @code{org-agenda-skip-archived-trees}, in which case these trees will always
 be included.  In the agenda you can press @kbd{v a} to get archives
@@ -7579,7 +7713,7 @@ outline.
 @end table
 
 
address@hidden Agenda Views, Markup, Capture - Refile - Archive, Top
address@hidden Agenda views
 @chapter Agenda views
 @cindex agenda views
 
@@ -7622,6 +7756,15 @@ buffer}.  This buffer is read-only, but provides 
commands to visit the
 corresponding locations in the original Org files, and even to
 edit these files remotely.
 
address@hidden org-agenda-skip-comment-trees
address@hidden org-agenda-skip-archived-trees
address@hidden commented entries, in agenda views
address@hidden archived entries, in agenda views
+By default, the report ignores commented (@pxref{Comment lines}) and archived
+(@pxref{Internal archiving}) entries.  You can override this by setting
address@hidden and
address@hidden to @code{nil}.
+
 @vindex org-agenda-window-setup
 @vindex org-agenda-restore-windows-after-quit
 Two variables control how the agenda buffer is displayed and whether the
@@ -7636,11 +7779,11 @@ window configuration is restored when the agenda exits:
 * Presentation and sorting::    How agenda items are prepared for display
 * Agenda commands::             Remote editing of Org trees
 * Custom agenda views::         Defining special searches and views
-* Exporting Agenda Views::      Writing a view to a file
+* Exporting agenda views::      Writing a view to a file
 * Agenda column view::          Using column view for collected entries
 @end menu
 
address@hidden Agenda files, Agenda dispatcher, Agenda Views, Agenda Views
address@hidden Agenda files
 @section Agenda files
 @cindex agenda files
 @cindex files for agenda
@@ -7717,7 +7860,7 @@ effect immediately.
 Lift the restriction.
 @end table
 
address@hidden Agenda dispatcher, Built-in agenda views, Agenda files, Agenda 
Views
address@hidden Agenda dispatcher
 @section The agenda dispatcher
 @cindex agenda dispatcher
 @cindex dispatching agenda commands
@@ -7763,15 +7906,17 @@ current region/subtree.}.  After pressing @kbd{< <}, 
you still need to press the
 character selecting the command.
 
 @item *
address@hidden agenda, sticky
 @vindex org-agenda-sticky
 Toggle sticky agenda views.  By default, Org maintains only a single agenda
 buffer and rebuilds it each time you change the view, to make sure everything
-is always up to date.  If you switch between views often and the build time
-bothers you, you can turn on sticky agenda buffers (make this the default by
-customizing the variable @code{org-agenda-sticky}).  With sticky agendas, the
-dispatcher only switches to the selected view, you need to update it by hand
-with @kbd{r} or @kbd{g}.  You can toggle sticky agenda view any time with
address@hidden
+is always up to date.  If you often switch between agenda views and the build
+time bothers you, you can turn on sticky agenda buffers or make this the
+default by customizing the variable @code{org-agenda-sticky}.  With sticky
+agendas, the agenda dispatcher will not recreate agenda views from scratch,
+it will only switch to the selected one, and you need to update the agenda by
+hand with @kbd{r} or @kbd{g} when needed.  You can toggle sticky agenda view
+any time with @code{org-toggle-sticky-agenda}.
 @end table
 
 You can also define custom commands that will be accessible through the
@@ -7780,7 +7925,7 @@ possibility to create extended agenda buffers that 
contain several
 blocks together, for example the weekly agenda, the global TODO list and
 a number of special tags matches.  @xref{Custom agenda views}.
 
address@hidden Built-in agenda views, Presentation and sorting, Agenda 
dispatcher, Agenda Views
address@hidden Built-in agenda views
 @section The built-in agenda views
 
 In this section we describe the built-in views.
@@ -7794,7 +7939,7 @@ In this section we describe the built-in views.
 * Stuck projects::              Find projects you need to review
 @end menu
 
address@hidden Weekly/daily agenda, Global TODO list, Built-in agenda views, 
Built-in agenda views
address@hidden Weekly/daily agenda
 @subsection The weekly/daily agenda
 @cindex agenda
 @cindex weekly agenda
@@ -7872,10 +8017,16 @@ the following segment of an Org file will be processed 
and entries
 will be made in the agenda:
 
 @example
-* Birthdays and similar stuff
-#+CATEGORY: Holiday
+* Holidays
+  :PROPERTIES:
+  :CATEGORY: Holiday
+  :END:
 %%(org-calendar-holiday)   ; special function for holiday names
-#+CATEGORY: Ann
+
+* Birthdays
+  :PROPERTIES:
+  :CATEGORY: Ann
+  :END:
 %%(org-anniversary 1956  5 14)@address@hidden is just like 
@code{diary-anniversary}, but the argument order is always according to ISO and 
therefore independent of the value of @code{calendar-date-style}.} Arthur Dent 
is %d years old
 %%(org-anniversary 1869 10  2) Mahatma Gandhi would be %d years old
 @end example
@@ -7919,6 +8070,20 @@ hash with anniversaries.  However, from then on things 
will be very fast---much
 faster in fact than a long list of @samp{%%(diary-anniversary)} entries
 in an Org or Diary file.
 
+If you would like to see upcoming anniversaries with a bit of forewarning,
+you can use the following instead:
+
address@hidden
+* Anniversaries
+  :PROPERTIES:
+  :CATEGORY: Anniv
+  :END:
+%%(org-bbdb-anniversaries-future 3)
address@hidden example
+
+That will give you three days' warning: on the anniversary date itself and the
+two days prior. The argument is optional: if omitted, it defaults to 7.
+
 @subsubheading Appointment reminders
 @cindex @file{appt.el}
 @cindex appointment reminders
@@ -7933,7 +8098,7 @@ It also reads a @code{APPT_WARNTIME} property which will 
then override the
 value of @code{appt-message-warning-time} for this appointment.  See the
 docstring for details.
 
address@hidden Global TODO list, Matching tags and properties, Weekly/daily 
agenda, Built-in agenda views
address@hidden Global TODO list
 @subsection The global TODO list
 @cindex global TODO list
 @cindex TODO list, global
@@ -7944,7 +8109,7 @@ collected into a single place.
 @table @kbd
 @orgcmd{C-c a t,org-todo-list}
 Show the global TODO list.  This collects the TODO items from all agenda
-files (@pxref{Agenda Views}) into a single buffer.  By default, this lists
+files (@pxref{Agenda views}) into a single buffer.  By default, this lists
 items with a state the is not a DONE state.  The buffer is in
 @code{agenda-mode}, so there are commands to examine and manipulate the TODO
 entries directly from that buffer (@pxref{Agenda commands}).
@@ -7994,7 +8159,7 @@ and omit the sublevels from the global list.  Configure 
the variable
 @code{org-agenda-todo-list-sublevels} to get this behavior.
 @end itemize
 
address@hidden Matching tags and properties, Timeline, Global TODO list, 
Built-in agenda views
address@hidden Matching tags and properties
 @subsection Matching tags and properties
 @cindex matching, of tags
 @cindex matching, of properties
@@ -8002,7 +8167,7 @@ and omit the sublevels from the global list.  Configure 
the variable
 @cindex match view
 
 If headlines in the agenda files are marked with @emph{tags} (@pxref{Tags}),
-or have properties (@pxref{Properties and Columns}), you can select headlines
+or have properties (@pxref{Properties and columns}), you can select headlines
 based on this metadata and collect them into an agenda buffer.  The match
 syntax described here also applies when creating sparse trees with @kbd{C-c /
 m}.
@@ -8063,31 +8228,29 @@ braces.  For example,
 @samp{:work:} and any tag @i{starting} with @samp{boss}.
 
 @cindex group tags, as regular expressions
-Group tags (@pxref{Tag groups}) are expanded as regular expressions.  E.g.,
+Group tags (@pxref{Tag hierarchy}) are expanded as regular expressions.  E.g.,
 if @samp{:work:} is a group tag for the group @samp{:work:lab:conf:}, then
 searching for @samp{work} will search for 
@address@hidden(?:work\|lab\|conf\)@}}
 and searching for @samp{-work} will search for all headlines but those with
-one of the tag in the group (i.e., @address@hidden(?:work\|lab\|conf\)@}}).
+one of the tags in the group (i.e., @address@hidden(?:work\|lab\|conf\)@}}).
 
 @cindex TODO keyword matching, with tags search
 @cindex level, require for tags/property match
 @cindex category, require for tags/property match
 @vindex org-odd-levels-only
-You may also test for properties (@pxref{Properties and Columns}) at the same
+You may also test for properties (@pxref{Properties and columns}) at the same
 time as matching tags.  The properties may be real properties, or special
 properties that represent other metadata (@pxref{Special properties}).  For
 example, the ``property'' @code{TODO} represents the TODO keyword of the
 entry and the ``property'' @code{PRIORITY} represents the PRIORITY keyword of
-the entry.  The ITEM special property cannot currently be used in tags/property
address@hidden @pxref{x-agenda-skip-entry-regexp,
-,skipping entries based on regexp}.}.
+the entry.
 
-Except the @pxref{Special properties}, one other ``property'' can also be
-used. @code{LEVEL} represents the level of an entry.  So a search
address@hidden"DONE"} lists all level three headlines that have
-the tag @samp{boss} and are @emph{not} marked with the TODO keyword 
address@hidden
-In buffers with @code{org-odd-levels-only} set, @samp{LEVEL} does not count
-the number of stars, but @samp{LEVEL=2} will correspond to 3 stars etc.
+In addition to the properties mentioned above, @code{LEVEL} represents the
+level of an entry.  So a search @samp{+LEVEL=3+boss-TODO="DONE"} lists all
+level three headlines that have the tag @samp{boss} and are @emph{not} marked
+with the TODO keyword address@hidden  In buffers with 
@code{org-odd-levels-only} set,
address@hidden does not count the number of stars, but @samp{LEVEL=2} will
+correspond to 3 stars etc.
 
 Here are more examples:
 
@@ -8141,11 +8304,6 @@ property that is numerically smaller than 2, a 
@samp{:With:} property that is
 matched by the regular expression @samp{Sarah\|Denny}, and that are scheduled
 on or after October 11, 2008.
 
-Accessing TODO, LEVEL, and CATEGORY during a search is fast.  Accessing any
-other properties will slow down the search.  However, once you have paid the
-price by accessing one property, testing additional properties is cheap
-again.
-
 You can configure Org mode to use property inheritance during a search, but
 beware that this can slow down searches considerably.  See @ref{Property
 inheritance}, for details.
@@ -8174,7 +8332,7 @@ Select @samp{:work:}-tagged TODO lines that are either 
@samp{WAITING} or
 @samp{NEXT}.
 @end table
 
address@hidden Timeline, Search view, Matching tags and properties, Built-in 
agenda views
address@hidden Timeline
 @subsection Timeline for a single file
 @cindex timeline, single file
 @cindex time-sorted view
@@ -8194,7 +8352,7 @@ When called with a @kbd{C-u} prefix, all unfinished TODO 
entries
 The commands available in the timeline buffer are listed in
 @ref{Agenda commands}.
 
address@hidden Search view, Stuck projects, Timeline, Built-in agenda views
address@hidden Search view
 @subsection Search view
 @cindex search view
 @cindex text search
@@ -8224,7 +8382,7 @@ the docstring of the command @code{org-search-view}.
 Note that in addition to the agenda files, this command will also search
 the files listed in @code{org-agenda-text-search-extra-files}.
 
address@hidden Stuck projects,  , Search view, Built-in agenda views
address@hidden Stuck projects
 @subsection Stuck projects
 @pindex GTD, Getting Things Done
 
@@ -8272,7 +8430,7 @@ correct customization for this is
 Note that if a project is identified as non-stuck, the subtree of this entry
 will still be searched for stuck projects.
 
address@hidden Presentation and sorting, Agenda commands, Built-in agenda 
views, Agenda Views
address@hidden Presentation and sorting
 @section Presentation and sorting
 @cindex presentation, of agenda items
 
@@ -8294,21 +8452,14 @@ associated with the item.
 * Filtering/limiting agenda items::  Dynamically narrow the agenda
 @end menu
 
address@hidden Categories, Time-of-day specifications, Presentation and 
sorting, Presentation and sorting
address@hidden Categories
 @subsection Categories
 
 @cindex category
 @cindex #+CATEGORY
-The category is a broad label assigned to each agenda item.  By default,
-the category is simply derived from the file name, but you can also
-specify it with a special line in the buffer, like address@hidden
-backward compatibility, the following also works: if there are several
-such lines in a file, each specifies the category for the text below it.
-The first category also applies to any text before the first CATEGORY
-line.  However, using this method is @emph{strongly} deprecated as it is
-incompatible with the outline structure of the document.  The correct
-method for setting multiple categories in a buffer is using a
-property.}:
+The category is a broad label assigned to each agenda item.  By default, the
+category is simply derived from the file name, but you can also specify it
+with a special line in the buffer, like this:
 
 @example
 #+CATEGORY: Thesis
@@ -8328,7 +8479,7 @@ longer than 10 characters.
 You can set up icons for category by customizing the
 @code{org-agenda-category-icon-alist} variable.
 
address@hidden Time-of-day specifications, Sorting agenda items, Categories, 
Presentation and sorting
address@hidden Time-of-day specifications
 @subsection Time-of-day specifications
 @cindex time-of-day specification
 
@@ -8379,7 +8530,7 @@ The time grid can be turned on and off with the variable
 @code{org-agenda-use-time-grid}, and can be configured with
 @code{org-agenda-time-grid}.
 
address@hidden Sorting agenda items, Filtering/limiting agenda items, 
Time-of-day specifications, Presentation and sorting
address@hidden Sorting agenda items
 @subsection Sorting agenda items
 @cindex sorting, of agenda items
 @cindex priorities, of agenda items
@@ -8413,14 +8564,14 @@ Sorting can be customized using the variable
 @code{org-agenda-sorting-strategy}, and may also include criteria based on
 the estimated effort of an entry (@pxref{Effort estimates}).
 
address@hidden Filtering/limiting agenda items,  , Sorting agenda items, 
Presentation and sorting
address@hidden Filtering/limiting agenda items
 @subsection Filtering/limiting agenda items
 
 Agenda built-in or customized commands are statically defined.  Agenda
 filters and limits provide two ways of dynamically narrowing down the list of
-agenda entries: @emph{fitlers} and @emph{limits}.  Filters only act on the
+agenda entries: @emph{filters} and @emph{limits}.  Filters only act on the
 display of the items, while limits take effect before the list of agenda
-entries is built.  Filter are more often used interactively, while limits are
+entries is built.  Filters are more often used interactively, while limits are
 mostly useful when defined as local variables within custom agenda commands.
 
 @subsubheading Filtering in the agenda
@@ -8444,34 +8595,14 @@ refreshes and more secondary filtering.  The filter is 
a global property of
 the entire agenda view---in a block agenda, you should only set this in the
 global options section, not in the section of an individual block.}
 
-You will be prompted for a tag selection letter; @key{SPC} will mean any tag at
-all.  Pressing @key{TAB} at that prompt will offer use completion to select a
-tag (including any tags that do not have a selection character).  The command
-then hides all entries that do not contain or inherit this tag.  When called
-with prefix arg, remove the entries that @emph{do} have the tag.  A second
address@hidden/} at the prompt will turn off the filter and unhide any hidden 
entries.
-If the first key you press is either @kbd{+} or @kbd{-}, the previous filter
-will be narrowed by requiring or forbidding the selected additional tag.
-Instead of pressing @kbd{+} or @kbd{-} after @kbd{/}, you can also
-immediately use the @kbd{\} command.
-
address@hidden org-sort-agenda-noeffort-is-high
-In order to filter for effort estimates, you should set up allowed
-efforts globally, for example
address@hidden
-(setq org-global-properties
-    '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
address@hidden lisp
-You can then filter for an effort by first typing an operator, one of
address@hidden<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an 
effort
-estimate in your array of allowed values, where @kbd{0} means the 10th value.
-The filter will then restrict to entries with effort smaller-or-equal, equal,
-or larger-or-equal than the selected value.  If the digits 0--9 are not used
-as fast access keys to tags, you can also simply press the index digit
-directly without an operator.  In this case, @kbd{<} will be assumed.  For
-application of the operator, entries without a defined effort will be treated
-according to the value of @code{org-sort-agenda-noeffort-is-high}.  To filter
-for tasks without effort definition, press @kbd{?} as the operator.
+You will be prompted for a tag selection letter; @key{SPC} will mean any tag
+at all.  Pressing @key{TAB} at that prompt will offer use completion to
+select a tag (including any tags that do not have a selection character).
+The command then hides all entries that do not contain or inherit this tag.
+When called with prefix arg, remove the entries that @emph{do} have the tag.
+A second @kbd{/} at the prompt will turn off the filter and unhide any hidden
+entries.  Pressing @kbd{+} or @kbd{-} switches between filtering and
+excluding the next tag.
 
 Org also supports automatic, context-aware tag filtering.  If the variable
 @code{org-agenda-auto-exclude-function} is set to a user-defined function,
@@ -8499,12 +8630,6 @@ Internet, and outside of business hours, with something 
like this:
 @end group
 @end smalllisp
 
address@hidden,org-agenda-filter-by-tag-refine}
-Narrow the current agenda filter by an additional condition.  When called with
-prefix arg, remove the entries that @emph{do} have the tag, or that do match
-the effort criterion.  You can achieve the same effect by pressing @kbd{+} or
address@hidden as the first key after the @kbd{/} command.
-
 @c
 @kindex [
 @kindex ]
@@ -8525,9 +8650,12 @@ selected.
 @vindex org-agenda-category-filter-preset
 
 Filter the current agenda view with respect to the category of the item at
-point.  Pressing @code{<} another time will remove this filter.  You can add
-a filter preset through the option @code{org-agenda-category-filter-preset}
-(see below.)
+point.  Pressing @code{<} another time will remove this filter.  When called
+with a prefix argument exclude the category of the item at point from the
+agenda.
+
+You can add a filter preset in custom agenda commands through the option
address@hidden  @xref{Setting options}.
 
 @orgcmd{^,org-agenda-filter-by-top-headline}
 Filter the current agenda view and only display the siblings and the parent
@@ -8540,8 +8668,34 @@ Filter the agenda view by a regular expression: only 
show agenda entries
 matching the regular expression the user entered.  When called with a prefix
 argument, it will filter @emph{out} entries matching the regexp.  With two
 universal prefix arguments, it will remove all the regexp filters, which can
-be accumulated.  You can add a filter preset through the option
address@hidden (see below.)
+be accumulated.
+
+You can add a filter preset in custom agenda commands through the option
address@hidden  @xref{Setting options}.
+
address@hidden,org-agenda-filter-by-effort}
address@hidden org-agenda-effort-filter-preset
address@hidden org-sort-agenda-noeffort-is-high
+Filter the agenda view with respect to effort estimates.
+You first need to set up allowed efforts globally, for example
address@hidden
+(setq org-global-properties
+    '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
address@hidden lisp
+You can then filter for an effort by first typing an operator, one of
address@hidden<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an 
effort
+estimate in your array of allowed values, where @kbd{0} means the 10th value.
+The filter will then restrict to entries with effort smaller-or-equal, equal,
+or larger-or-equal than the selected value.  For application of the operator,
+entries without a defined effort will be treated according to the value of
address@hidden
+
+When called with a prefix argument, it will remove entries matching the
+condition.  With two universal prefix arguments, it will clear effort
+filters, which can be accumulated.
+
+You can add a filter preset in custom agenda commands through the option
address@hidden  @xref{Setting options}.
 
 @orgcmd{|,org-agenda-filter-remove-all}
 Remove all filters in the current agenda view.
@@ -8555,9 +8709,9 @@ Remove all filters in the current agenda view.
 @vindex org-agenda-max-tags
 
 Here is a list of options that you can set, either globally, or locally in
-your custom agenda address@hidden agenda views}.
+your custom agenda views (@pxref{Custom agenda views}).
 
address@hidden @var
address@hidden @code
 @item org-agenda-max-entries
 Limit the number of entries.
 @item org-agenda-max-effort
@@ -8570,7 +8724,7 @@ Limit the number of tagged entries.
 
 When set to a positive integer, each option will exclude entries from other
 categories: for example, @code{(setq org-agenda-max-effort 100)} will limit
-the agenda to 100 minutes of effort and exclude any entry that as no effort
+the agenda to 100 minutes of effort and exclude any entry that has no effort
 property.  If you want to include entries with no effort property, use a
 negative value for @code{org-agenda-max-effort}.
 
@@ -8588,15 +8742,15 @@ Once you mark one of these five entry as @code{DONE}, 
rebuilding the agenda
 will again the next five entries again, including the first entry that was
 excluded so far.
 
-You can also dynamically set temporary address@hidden temporary limits
-are lost when rebuilding the agenda.}:
+You can also dynamically set temporary limits, which will be lost when
+rebuilding the agenda:
 
 @table @kbd
 @orgcmd{~,org-agenda-limit-interactively}
 This prompts for the type of limit to apply and its value.
 @end table
 
address@hidden Agenda commands, Custom agenda views, Presentation and sorting, 
Agenda Views
address@hidden Agenda commands
 @section Commands in the agenda buffer
 @cindex commands, in agenda buffer
 
@@ -8617,11 +8771,14 @@ the other commands, the cursor needs to be in the 
desired line.
 Next line (same as @key{down} and @kbd{C-n}).
 @orgcmd{p,org-agenda-previous-line}
 Previous line (same as @key{up} and @kbd{C-p}).
address@hidden,org-agenda-next-item}
+Next item: same as next line, but only consider items.
address@hidden,org-agenda-previous-item}
+Previous item: same as previous line, but only consider items.
 @tsubheading{View/Go to Org file}
 @address@hidden,mouse-3,org-agenda-show-and-scroll-up}
-Display the original location of the item in another window.
-With prefix arg, make sure that the entire entry is made visible in the
-outline, not only the heading.
+Display the original location of the item in another window.  With prefix
+arg, make sure that drawers stay folded.
 @c
 @orgcmd{L,org-agenda-recenter}
 Display original location and recenter that window.
@@ -8719,6 +8876,7 @@ agenda and timeline views.
 @c
 @orgcmd{v a,org-agenda-archives-mode}
 @xorgcmd{v A,org-agenda-archives-mode 'files}
address@hidden Archives mode
 Toggle Archives mode.  In Archives mode, trees that are marked
 @code{ARCHIVED} are also scanned when producing the agenda.  When you use the
 capital @kbd{A}, even all archive files are included.  To exit archives mode,
@@ -8789,35 +8947,25 @@ file or subtree (@pxref{Agenda files}).
 
 @tsubheading{Secondary filtering and query editing}
 
-For a detailed description of these commands, see @pxref{Filtering/limiting
+For a detailed description of these commands, @pxref{Filtering/limiting
 agenda items}.
 
 @orgcmd{/,org-agenda-filter-by-tag}
address@hidden org-agenda-tag-filter-preset
 Filter the agenda view with respect to a tag and/or effort estimates.
 
address@hidden,org-agenda-filter-by-tag-refine}
-Narrow the current agenda filter by an additional condition.
-
 @orgcmd{<,org-agenda-filter-by-category}
address@hidden org-agenda-category-filter-preset
-
 Filter the current agenda view with respect to the category of the item at
-point.  Pressing @code{<} another time will remove this filter.
+point.
 
 @orgcmd{^,org-agenda-filter-by-top-headline}
 Filter the current agenda view and only display the siblings and the parent
 headline of the one at point.
 
 @orgcmd{=,org-agenda-filter-by-regexp}
address@hidden org-agenda-regexp-filter-preset
+Filter the agenda view by a regular expression.
 
-Filter the agenda view by a regular expression: only show agenda entries
-matching the regular expression the user entered.  When called with a prefix
-argument, it will filter @emph{out} entries matching the regexp.  With two
-universal prefix arguments, it will remove all the regexp filters, which can
-be accumulated.  You can add a filter preset through the option
address@hidden (see below.)
address@hidden,org-agenda-filter-by-effort}
+Filter the agenda view with respect to effort estimates.
 
 @orgcmd{|,org-agenda-filter-remove-all}
 Remove all filters in the current agenda view.
@@ -8996,8 +9144,8 @@ Bulk action: act on all marked entries in the agenda.  
This will prompt for
 another key to select the action to be applied.  The prefix arg to @kbd{B}
 will be passed through to the @kbd{s} and @kbd{d} commands, to bulk-remove
 these special timestamps.  By default, marks are removed after the bulk.  If
-you want them to persist, set @code{org-agenda-bulk-persistent-marks} to
address@hidden or hit @kbd{p} at the prompt.
+you want them to persist, set @code{org-agenda-persistent-marks} to @code{t}
+or hit @kbd{p} at the prompt.
 
 @table @kbd
 @item *
@@ -9124,7 +9272,7 @@ visit Org files will not be removed.
 @end table
 
 
address@hidden Custom agenda views, Exporting Agenda Views, Agenda commands, 
Agenda Views
address@hidden Custom agenda views
 @section Custom agenda views
 @cindex custom agenda views
 @cindex agenda views, custom
@@ -9137,10 +9285,10 @@ dispatcher (@pxref{Agenda dispatcher}), just like the 
default commands.
 @menu
 * Storing searches::            Type once, use often
 * Block agenda::                All the stuff you need in a single buffer
-* Setting Options::             Changing the rules
+* Setting options::             Changing the rules
 @end menu
 
address@hidden Storing searches, Block agenda, Custom agenda views, Custom 
agenda views
address@hidden Storing searches
 @subsection Storing searches
 
 The first application of custom searches is the definition of keyboard
@@ -9162,7 +9310,7 @@ buffer).
 Custom commands are configured in the variable
 @code{org-agenda-custom-commands}.  You can customize this variable, for
 example by pressing @kbd{C-c a C}.  You can also directly set it with Emacs
-Lisp in @file{.emacs}.  The following example contains all valid agenda
+Lisp in the Emacs init file.  The following example contains all valid agenda
 views:
 
 @lisp
@@ -9232,7 +9380,7 @@ Peter, or Kim) as additional tag to match.
 Note that the @code{*-tree} agenda views need to be called from an
 Org buffer as they operate on the current buffer only.
 
address@hidden Block agenda, Setting Options, Storing searches, Custom agenda 
views
address@hidden Block agenda
 @subsection Block agenda
 @cindex block agenda
 @cindex agenda, with block views
@@ -9266,7 +9414,7 @@ your agenda for the current week, all TODO items that 
carry the tag
 @samp{home}, and also all lines tagged with @samp{garden}.  Finally the
 command @kbd{C-c a o} provides a similar view for office tasks.
 
address@hidden Setting Options,  , Block agenda, Custom agenda views
address@hidden Setting options
 @subsection Setting options for custom commands
 @cindex options, for custom agenda views
 
@@ -9285,8 +9433,7 @@ right spot in @code{org-agenda-custom-commands}.  For 
example:
          ((org-agenda-sorting-strategy '(priority-down))
           (org-agenda-prefix-format "  Mixed: ")))
         ("U" tags-tree "+boss-urgent"
-         ((org-show-following-heading nil)
-          (org-show-hierarchy-above nil)))
+         ((org-show-context-detail 'minimal)))
         ("N" search ""
          ((org-agenda-files '("~org/notes.org"))
           (org-agenda-text-search-extra-files nil)))))
@@ -9340,7 +9487,7 @@ yourself.
 @vindex org-agenda-custom-commands-contexts
 To control whether an agenda command should be accessible from a specific
 context, you can customize @code{org-agenda-custom-commands-contexts}.  Let's
-say for example that you have an agenda commands @code{"o"} displaying a view
+say for example that you have an agenda command @code{"o"} displaying a view
 that you only need when reading emails.  Then you would configure this option
 like this:
 
@@ -9359,8 +9506,8 @@ command key @code{"r"}.  In that case, add this command 
key like this:
 
 See the docstring of the variable for more information.
 
address@hidden Exporting Agenda Views, Agenda column view, Custom agenda views, 
Agenda Views
address@hidden Exporting Agenda Views
address@hidden Exporting agenda views
address@hidden Exporting agenda views
 @cindex agenda views, exporting
 
 If you are away from your computer, it can be very useful to have a printed
@@ -9498,7 +9645,7 @@ processing by other programs.  See @ref{Extracting agenda 
information}, for
 more information.
 
 
address@hidden Agenda column view,  , Exporting Agenda Views, Agenda Views
address@hidden Agenda column view
 @section Using column view in the agenda
 @cindex column view, in agenda
 @cindex agenda, column view
@@ -9524,11 +9671,12 @@ This causes the following issues:
 Org needs to make a decision which @code{COLUMNS} format to use.  Since the
 entries in the agenda are collected from different files, and different files
 may have different @code{COLUMNS} formats, this is a non-trivial problem.
-Org first checks if the variable @code{org-agenda-overriding-columns-format} is
-currently set, and if so, takes the format from there.  Otherwise it takes
+Org first checks if the variable @code{org-agenda-overriding-columns-format}
+is currently set, and if so, takes the format from there.  Otherwise it takes
 the format associated with the first item in the agenda, or, if that item
-does not have a specific format (defined in a property, or in its file), it
+does not have a specific format---defined in a property, or in its file---it
 uses @code{org-columns-default-format}.
+
 @item
 @cindex property, special, CLOCKSUM
 If any of the columns has a summary type defined (@pxref{Column attributes}),
@@ -9537,11 +9685,12 @@ make sure that the computations of this property are up 
to date.  This is
 also true for the special @code{CLOCKSUM} property.  Org will then sum the
 values displayed in the agenda.  In the daily/weekly agenda, the sums will
 cover a single day; in all other views they cover the entire block.  It is
-vital to realize that the agenda may show the same entry @emph{twice} (for
-example as scheduled and as a deadline), and it may show two entries from the
-same hierarchy (for example a @emph{parent} and its @emph{child}).  In these
+vital to realize that the agenda may show the same entry @emph{twice}---for
+example as scheduled and as a deadline---and it may show two entries from the
+same hierarchy---for example a @emph{parent} and its @emph{child}.  In these
 cases, the summation in the agenda will lead to incorrect results because
 some values will count double.
+
 @item
 When the column view in the agenda shows the @code{CLOCKSUM}, that is always
 the entire clocked time for this item.  So even in the daily/weekly agenda,
@@ -9555,149 +9704,46 @@ the agenda).
 @item
 @cindex property, special, CLOCKSUM_T
 When the column view in the agenda shows the @code{CLOCKSUM_T}, that is
-always today's clocked time for this item.  So even in the weekly agenda,
-the clocksum listed in column view only originates from today.  This lets
-you compare the time you spent on a task for today, with the time already
-spent (via @code{CLOCKSUM}) and with the planned total effort for it.
+always today's clocked time for this item.  So even in the weekly agenda, the
+clocksum listed in column view only originates from today.  This lets you
+compare the time you spent on a task for today, with the time already
+spent ---via @code{CLOCKSUM}---and with the planned total effort for it.
 @end enumerate
 
 
address@hidden Markup, Exporting, Agenda Views, Top
address@hidden Markup
 @chapter Markup for rich export
 
 When exporting Org mode documents, the exporter tries to reflect the
 structure of the document as accurately as possible in the back-end.  Since
-export targets like HTML, @LaTeX{} allow much richer formatting, Org mode has
+export targets like HTML and @LaTeX{} allow much richer formatting, Org mode 
has
 rules on how to prepare text for rich export.  This section summarizes the
 markup rules used in an Org mode buffer.
 
 @menu
-* Structural markup elements::  The basic structure as seen by the exporter
+* Paragraphs::                  The basic unit of text
+* Emphasis and monospace::      Bold, italic, etc.
+* Horizontal rules::            Make a line
 * Images and tables::           Images, tables and caption mechanism
 * Literal examples::            Source code examples with special formatting
-* Include files::               Include additional files into a document
-* Index entries::               Making an index
-* Macro replacement::           Use macros to create templates
+* Special symbols::             Greek letters and other symbols
+* Subscripts and superscripts::  Simple syntax for raising/lowering text
 * Embedded @LaTeX{}::           LaTeX can be freely used inside Org documents
-* Special blocks::              Containers targeted at export back-ends
address@hidden menu
-
address@hidden Structural markup elements, Images and tables, Markup, Markup
address@hidden Structural markup elements
-
address@hidden
-* Document title::              Where the title is taken from
-* Headings and sections::       The document structure as seen by the exporter
-* Table of contents::           The if and where of the table of contents
-* Lists::                       Lists
-* Paragraphs::                  Paragraphs
-* Footnote markup::             Footnotes
-* Emphasis and monospace::      Bold, italic, etc.
-* Horizontal rules::            Make a line
-* Comment lines::               What will *not* be exported
 @end menu
 
address@hidden Document title, Headings and sections, Structural markup 
elements, Structural markup elements
address@hidden Document title
address@hidden document title, markup rules
-
address@hidden
-The title of the exported document is taken from the special line
-
address@hidden #+TITLE
address@hidden
-#+TITLE: This is the title of the document
address@hidden example
-
address@hidden
-If this line does not exist, the title will be the name of the file
-associated to buffer, without extension, or the buffer name.
-
address@hidden property, EXPORT_TITLE
-If you are exporting only a subtree, its heading will become the title of the
-document.  If the subtree has a property @code{EXPORT_TITLE}, that will take
-precedence.
-
address@hidden Headings and sections, Table of contents, Document title, 
Structural markup elements
address@hidden Headings and sections
address@hidden headings and sections, markup rules
-
address@hidden org-export-headline-levels
-The outline structure of the document as described in @ref{Document
-Structure}, forms the basis for defining sections of the exported document.
-However, since the outline structure is also used for (for example) lists of
-tasks, only the first three outline levels will be used as headings.  Deeper
-levels will become itemized lists.  You can change the location of this
-switch globally by setting the variable @code{org-export-headline-levels}, or 
on a
-per-file basis with a line
-
address@hidden #+OPTIONS
address@hidden
-#+OPTIONS: H:4
address@hidden example
-
address@hidden Table of contents, Lists, Headings and sections, Structural 
markup elements
address@hidden Table of contents
address@hidden table of contents, markup rules
-
address@hidden #+TOC
address@hidden org-export-with-toc
-The table of contents is normally inserted directly before the first headline
-of the file.  The depth of the table is by default the same as the number of
-headline levels, but you can choose a smaller number, or turn off the table
-of contents entirely, by configuring the variable @code{org-export-with-toc},
-or on a per-file basis with a line like
-
address@hidden
-#+OPTIONS: toc:2          (only to two levels in TOC)
-#+OPTIONS: toc:nil        (no default TOC at all)
address@hidden example
-
-If you would like to move the table of contents to a different location, you
-should turn off the default table using @code{org-export-with-toc} or
address@hidden and insert @code{#+TOC: headlines N} at the desired
-location(s).
-
address@hidden
-#+OPTIONS: toc:nil        (no default TOC)
-...
-#+TOC: headlines 2        (insert TOC here, with two headline levels)
address@hidden example
-
-Multiple @code{#+TOC: headline} lines are allowed.  The same @code{TOC}
-keyword can also generate a list of all tables (resp.@: all listings) with a
-caption in the buffer.
-
address@hidden
-#+TOC: listings           (build a list of listings)
-#+TOC: tables             (build a list of tables)
address@hidden example
-
address@hidden property, ALT_TITLE
-The headline's title usually determines its corresponding entry in a table of
-contents.  However, it is possible to specify an alternative title by
-setting @code{ALT_TITLE} property accordingly.  It will then be used when
-building the table.
-
address@hidden Lists, Paragraphs, Table of contents, Structural markup elements
address@hidden Lists
address@hidden lists, markup rules
-
-Plain lists as described in @ref{Plain lists}, are translated to the back-end's
-syntax for such lists.  Most back-ends support unordered, ordered, and
-description lists.
-
address@hidden Paragraphs, Footnote markup, Lists, Structural markup elements
address@hidden Paragraphs, line breaks, and quoting
address@hidden Paragraphs
address@hidden Paragraphs, line breaks, and quoting
 @cindex paragraphs, markup rules
 
 Paragraphs are separated by at least one empty line.  If you need to enforce
 a line break within a paragraph, use @samp{\\} at the end of a line.
 
-To keep the line breaks in a region, but otherwise use normal formatting, you
-can use this construct, which can also be used to format poetry.
+To preserve the line breaks, indentation and blank lines in a region, but
+otherwise use normal formatting, you can use this construct, which can also
+be used to format poetry.
 
 @cindex #+BEGIN_VERSE
address@hidden verse blocks
 @example
 #+BEGIN_VERSE
  Great clouds overhead
@@ -9713,6 +9759,7 @@ as a paragraph that is indented on both the left and the 
right margin.  You
 can include quotations in Org mode documents like this:
 
 @cindex #+BEGIN_QUOTE
address@hidden quote blocks
 @example
 #+BEGIN_QUOTE
 Everything should be made as simple as possible,
@@ -9722,6 +9769,7 @@ but not any simpler -- Albert Einstein
 
 If you would like to center some text, do it like this:
 @cindex #+BEGIN_CENTER
address@hidden center blocks
 @example
 #+BEGIN_CENTER
 Everything should be made as simple as possible, \\
@@ -9729,18 +9777,8 @@ but not any simpler
 #+END_CENTER
 @end example
 
-
address@hidden Footnote markup, Emphasis and monospace, Paragraphs, Structural 
markup elements
address@hidden Footnote markup
address@hidden footnotes, markup rules
address@hidden @file{footnote.el}
-
-Footnotes defined in the way described in @ref{Footnotes}, will be exported
-by all back-ends.  Org allows multiple references to the same note, and
-multiple footnotes side by side.
-
address@hidden Emphasis and monospace, Horizontal rules, Footnote markup, 
Structural markup elements
address@hidden Emphasis and monospace
address@hidden Emphasis and monospace
address@hidden Emphasis and monospace
 
 @cindex underlined text, markup rules
 @cindex bold text, markup rules
@@ -9764,32 +9802,13 @@ can tweak @code{org-emphasis-regexp-components}.  
Beware that changing one of
 the above variables will no take effect until you reload Org, for which you
 may need to restart Emacs.
 
address@hidden Horizontal rules, Comment lines, Emphasis and monospace, 
Structural markup elements
address@hidden  Horizontal rules
address@hidden Horizontal rules
address@hidden Horizontal rules
 @cindex horizontal rules, markup rules
 A line consisting of only dashes, and at least 5 of them, will be exported as
 a horizontal line.
 
address@hidden Comment lines,  , Horizontal rules, Structural markup elements
address@hidden Comment lines
address@hidden comment lines
address@hidden exporting, not
address@hidden #+BEGIN_COMMENT
-
-Lines starting with zero or more whitespace characters followed by one
address@hidden and a whitespace are treated as comments and will never be 
exported.
-Also entire subtrees starting with the word @samp{COMMENT} will never be
-exported.  Finally, regions surrounded by @samp{#+BEGIN_COMMENT}
-... @samp{#+END_COMMENT} will not be exported.
-
address@hidden @kbd
address@hidden C-c ;
address@hidden C-c ;
-Toggle the COMMENT keyword at the beginning of an entry.
address@hidden table
-
-
address@hidden Images and tables, Literal examples, Structural markup elements, 
Markup
address@hidden Images and tables
 @section Images and Tables
 
 @cindex tables, markup rules
@@ -9837,7 +9856,7 @@ the same caption mechanism can apply to many others 
(e.g., @LaTeX{}
 equations, source code blocks).  Depending on the export back-end, those may
 or may not be handled.
 
address@hidden Literal examples, Include files, Images and tables, Markup
address@hidden Literal examples
 @section Literal examples
 @cindex literal examples, markup rules
 @cindex code line references, markup rules
@@ -9865,20 +9884,25 @@ Here is an example
 @end example
 
 @cindex formatting source code, markup rules
address@hidden org-latex-listings
 If the example is source code from a programming language, or any other text
 that can be marked up by font-lock in Emacs, you can ask for the example to
 look like the fontified Emacs address@hidden works automatically for
 the HTML back-end (it requires version 1.34 of the @file{htmlize.el} package,
 which is distributed with Org).  Fontified code chunks in @LaTeX{} can be
-achieved using either the listings or the
address@hidden://code.google.com/p/minted, minted,} package.  Refer to
address@hidden documentation for details.}.  This is done
-with the @samp{src} block, where you also need to specify the name of the
-major mode that should be used to fontify the address@hidden in
address@hidden blocks may also be evaluated either interactively or on export.
-See @pxref{Working With Source Code} for more information on evaluating code
-blocks.}, see @ref{Easy Templates} for shortcuts to easily insert code
-blocks.
+achieved using either the
address@hidden://www.ctan.org/tex-archive/macros/latex/contrib/listings/?lang=en,
 listings,}
+or the
address@hidden://github.com/gpoore/minted, minted,} package.
+If you use minted or listing, you must load the packages manually, for
+example by adding the desired package to
address@hidden  Refer to @code{org-latex-listings}
+for details.}.  This is done with the @samp{src} block, where you also need
+to specify the name of the major mode that should be used to fontify the
address@hidden in @samp{src} blocks may also be evaluated either
+interactively or on export.  @xref{Working with source code}, for more
+information on evaluating code blocks.}, see @ref{Easy templates} for
+shortcuts to easily insert code blocks.
 @cindex #+BEGIN_SRC
 
 @example
@@ -9891,13 +9915,29 @@ blocks.
 
 Both in @code{example} and in @code{src} snippets, you can add a @code{-n}
 switch to the end of the @code{BEGIN} line, to get the lines of the example
-numbered.  If you use a @code{+n} switch, the numbering from the previous
-numbered snippet will be continued in the current one.  In literal examples,
-Org will interpret strings like @samp{(ref:name)} as labels, and use them as
-targets for special hyperlinks like @code{[[(name)]]} (i.e., the reference name
-enclosed in single parenthesis).  In HTML, hovering the mouse over such a
-link will remote-highlight the corresponding code line, which is kind of
-cool.
+numbered.  The @code{-n} takes an optional numeric argument specifying the
+starting line number of the block.  If you use a @code{+n} switch, the
+numbering from the previous numbered snippet will be continued in the current
+one.  The @code{+n} can also take a numeric argument.  The value of the
+argument will be added to the last line of the previous block to determine
+the starting line number.
+
address@hidden
+#+BEGIN_SRC emacs-lisp -n 20
+ ;; this will export with line number 20
+ (message "This is line 21")
+#+END_SRC
+#+BEGIN_SRC emacs-lisp +n 10
+ ;; This will be listed as line 31
+ (message "This is line 32")
+#+END_SRC
address@hidden example
+
+In literal examples, Org will interpret strings like @samp{(ref:name)} as
+labels, and use them as targets for special hyperlinks like @code{[[(name)]]}
+(i.e., the reference name enclosed in single parenthesis).  In HTML, hovering
+the mouse over such a link will remote-highlight the corresponding code line,
+which is kind of cool.
 
 You can also add a @code{-r} switch which @i{removes} the labels from the
 source address@hidden @code{-k} to @code{-n -r} will @i{keep} the
@@ -9916,6 +9956,10 @@ In line [[(sc)]] we remember the current position.  
[[(jump)][Line (jump)]]
 jumps to point-min.
 @end example
 
address@hidden indentation, in source blocks
+Finally, you can use @code{-i} to preserve the indentation of a specific code
+block (@pxref{Editing source code}).
+
 @vindex org-coderef-label-format
 If the syntax for the label format conflicts with the language syntax, use a
 @code{-l} switch to change the format, for example @samp{#+BEGIN_SRC pascal
@@ -9925,8 +9969,8 @@ HTML export also allows examples to be published as text 
areas (@pxref{Text
 areas in HTML export}).
 
 Because the @code{#+BEGIN_...} and @code{#+END_...} patterns need to be added
-so often, shortcuts are provided using the Easy Templates facility
-(@pxref{Easy Templates}).
+so often, shortcuts are provided using the Easy templates facility
+(@pxref{Easy templates}).
 
 @table @kbd
 @kindex C-c '
@@ -9952,157 +9996,44 @@ formatting like @samp{(ref:label)} at the end of the 
current line.  Then the
 label is stored as a link @samp{(label)}, for retrieval with @kbd{C-c C-l}.
 @end table
 
-
address@hidden Include files, Index entries, Literal examples, Markup
address@hidden Include files
address@hidden include files, markup rules
-
-During export, you can include the content of another file.  For example, to
-include your @file{.emacs} file, you could use:
address@hidden #+INCLUDE
-
address@hidden
-#+INCLUDE: "~/.emacs" src emacs-lisp
address@hidden example
-
address@hidden
-The optional second and third parameter are the markup (i.e., @samp{example}
-or @samp{src}), and, if the markup is @samp{src}, the language for formatting
-the contents.  The markup is optional; if it is not given, the text will be
-assumed to be in Org mode format and will be processed normally.
-
-Contents of the included file will belong to the same structure (headline,
-item) containing the @code{INCLUDE} keyword.  In particular, headlines within
-the file will become children of the current section.  That behavior can be
-changed by providing an additional keyword parameter, @code{:minlevel}.  In
-that case, all headlines in the included file will be shifted so the one with
-the lowest level reaches that specified level.  For example, to make a file
-become a sibling of the current top-level headline, use
-
address@hidden
-#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1
address@hidden example
-
-You can also include a portion of a file by specifying a lines range using
-the @code{:lines} parameter.  The line at the upper end of the range will not
-be included.  The start and/or the end of the range may be omitted to use the
-obvious defaults.
-
address@hidden
-#+INCLUDE: "~/.emacs" :lines "5-10"   @r{Include lines 5 to 10, 10 excluded}
-#+INCLUDE: "~/.emacs" :lines "-10"    @r{Include lines 1 to 10, 10 excluded}
-#+INCLUDE: "~/.emacs" :lines "10-"    @r{Include lines from 10 to EOF}
address@hidden example
-
address@hidden @kbd
address@hidden C-c '
address@hidden C-c '
-Visit the include file at point.
address@hidden table
-
address@hidden Index entries, Macro replacement, Include files, Markup
address@hidden Index entries
address@hidden index entries, for publishing
-
-You can specify entries that will be used for generating an index during
-publishing.  This is done by lines starting with @code{#+INDEX}.  An entry
-the contains an exclamation mark will create a sub item.  See @ref{Generating
-an index} for more information.
-
address@hidden
-* Curriculum Vitae
-#+INDEX: CV
-#+INDEX: Application!CV
address@hidden example
-
-
-
-
address@hidden Macro replacement, Embedded @LaTeX{}, Index entries, Markup
address@hidden Macro replacement
address@hidden macro replacement, during export
address@hidden #+MACRO
-
-You can define text snippets with
-
address@hidden
-#+MACRO: name   replacement text $1, $2 are arguments
address@hidden example
-
address@hidden which can be referenced in
-paragraphs, verse blocks, table cells and some keywords with
address@hidden@address@hidden@{name(arg1,arg2)@address@hidden@address@hidden 
commas separate arguments,
-commas within arguments have to be escaped with a backslash character.
-Conversely, backslash characters before a comma, and only them, need to be
-escaped with another backslash character.}.  In addition to defined macros,
address@hidden@address@hidden@address@hidden@address@hidden, 
@address@hidden@address@hidden@address@hidden@}}, etc., will reference
-information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and similar lines.
-Also, @address@hidden@address@hidden(@var{FORMAT})@address@hidden@}} and
address@hidden@address@hidden@{modification-time(@var{FORMAT})@address@hidden@}}
 refer to current date time
-and to the modification time of the file being exported, respectively.
address@hidden should be a format string understood by
address@hidden
-
-Macro expansion takes place during export.
-
-
address@hidden Embedded @LaTeX{}, Special blocks, Macro replacement, Markup
address@hidden Embedded @LaTeX{}
address@hidden @TeX{} interpretation
address@hidden @LaTeX{} interpretation
-
-Plain ASCII is normally sufficient for almost all note taking.  Exceptions
-include scientific notes, which often require mathematical symbols and the
-occasional formula.  @address@hidden@LaTeX{} is a macro system based on
-Donald E. Knuth's @TeX{} system.  Many of the features described here as
address@hidden'' are really from @TeX{}, but for simplicity I am blurring this
-distinction.}  is widely used to typeset scientific documents.  Org mode
-supports embedding @LaTeX{} code into its files, because many academics are
-used to writing and reading @LaTeX{} source code, and because it can be
-readily processed to produce pretty output for a number of export back-ends.
-
address@hidden
-* Special symbols::             Greek letters and other symbols
-* Subscripts and superscripts::  Simple syntax for raising/lowering text
-* @LaTeX{} fragments::          Complex formulas made easy
-* Previewing @LaTeX{} fragments::  What will this snippet look like?
-* CDLaTeX mode::                Speed up entering of formulas
address@hidden menu
-
address@hidden Special symbols, Subscripts and superscripts, Embedded @LaTeX{}, 
Embedded @LaTeX{}
address@hidden Special symbols
address@hidden Special symbols
address@hidden Special symbols
address@hidden Org entities
 @cindex math symbols
 @cindex special symbols
address@hidden @TeX{} macros
address@hidden @LaTeX{} fragments, markup rules
 @cindex HTML entities
 @cindex @LaTeX{} entities
 
-You can use @LaTeX{}-like syntax to insert special symbols like @samp{\alpha}
-to indicate the Greek letter, or @samp{\to} to indicate an arrow.  Completion
-for these symbols is available, just type @samp{\} and maybe a few letters,
-and press @address@hidden to see possible completions.  Unlike @LaTeX{}
-code, Org mode allows these symbols to be present without surrounding math
-delimiters, for example:
+You can use @LaTeX{}-like syntax to insert special symbols---named
+entities---like @samp{\alpha} to indicate the Greek letter, or @samp{\to} to
+indicate an arrow.  Completion for these symbols is available, just type
address@hidden and maybe a few letters, and press @address@hidden to see 
possible
+completions.  If you need such a symbol inside a word, terminate it with
+a pair of curly brackets.  For example
 
 @example
-Angles are written as Greek letters \alpha, \beta and \gamma.
+Protip: Given a circle \Gamma of diameter d, the length of its circumference
+is address@hidden@}d.
 @end example
 
address@hidden org-entities
-During export, these symbols will be transformed into the native format of
-the exporter back-end.  Strings like @code{\alpha} will be exported as
address@hidden&alpha;} in the HTML output, and as @code{$\alpha$} in the 
@LaTeX{}
-output.  Similarly, @code{\nbsp} will become @code{&nbsp;} in HTML and
address@hidden in @LaTeX{}.  If you need such a symbol inside a word, terminate 
it
-like this: @address@hidden@}stor}.
-
address@hidden org-entities-help
address@hidden org-entities-user
 A large number of entities is provided, with names taken from both HTML and
address@hidden; see the variable @code{org-entities} for the complete list.
address@hidden is treated as a shy hyphen, and @samp{--}, @samp{---}, and
address@hidden are all converted into special commands creating hyphens of
-different lengths or a compact set of dots.
address@hidden; you can comfortably browse the complete list from a dedicated
+buffer using the command @code{org-entities-help}.  It is also possible to
+provide your own special symbols in the variable @code{org-entities-user}.
+
+During export, these symbols are transformed into the native format of the
+exporter back-end.  Strings like @code{\alpha} are exported as @code{&alpha;}
+in the HTML output, and as @code{\(\alpha\)} in the @LaTeX{} output.
+Similarly, @code{\nbsp} becomes @code{&nbsp;} in HTML and @code{~} in
address@hidden
+
address@hidden escaping characters
+Entities may also be used as a may to escape markup in an Org document, e.g.,
address@hidden@address@hidden underlined\under} exports as @samp{_not 
underlined_}.
 
address@hidden special symbols, in-buffer display
 If you would like to see entities displayed as UTF-8 characters, use the
 following address@hidden can turn this on by default by setting the
 variable @code{org-pretty-entities}, or on a per-file base with the
@@ -10117,20 +10048,28 @@ buffer content which remains plain ASCII, but it 
overlays the UTF-8 character
 for display purposes only.
 @end table
 
address@hidden Subscripts and superscripts, @LaTeX{} fragments, Special 
symbols, Embedded @LaTeX{}
address@hidden Subscripts and superscripts
address@hidden shy hyphen, special symbol
address@hidden dash, special symbol
address@hidden ellipsis, special symbol
+In addition to regular entities defined above, Org exports in a special
address@hidden behaviour can be disabled with @code{-} export setting
+(@pxref{Export settings}).} the following commonly used character
+combinations: @samp{\-} is treated as a shy hyphen, @samp{--} and @samp{---}
+are converted into dashes, and @samp{...} becomes a compact set of dots.
+
address@hidden Subscripts and superscripts
address@hidden Subscripts and superscripts
 @cindex subscript
 @cindex superscript
 
-Just like in @LaTeX{}, @samp{^} and @samp{_} are used to indicate super- and
-subscripts.  Again, these can be used without embedding them in math-mode
-delimiters.  To increase the readability of ASCII text, it is not necessary
-(but OK) to surround multi-character sub- and superscripts with curly braces.
-For example
address@hidden and @samp{_} are used to indicate super- and subscripts.  To
+increase the readability of ASCII text, it is not necessary---but OK---to
+surround multi-character sub- and superscripts with curly braces.  Those are,
+however, mandatory, when more than one word is involved.  For example
 
 @example
-The mass of the sun is M_sun = 1.989 x 10^30 kg.  The radius of
-the sun is address@hidden@} = 6.96 x 10^8 m.
+The radius of the sun is R_sun = 6.96 x 10^8 m.  On the other hand, the
+radius of Alpha Centauri is address@hidden address@hidden = 1.28 x 
address@hidden@}.
 @end example
 
 @vindex org-use-sub-superscripts
@@ -10147,46 +10086,58 @@ In addition to showing entities as UTF-8 characters, 
this command will also
 format sub- and superscripts in a WYSIWYM way.
 @end table
 
address@hidden @LaTeX{} fragments, Previewing @LaTeX{} fragments, Subscripts 
and superscripts, Embedded @LaTeX{}
address@hidden Embedded @LaTeX{}
address@hidden Embedded @LaTeX{}
address@hidden @TeX{} interpretation
address@hidden @LaTeX{} interpretation
+
+Plain ASCII is normally sufficient for almost all note taking.  Exceptions
+include scientific notes, which often require mathematical symbols and the
+occasional formula.  @address@hidden@LaTeX{} is a macro system based on
+Donald E. Knuth's @TeX{} system.  Many of the features described here as
address@hidden'' are really from @TeX{}, but for simplicity I am blurring this
+distinction.}  is widely used to typeset scientific documents.  Org mode
+supports embedding @LaTeX{} code into its files, because many academics are
+used to writing and reading @LaTeX{} source code, and because it can be
+readily processed to produce pretty output for a number of export back-ends.
+
address@hidden
+* @LaTeX{} fragments::          Complex formulas made easy
+* Previewing @LaTeX{} fragments::  What will this snippet look like?
+* CDLaTeX mode::                Speed up entering of formulas
address@hidden menu
+
address@hidden @LaTeX{} fragments
 @subsection @LaTeX{} fragments
 @cindex @LaTeX{} fragments
 
 @vindex org-format-latex-header
-Going beyond symbols and sub- and superscripts, a full formula language is
-needed.  Org mode can contain @LaTeX{} math fragments, and it supports ways
-to process these for several export back-ends.  When exporting to @LaTeX{},
-the code is obviously left as it is.  When exporting to HTML, Org invokes the
address@hidden://www.mathjax.org, MathJax library} (@pxref{Math formatting in
-HTML export}) to process and display the address@hidden you plan to use
-this regularly or on pages with significant page views, you should install
address@hidden on your own server in order to limit the load of our server.}.
-Finally, it can also process the mathematical expressions into
address@hidden this to work you need to be on a system with a working
address@hidden installation.  You also need the @file{dvipng} program or the
address@hidden, respectively available at
address@hidden://sourceforge.net/projects/dvipng/} and from the 
@file{imagemagick}
-suite.  The @LaTeX{} header that will be used when processing a fragment can
-be configured with the variable @code{org-format-latex-header}.} that can be
-displayed in a browser.
+Org mode can contain @LaTeX{} math fragments, and it supports ways to process
+these for several export back-ends.  When exporting to @LaTeX{}, the code is
+left as it is.  When exporting to HTML, Org can use either
address@hidden://www.mathjax.org, MathJax} (@pxref{Math formatting in HTML
+export}) or transcode the math into images (see @pxref{Previewing @LaTeX{}
+fragments}).
 
 @LaTeX{} fragments don't need any special marking at all.  The following
 snippets will be identified as @LaTeX{} source code:
 @itemize @bullet
 @item
-Environments of any address@hidden @file{MathJax} is used, only the
-environments recognized by @file{MathJax} will be processed.  When
address@hidden program or @file{imagemagick} suite is used to create images,
-any @LaTeX{} environment will be handled.}.  The only requirement is that the
address@hidden and @code{\end} statements appear on a new line, at the
+Environments of any address@hidden MathJax is used, only the
+environments recognized by MathJax will be processed.  When
address@hidden program, @file{dvisvgm} program or @file{imagemagick} suite is
+used to create images, any @LaTeX{} environment will be handled.}.  The only
+requirement is that the @code{\begin} statement appears on a new line, at the
 beginning of the line or after whitespaces only.
 @item
 Text within the usual @LaTeX{} math delimiters.  To avoid conflicts with
 currency specifications, single @samp{$} characters are only recognized as
 math delimiters if the enclosed text contains at most two line breaks, is
 directly attached to the @samp{$} characters with no whitespace in between,
-and if the closing @samp{$} is followed by whitespace, punctuation or a dash.
-For the other delimiters, there is no such restriction, so when in doubt, use
address@hidden(...\)} as inline math delimiters.
+and if the closing @samp{$} is followed by whitespace or punctuation
+(parentheses and quotes are considered to be punctuation in this
+context).  For the other delimiters, there is no such restriction, so when in
+doubt, use @samp{\(...\)} as inline math delimiters.
 @end itemize
 
 @noindent For example:
@@ -10210,7 +10161,7 @@ either $$ address@hidden@} $$ or \[ address@hidden@} \].
 @vindex org-export-with-latex
 @LaTeX{} processing can be configured with the variable
 @code{org-export-with-latex}.  The default setting is @code{t} which means
address@hidden for HTML, and no processing for ASCII and @LaTeX{} back-ends.
+MathJax for HTML, and no processing for ASCII and @LaTeX{} back-ends.
 You can also set this variable on a per-file basis using one of these
 lines:
 
@@ -10220,16 +10171,26 @@ lines:
 #+OPTIONS: tex:verbatim   @r{Verbatim export, for jsMath or so}
 @end example
 
address@hidden Previewing @LaTeX{} fragments, CDLaTeX mode, @LaTeX{} fragments, 
Embedded @LaTeX{}
address@hidden Previewing @LaTeX{} fragments
 @subsection Previewing @LaTeX{} fragments
 @cindex @LaTeX{} fragments, preview
 
address@hidden org-latex-create-formula-image-program
-If you have @file{dvipng} or @file{imagemagick} address@hidden the
-converter by setting the variable
address@hidden accordingly.}, @LaTeX{}
-fragments can be processed to produce preview images of the typeset
-expressions:
address@hidden org-preview-latex-default-process
+If you have a working @LaTeX{} installation and @file{dvipng}, @file{dvisvgm}
+or @file{convert} address@hidden are respectively available at
address@hidden://sourceforge.net/projects/dvipng/}, 
@url{http://dvisvgm.bplaced.net/}
+and from the @file{imagemagick} suite.  Choose the converter by setting the
+variable @code{org-preview-latex-default-process} accordingly.}, @LaTeX{}
+fragments can be processed to produce images of the typeset expressions to be
+used for inclusion while exporting to HTML (see @address@hidden fragments}),
+or for inline previewing within Org mode.
+
address@hidden org-format-latex-options
address@hidden org-format-latex-header
+You can customize the variables @code{org-format-latex-options} and
address@hidden to influence some aspects of the preview.  In
+particular, the @code{:scale} (and for HTML export, @code{:html-scale})
+property of the former can be used to adjust the size of the preview images.
 
 @table @kbd
 @kindex C-c C-x C-l
@@ -10245,12 +10206,6 @@ process the entire buffer.
 Remove the overlay preview images.
 @end table
 
address@hidden org-format-latex-options
-You can customize the variable @code{org-format-latex-options} to influence
-some aspects of the preview.  In particular, the @code{:scale} (and for HTML
-export, @code{:html-scale}) property can be used to adjust the size of the
-preview images.
-
 @vindex org-startup-with-latex-preview
 You can turn on the previewing of all @LaTeX{} fragments in a file with
 
@@ -10264,7 +10219,7 @@ To disable it, simply use
 #+STARTUP: nolatexpreview
 @end example
 
address@hidden CDLaTeX mode,  , Previewing @LaTeX{} fragments, Embedded @LaTeX{}
address@hidden CDLaTeX mode
 @subsection Using address@hidden to enter math
 @cindex address@hidden
 
@@ -10325,252 +10280,233 @@ modification will work only inside @LaTeX{} 
fragments; outside the quote
 is normal.
 @end itemize
 
address@hidden Special blocks,  , Embedded @LaTeX{}, Markup
address@hidden Special blocks
address@hidden Special blocks
address@hidden Exporting
address@hidden Exporting
address@hidden exporting
 
-Org syntax includes pre-defined blocks (@pxref{Paragraphs} and @ref{Literal
-examples}).  It is also possible to create blocks containing raw code
-targeted at a specific back-ends (e.g., @samp{#+BEGIN_LATEX}).
+Sometimes, you may want to pretty print your notes, publish them on the web
+or even share them with people not using Org.  In these cases, the Org export
+facilities can be used to convert your documents to a variety of other
+formats, while retaining as much structure (@pxref{Document structure}) and
+markup (@pxref{Markup}) as possible.
 
-Any other block is a @emph{special block}.
address@hidden export back-end
+Libraries responsible for such translation are called back-ends.  Org ships
+with the following ones
 
-For example, @samp{#+BEGIN_ABSTRACT} and @samp{#+BEGIN_VIDEO} are special
-blocks.  The first one is useful when exporting to @LaTeX{}, the second one
-when exporting to HTML5.
address@hidden
address@hidden ascii (ASCII format)
address@hidden beamer (@LaTeX{} Beamer format)
address@hidden html (HTML format)
address@hidden icalendar (iCalendar format)
address@hidden latex (@LaTeX{} format)
address@hidden md (Markdown format)
address@hidden odt (OpenDocument Text format)
address@hidden org (Org format)
address@hidden texinfo (Texinfo format)
address@hidden man (Man page format)
address@hidden itemize
 
-Each export back-end decides if they should be exported, and how.  When the
-block is ignored, its contents are still exported, as if the opening and
-closing block lines were not there.  For example, when exporting a
address@hidden block, HTML back-end wraps its contents within a
address@hidden<div name="test">} tag.
address@hidden Org also uses additional libraries located in @code{contrib/}
+directory (@pxref{Installation}).  Users can install additional export
+libraries for additional formats from the Emacs packaging system.  For easy
+discovery, these packages have a common naming scheme: @file{ox-NAME}, where
+NAME is one of the formats.  For example, @file{ox-koma-letter} for
address@hidden back-end.
 
-Refer to back-end specific documentation for more information.
address@hidden org-export-backends
+Org loads back-ends for the following formats by default: @code{ascii},
address@hidden, @code{icalendar}, @code{latex} and @code{odt}.
 
address@hidden Exporting, Publishing, Markup, Top
address@hidden Exporting
address@hidden exporting
+Org can load additional back-ends either of two ways: through the
address@hidden variable configuration; or, by requiring the
+library in the Emacs init file like this:
 
-The Org mode export facilities can be used to export Org documents or parts
-of Org documents to a variety of other formats.  In addition, these
-facilities can be used with @code{orgtbl-mode} and/or @code{orgstruct-mode}
-in foreign buffers so you can author tables and lists in Org syntax and
-convert them in place to the target language.
-
-ASCII export produces a readable and simple version of an Org file for
-printing and sharing notes.  HTML export allows you to easily publish notes
-on the web, or to build full-fledged websites.  @LaTeX{} export lets you use
-Org mode and its structured editing functions to create arbitrarily complex
address@hidden files for any kind of document.  OpenDocument Text (ODT) export
-allows seamless collaboration across organizational boundaries.  Markdown
-export lets you seamlessly collaborate with other developers.  Finally, iCal
-export can extract entries with deadlines or appointments to produce a file
-in the iCalendar format.
address@hidden
+(require 'ox-md)
address@hidden lisp
 
 @menu
-* The Export Dispatcher::       The main exporter interface
-* Export back-ends::            Built-in export formats
-* Export settings::             Generic export settings
+* The export dispatcher::       The main interface
+* Export settings::             Common export settings
+* Table of contents::           The if and where of the table of contents
+* Include files::               Include additional files into a document
+* Macro replacement::           Use macros to create templates
+* Comment lines::               What will not be exported
 * ASCII/Latin-1/UTF-8 export::  Exporting to flat files with encoding
 * Beamer export::               Exporting as a Beamer presentation
 * HTML export::                 Exporting to HTML
-* @LaTeX{} and PDF export::     Exporting to @LaTeX{}, and processing to PDF
+* @LaTeX{} export::             Exporting to @LaTeX{}, and processing to PDF
 * Markdown export::             Exporting to Markdown
 * OpenDocument Text export::    Exporting to OpenDocument Text
 * Org export::                  Exporting to Org
 * Texinfo export::              Exporting to Texinfo
 * iCalendar export::            Exporting to iCalendar
 * Other built-in back-ends::    Exporting to a man page
-* Export in foreign buffers::   Author tables and lists in Org syntax
 * Advanced configuration::      Fine-tuning the export output
+* Export in foreign buffers::   Author tables and lists in Org syntax
 @end menu
 
address@hidden The Export Dispatcher, Export back-ends, Exporting, Exporting
address@hidden The Export Dispatcher
address@hidden The export dispatcher
address@hidden The export dispatcher
 @vindex org-export-dispatch-use-expert-ui
 @cindex Export, dispatcher
 
-The main entry point for export related tasks is the dispatcher, a
-hierarchical menu from which it is possible to select an export format and
-toggle export address@hidden is also possible to use a less intrusive
-interface by setting @code{org-export-dispatch-use-expert-ui} to a
address@hidden value.  In that case, only a prompt is visible from the
-minibuffer.  From there one can still switch back to regular menu by pressing
address@hidden from which it is possible to select an export format and to 
toggle
-export options.
+The export dispatcher is the main interface for Org's exports.  A
+hierarchical menu presents the currently configured export formats.  Options
+are shown as easy toggle switches on the same screen.
+
+Org also has a minimal prompt interface for the export dispatcher.  When the
+variable @code{org-export-dispatch-use-expert-ui} is set to a address@hidden
+value, Org prompts in the minibuffer.  To switch back to the hierarchical
+menu, press @key{?}.
 
address@hidden @quotation
 @table @asis
 @orgcmd{C-c C-e,org-export-dispatch}
 
-Dispatch for export and publishing commands.  When called with a @kbd{C-u}
-prefix argument, repeat the last export command on the current buffer while
-preserving toggled options.  If the current buffer hasn't changed and subtree
-export was activated, the command will affect that same subtree.
+Invokes the export dispatcher interface.  The options show default settings.
+The @kbd{C-u} prefix argument preserves options from the previous export,
+including any sub-tree selections.
+
 @end table
address@hidden @end quotation
 
-Normally the entire buffer is exported, but if there is an active region
-only that part of the buffer will be exported.
+Org exports the entire buffer by default.  If the Org buffer has an active
+region, then Org exports just that region.
 
-Several export options (@pxref{Export settings}) can be toggled from the
-export dispatcher with the following key combinations:
+These are the export options, the key combinations that toggle them
+(@pxref{Export settings}):
 
 @table @kbd
 @item C-a
 @vindex org-export-async-init-file
-Toggle asynchronous export.  Asynchronous export uses an external Emacs
-process that is configured with a specified initialization file.
+Toggles asynchronous export.  Asynchronous export uses an external Emacs
+process with a specially configured initialization file to complete the
+exporting process in the background thereby releasing the current interface.
+This is particularly useful when exporting long documents.
 
-While exporting asynchronously, the output is not displayed, but stored in
-a place called ``the export stack''.  This stack can be displayed by calling
-the dispatcher with a double @kbd{C-u} prefix argument, or with @kbd{&} key
-from the dispatcher menu.
+Output from an asynchronous export is saved on the ``the export stack''.  To
+view this stack, call the export dispatcher with a double @kbd{C-u} prefix
+argument.  If already in the export dispatcher menu, @kbd{&} displays the
+stack.
 
 @vindex org-export-in-background
-To make this behavior the default, customize the variable
+To make the background export process the default, customize the variable,
 @code{org-export-in-background}.
 
 @item C-b
-Toggle body-only export.  Its effect depends on the back-end used.
-Typically, if the back-end has a header section (like @code{<head>...</head>}
-in the HTML back-end), a body-only export will not include this header.
+Toggle body-only export.  Useful for excluding headers and footers in the
+export.  Affects only those back-end formats that have such sections---like
address@hidden<head>...</head>} in HTML.
 
 @item C-s
 @vindex org-export-initial-scope
-Toggle subtree export.  The top heading becomes the document title.
+Toggle sub-tree export.  When turned on, Org exports only the sub-tree starting
+from the cursor position at the time the export dispatcher was invoked.  Org
+uses the top heading of this sub-tree as the document's title.  If the cursor
+is not on a heading, Org uses the nearest enclosing header.  If the cursor is
+in the document preamble, Org signals an error and aborts export.
 
-You can change the default state of this option by setting
+To make the sub-tree export the default, customize the variable,
 @code{org-export-initial-scope}.
 
 @item C-v
-Toggle visible-only export.  Only export the text that is currently
-visible, i.e., not hidden by outline visibility in the buffer.
-
+Toggle visible-only export.  Useful for exporting only visible parts of an
+Org document by adjusting outline visibility settings.
 @end table
 
address@hidden org-export-copy-to-kill-ring
-With the exception of asynchronous export, a successful export process writes
-its output to the kill-ring. You can configure this behavior by altering the
-option @code{org-export-copy-to-kill-ring}.
-
address@hidden Export back-ends, Export settings, The Export Dispatcher, 
Exporting
address@hidden Export back-ends
address@hidden Export, back-ends
-
-An export back-end is a library that translates Org syntax into a foreign
-format.  An export format is not available until the proper back-end has been
-loaded.
-
address@hidden org-export-backends
-By default, the following four back-ends are loaded: @code{ascii},
address@hidden, @code{icalendar} and @code{latex}.  It is possible to add more
-(or remove some) by customizing @code{org-export-backends}.
-
-Built-in back-ends include:
-
address@hidden
address@hidden ascii (ASCII format)
address@hidden beamer (@LaTeX{} Beamer format)
address@hidden html (HTML format)
address@hidden icalendar (iCalendar format)
address@hidden latex (@LaTeX{} format)
address@hidden man (Man page format)
address@hidden md (Markdown format)
address@hidden odt (OpenDocument Text format)
address@hidden org (Org format)
address@hidden texinfo (Texinfo format)
address@hidden itemize
-
-Other back-ends might be found in the @code{contrib/} directory
-(@pxref{Installation}).
-
address@hidden Export settings, ASCII/Latin-1/UTF-8 export, Export back-ends, 
Exporting
address@hidden Export settings
 @section Export settings
 @cindex Export, settings
 
address@hidden #+OPTIONS
 Export options can be set: globally with variables; for an individual file by
 making variables buffer-local with in-buffer settings (@pxref{In-buffer
 settings}), by setting individual keywords, or by specifying them in a
 compact form with the @code{#+OPTIONS} keyword; or for a tree by setting
-properties (@pxref{Properties and Columns}).  Options set at a specific level
+properties (@pxref{Properties and columns}).  Options set at a specific level
 override options set at a more general level.
 
 @cindex #+SETUPFILE
 In-buffer settings may appear anywhere in the file, either directly or
 indirectly through a file included using @samp{#+SETUPFILE: filename} syntax.
 Option keyword sets tailored to a particular back-end can be inserted from
-the export dispatcher (@pxref{The Export Dispatcher}) using the @code{Insert
+the export dispatcher (@pxref{The export dispatcher}) using the @code{Insert
 template} command by pressing @key{#}.  To insert keywords individually,
 a good way to make sure the keyword is correct is to type @code{#+} and then
-to use @kbd{M-<TAB>} for completion.
+to use @address@hidden@footnote{Many desktops intercept @kbd{M-TAB} to
+switch windows.  Use @kbd{C-M-i} or @address@hidden @key{TAB}} instead.} for
+completion.
 
 The export keywords available for every back-end, and their equivalent global
 variables, include:
 
 @table @samp
 @item AUTHOR
address@hidden #+AUTHOR
 @vindex user-full-name
 The document author (@code{user-full-name}).
 
 @item CREATOR
address@hidden #+CREATOR
 @vindex org-export-creator-string
 Entity responsible for output generation (@code{org-export-creator-string}).
 
 @item DATE
address@hidden #+DATE
 @vindex org-export-date-timestamp-format
 A date or a address@hidden variable
 @code{org-export-date-timestamp-format} defines how this time-stamp will be
 exported.}.
 
address@hidden DESCRIPTION
-The document description.  Back-ends handle it as they see fit (e.g., for the
-XHTML meta tag), if at all.  You can use several such keywords for long
-descriptions.
-
 @item EMAIL
address@hidden #+EMAIL
 @vindex user-mail-address
 The email address (@code{user-mail-address}).
 
address@hidden KEYWORDS
-The keywords defining the contents of the document.  Back-ends handle it as
-they see fit (e.g., for the XHTML meta tag), if at all.  You can use several
-such keywords if the list is long.
-
 @item LANGUAGE
address@hidden #+LANGUAGE
 @vindex org-export-default-language
-The language used for translating some strings
-(@code{org-export-default-language}).  E.g., @samp{#+LANGUAGE: fr} will tell
-Org to translate @emph{File} (english) into @emph{Fichier} (french) in the
-clocktable.
+Language to use for translating certain strings
+(@code{org-export-default-language}).  With @samp{#+LANGUAGE: fr}, for
+example, Org translates @emph{Table of contents} to the French @emph{Table
+des matières}.
 
 @item SELECT_TAGS
address@hidden #+SELECT_TAGS
 @vindex org-export-select-tags
-The tags that select a tree for export (@code{org-export-select-tags}).  The
-default value is @code{:export:}.  Within a subtree tagged with
address@hidden:export:}, you can still exclude entries with @code{:noexport:} 
(see
-below).  When headlines are selectively exported with @code{:export:}
-anywhere in a file, text before the first headline is ignored.
+The default value is @code{:export:}.  When a tree is tagged with
address@hidden:export:} (@code{org-export-select-tags}), Org selects that tree 
and
+its sub-trees for export.  Org excludes trees with @code{:noexport:} tags,
+see below.  When selectively exporting files with @code{:export:} tags set,
+Org does not export any text that appears before the first headline.
 
 @item EXCLUDE_TAGS
-The tags that exclude a tree from export (@code{org-export-exclude-tags}).
-The default value is @code{:noexport:}.  Entries with the @code{:noexport:}
-tag will be unconditionally excluded from the export, even if they have an
address@hidden:export:} tag.
address@hidden #+EXCLUDE_TAGS
address@hidden org-export-exclude-tags
+The default value is @code{:noexport:}.  When a tree is tagged with
address@hidden:noexport:} (@code{org-export-exclude-tags}), Org excludes that 
tree
+and its sub-trees from export.  Entries tagged with @code{:noexport:} will be
+unconditionally excluded from the export, even if they have an
address@hidden:export:} tag.  Even if a sub-tree is not exported, Org will 
execute any
+code blocks contained in them.
 
 @item TITLE
-The title to be shown (otherwise derived from buffer's name).  You can use
-several such keywords for long titles.
address@hidden #+TITLE
address@hidden document title
+Org displays this title.  For long titles, use multiple @code{#+TITLE} lines.
 @end table
 
-The @code{#+OPTIONS} keyword is a address@hidden you want to configure
-many options this way, you can use several @code{#+OPTIONS} lines.} form that
-recognizes the following arguments:
+The @code{#+OPTIONS} keyword is a compact form.  To configure multiple
+options, use several @code{#+OPTIONS} lines.  @code{#+OPTIONS} recognizes the
+following arguments.
 
 @table @code
 @item ':
 @vindex org-export-with-smart-quotes
-Toggle smart quotes (@code{org-export-with-smart-quotes}).
+Toggle smart quotes (@code{org-export-with-smart-quotes}).  Depending on the
+language used, when activated, Org treats pairs of double quotes as primary
+quotes, pairs of single quotes as secondary quotes, and single quote marks as
+apostrophes.
 
 @item *:
 Toggle emphasized text (@code{org-export-with-emphasize}).
@@ -10587,12 +10523,12 @@ Toggle fixed-width sections
 
 @item <:
 @vindex org-export-with-timestamps
-Toggle inclusion of any time/date active/inactive stamps
+Toggle inclusion of time/date active/inactive stamps
 (@code{org-export-with-timestamps}).
 
address@hidden :
address@hidden \n:
 @vindex org-export-preserve-breaks
-Toggle line-break-preservation (@code{org-export-preserve-breaks}).
+Toggles whether to preserve line breaks (@code{org-export-preserve-breaks}).
 
 @item ^:
 @vindex org-export-with-sub-superscripts
@@ -10602,8 +10538,8 @@ it is (@code{org-export-with-sub-superscripts}).
 
 @item arch:
 @vindex org-export-with-archived-trees
-Configure export of archived trees.  Can be set to @code{headline} to only
-process the headline, skipping its contents
+Configure how archived trees are exported.  When set to @code{headline}, the
+export process skips the contents and processes only the headlines
 (@code{org-export-with-archived-trees}).
 
 @item author:
@@ -10611,19 +10547,29 @@ process the headline, skipping its contents
 Toggle inclusion of author name into exported file
 (@code{org-export-with-author}).
 
address@hidden broken-links:
address@hidden org-export-with-broken-links
+Toggles if Org should continue exporting upon finding a broken internal link.
+When set to @code{mark}, Org clearly marks the problem link in the output
+(@code{org-export-with-broken-links}).
+
 @item c:
 @vindex org-export-with-clocks
 Toggle inclusion of CLOCK keywords (@code{org-export-with-clocks}).
 
 @item creator:
 @vindex org-export-with-creator
-Configure inclusion of creator info into exported file.  It may be set to
address@hidden (@code{org-export-with-creator}).
+Toggle inclusion of creator information in the exported file
+(@code{org-export-with-creator}).
 
 @item d:
 @vindex org-export-with-drawers
-Toggle inclusion of drawers, or list drawers to include
-(@code{org-export-with-drawers}).
+Toggles inclusion of drawers, or list of drawers to include, or list of
+drawers to exclude (@code{org-export-with-drawers}).
+
address@hidden date:
address@hidden org-export-with-date
+Toggle inclusion of a date into exported file (@code{org-export-with-date}).
 
 @item e:
 @vindex org-export-with-entities
@@ -10650,20 +10596,28 @@ Toggle inclusion of inlinetasks 
(@code{org-export-with-inlinetasks}).
 
 @item num:
 @vindex org-export-with-section-numbers
-Toggle section-numbers (@code{org-export-with-section-numbers}).  It can also
-be set to a number @samp{n}, so only headlines at that level or above will be
-numbered.
address@hidden property, UNNUMBERED
+Toggle section-numbers (@code{org-export-with-section-numbers}).  When set to
+number @samp{n}, Org numbers only those headlines at level @samp{n} or above.
+Set @code{UNNUMBERED} property to address@hidden to disable numbering of
+heading and subheadings entirely.
 
 @item p:
 @vindex org-export-with-planning
 Toggle export of planning information (@code{org-export-with-planning}).
-``Planning information'' is the line containing the @code{SCHEDULED:}, the
address@hidden:} or the @code{CLOSED:} cookies or a combination of them.
+``Planning information'' comes from lines located right after the headline
+and contain any combination of these cookies: @code{SCHEDULED:},
address@hidden:}, or @code{CLOSED:}.
 
 @item pri:
 @vindex org-export-with-priority
 Toggle inclusion of priority cookies (@code{org-export-with-priority}).
 
address@hidden prop:
address@hidden org-export-with-properties
+Toggle inclusion of property drawers, or list the properties to include
+(@code{org-export-with-properties}).
+
 @item stat:
 @vindex org-export-with-statistics-cookies
 Toggle inclusion of statistics cookies
@@ -10676,20 +10630,24 @@ Toggle inclusion of tags, may also be 
@code{not-in-toc}
 
 @item tasks:
 @vindex org-export-with-tasks
-Toggle inclusion of tasks (TODO items), can be @code{nil} to remove all
-tasks, @code{todo} to remove DONE tasks, or a list of keywords to keep
+Toggle inclusion of tasks (TODO items); or @code{nil} to remove all tasks; or
address@hidden to remove DONE tasks; or list the keywords to keep
 (@code{org-export-with-tasks}).
 
 @item tex:
 @vindex org-export-with-latex
-Configure export of @LaTeX{} fragments and environments.  It may be set to
address@hidden (@code{org-export-with-latex}).
address@hidden does not export; @code{t} exports; @code{verbatim} keeps
+everything in verbatim (@code{org-export-with-latex}).
 
 @item timestamp:
 @vindex org-export-time-stamp-file
-Toggle inclusion of the creation time into exported file
+Toggle inclusion of the creation time in the exported file
 (@code{org-export-time-stamp-file}).
 
address@hidden title:
address@hidden org-export-with-title
+Toggle inclusion of title (@code{org-export-with-title}).
+
 @item toc:
 @vindex org-export-with-toc
 Toggle inclusion of the table of contents, or set the level limit
@@ -10703,255 +10661,589 @@ Toggle inclusion of TODO keywords into exported text
 @item |:
 @vindex org-export-with-tables
 Toggle inclusion of tables (@code{org-export-with-tables}).
+
 @end table
 
-When exporting only a subtree, each of the previous address@hidden
-the exception of @samp{SETUPFILE}.} can be overridden locally by special node
-properties.  These begin with @samp{EXPORT_}, followed by the name of the
-keyword they supplant.  For example, @samp{DATE} and @samp{OPTIONS} keywords
-become, respectively, @samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS}
-properties.
+When exporting sub-trees, special node properties in them can override the
+above keywords.  They are special because they have an @samp{EXPORT_} prefix.
+For example, @samp{DATE} and @samp{OPTIONS} keywords become, respectively,
address@hidden and @samp{EXPORT_OPTIONS}.  Except for @samp{SETUPFILE},
+all other keywords listed above have an @samp{EXPORT_} equivalent.
 
 @cindex #+BIND
 @vindex org-export-allow-bind-keywords
 If @code{org-export-allow-bind-keywords} is address@hidden, Emacs variables
 can become buffer-local during export by using the BIND keyword.  Its syntax
 is @samp{#+BIND: variable value}.  This is particularly useful for in-buffer
-settings that cannot be changed using specific keywords.
+settings that cannot be changed using keywords.
 
 @cindex property, EXPORT_FILE_NAME
-The name of the output file to be generated is taken from the file associated
-to the buffer, when possible, or asked to you otherwise.  For subtree export,
-you can also set @samp{EXPORT_FILE_NAME} property.  In all cases, only the
-base name of the file is retained, and a back-end specific extension is
-added.
+Normally Org generates the file name based on the buffer name and the
+extension based on the back-end format.  For sub-trees, Org can export to a
+file name as specified in the @code{EXPORT_FILE_NAME} property.
+
address@hidden Table of contents
address@hidden Table of contents
address@hidden table of contents
address@hidden list of tables
address@hidden list of listings
+
address@hidden #+TOC
address@hidden org-export-with-toc
+Org normally inserts the table of contents directly before the first headline
+of the file.  Org sets the TOC depth the same as the headline levels in the
+file.  Use a lower number for lower TOC depth.  To turn off TOC entirely, use
address@hidden  This is configured in the @code{org-export-with-toc} variable or
+as keywords in an Org file as:
+
address@hidden
+#+OPTIONS: toc:2          @r{only include two levels in TOC}
+#+OPTIONS: toc:nil        @r{no default TOC at all}
address@hidden example
+
+To move the table of contents to a different location, first turn off the
+default with @code{org-export-with-toc} variable or with @code{#+OPTIONS:
+toc:nil}.  Then insert @code{#+TOC: headlines N} at the desired location(s).
+
address@hidden
+#+OPTIONS: toc:nil        @r{no default TOC}
+...
+#+TOC: headlines 2        @r{insert TOC here, with two headline levels}
address@hidden example
+
+To adjust the TOC depth for a specific section of the Org document, append an
+additional @samp{local} parameter.  This parameter becomes a relative depth
+for the current level.
+
+Note that for this feature to work properly in @LaTeX{} export, the Org file
+requires the inclusion of the @code{titletoc} package.  Because of
+compatibility issues, @code{titletoc} has to be loaded @emph{before}
address@hidden  Customize the @code{org-latex-default-packages-alist}
+variable.
+
address@hidden
+* Section #+TOC: headlines 1 local @r{insert local TOC, with direct children
+only}
address@hidden example
+
+Use the @code{TOC} keyword to generate list of tables (resp.@: all listings)
+with captions.
+
address@hidden
+#+TOC: listings           @r{build a list of listings}
+#+TOC: tables             @r{build a list of tables}
address@hidden example
+
address@hidden property, ALT_TITLE
+Normally Org uses the headline for its entry in the table of contents.  But
+with @code{ALT_TITLE} property, a different entry can be specified for the
+table of contents.
+
address@hidden Include files
address@hidden Include files
address@hidden include files, during export
+Include other files during export.  For example, to include your @file{.emacs}
+file, you could use:
address@hidden #+INCLUDE
+
address@hidden
+#+INCLUDE: "~/.emacs" src emacs-lisp
address@hidden example
+
address@hidden
+The first parameter is the file name to include.  The optional second
+parameter specifies the block type: @samp{example}, @samp{export} or
address@hidden  The optional third parameter specifies the source code language
+to use for formatting the contents.  This is relevant to both @samp{export}
+and @samp{src} block types.
+
+If an include file is specified as having a markup language, Org neither
+checks for valid syntax nor changes the contents in any way.  For
address@hidden and @samp{src} blocks, Org code-escapes the contents before
+inclusion.
+
+If an include file is not specified as having any markup language, Org
+assumes it be in Org format and proceeds as usual with a few exceptions.  Org
+makes the footnote labels (@pxref{Footnotes}) in the included file local to
+that file.  The contents of the included file will belong to the same
+structure---headline, item---containing the @code{INCLUDE} keyword.  In
+particular, headlines within the file will become children of the current
+section.  That behavior can be changed by providing an additional keyword
+parameter, @code{:minlevel}.  It shifts the headlines in the included file to
+become the lowest level.  For example, this syntax makes the included file
+a sibling of the current top-level headline:
+
address@hidden
+#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1
address@hidden example
+
+Inclusion of only portions of files are specified using ranges parameter with
address@hidden:lines} keyword.  The line at the upper end of the range will not 
be
+included.  The start and/or the end of the range may be omitted to use the
+obvious defaults.
+
address@hidden
+#+INCLUDE: "~/.emacs" :lines "5-10"   @r{Include lines 5 to 10, 10 excluded}
+#+INCLUDE: "~/.emacs" :lines "-10"    @r{Include lines 1 to 10, 10 excluded}
+#+INCLUDE: "~/.emacs" :lines "10-"    @r{Include lines from 10 to EOF}
address@hidden example
+
+Inclusions may specify a file-link to extract an object matched by
address@hidden@footnote{Note that
address@hidden is locally bound to
address@hidden  Therefore, @code{org-link-search} only matches headlines and
+named elements.}  (@pxref{Search options}).
+
+To extract only the contents of the matched object, set @code{:only-contents}
+property to address@hidden  This will omit any planning lines or property
+drawers.  The ranges for @code{:lines} keyword are relative to the requested
+element.  Some examples:
+
address@hidden
+#+INCLUDE: "./paper.org::#theory" :only-contents t
+   @r{Include the body of the heading with the custom id @samp{theory}}
+#+INCLUDE: "./paper.org::mytable"  @r{Include named element.}
+#+INCLUDE: "./paper.org::*conclusion" :lines 1-20
+   @r{Include the first 20 lines of the headline named @samp{conclusion}.}
address@hidden example
+
address@hidden @kbd
address@hidden C-c '
address@hidden C-c '
+Visit the include file at point.
address@hidden table
+
address@hidden Macro replacement
address@hidden Macro replacement
address@hidden macro replacement, during export
address@hidden #+MACRO
+
+Macros replace text snippets during export.  This is a macro definition in
+Org:
+
address@hidden
+#+MACRO: name   replacement text $1, $2 are arguments
address@hidden example
+
address@hidden which can be referenced using
address@hidden@address@hidden@{name(arg1, arg2)@address@hidden@address@hidden 
commas separate the
+arguments, commas within arguments have to be escaped with the backslash
+character.  So only those backslash characters before a comma need escaping
+with another backslash character.}.
+
+Org recognizes macro references in following Org markup areas: paragraphs,
+headlines, verse blocks, tables cells and lists.  Org also recognizes macro
+references in keywords, such as @code{#+CAPTION}, @code{#+TITLE},
address@hidden, @code{#+DATE}, and for some back-end specific export
+options.
+
+Org comes with following pre-defined macros:
+
address@hidden @code
address@hidden @address@hidden@address@hidden@address@hidden
address@hidden @address@hidden@address@hidden@address@hidden
address@hidden @address@hidden@address@hidden@address@hidden
address@hidden title, macro
address@hidden author, macro
address@hidden email, macro
+Org replaces these macro references with available information at the time of
+export.
+
address@hidden @address@hidden@address@hidden@address@hidden
address@hidden @address@hidden@{date(@var{FORMAT})@address@hidden@}
address@hidden date, macro
+This macro refers to the @code{#+DATE} keyword.  @var{FORMAT} is an optional
+argument to the @address@hidden@address@hidden@address@hidden@}} macro that 
will be used only if
address@hidden is a single timestamp.  @var{FORMAT} should be a format string
+understood by @code{format-time-string}.
+
address@hidden @address@hidden@{time(@var{FORMAT})@address@hidden@}
address@hidden @address@hidden@{modification-time(@var{FORMAT}, 
@var{VC})@address@hidden@}
address@hidden time, macro
address@hidden modification time, macro
+These macros refer to the document's date and time of export and date and
+time of modification.  @var{FORMAT} is a string understood by
address@hidden  If the second argument to the
address@hidden macro is address@hidden, Org uses @file{vc.el} to
+retrieve the document's modification time from the version control
+system.  Otherwise Org reads the file attributes.
+
address@hidden @address@hidden@address@hidden@address@hidden
address@hidden input file, macro
+This macro refers to the filename of the exported file.
+
address@hidden @address@hidden@{property(@var{PROPERTY-NAME})@address@hidden@}
address@hidden 
@address@hidden@{property(@var{PROPERTY-NAME},@var{SEARCH-OPTION})@address@hidden@}
address@hidden property, macro
+This macro returns the value of property @var{PROPERTY-NAME} in the current
+entry.  If @var{SEARCH-OPTION} (@pxref{Search options}) refers to a remote
+entry, that will be used instead.
address@hidden table
+
+The surrounding brackets can be made invisible by setting
address@hidden address@hidden
+
+Org expands macros at the very beginning of the export process.
 
address@hidden ASCII/Latin-1/UTF-8 export, Beamer export, Export settings, 
Exporting
address@hidden Comment lines
address@hidden Comment lines
address@hidden exporting, not
+
address@hidden comment lines
+Lines starting with zero or more whitespace characters followed by one
address@hidden and a whitespace are treated as comments and, as such, are not
+exported.
+
address@hidden #+BEGIN_COMMENT
+Likewise, regions surrounded by @samp{#+BEGIN_COMMENT}
+... @samp{#+END_COMMENT} are not exported.
+
address@hidden comment trees
+Finally, a @samp{COMMENT} keyword at the beginning of an entry, but after any
+other keyword or priority cookie, comments out the entire subtree.  In this
+case, the subtree is not exported and no code block within it is executed
address@hidden a less drastic behavior, consider using a select tag
+(@pxref{Export settings}) instead.}.  The command below helps changing the
+comment status of a headline.
+
address@hidden @kbd
address@hidden C-c ;
address@hidden C-c ;
+Toggle the @samp{COMMENT} keyword at the beginning of an entry.
address@hidden table
+
address@hidden ASCII/Latin-1/UTF-8 export
 @section ASCII/Latin-1/UTF-8 export
 @cindex ASCII export
 @cindex Latin-1 export
 @cindex UTF-8 export
 
-ASCII export produces a simple and very readable version of an Org mode
-file, containing only plain address@hidden  Latin-1 and UTF-8 export augment 
the file
-with special characters and symbols available in these encodings.
+ASCII export produces an output file containing only plain ASCII characters.
+This is the most simplest and direct text output.  It does not contain any
+Org markup either.  Latin-1 and UTF-8 export use additional characters and
+symbols available in these encoding standards.  All three of these export
+formats offer the most basic of text output for maximum portability.
+
address@hidden org-ascii-text-width
+On export, Org fills and justifies text according to the text width set in
address@hidden
 
 @vindex org-ascii-links-to-notes
-Links are exported in a footnote-like style, with the descriptive part in the
-text and the link in a note before the next heading.  See the variable
address@hidden for details and other options.
+Org exports links using a footnote-like style where the descriptive part is
+in the text and the link is in a note before the next heading.  See the
+variable @code{org-ascii-links-to-notes} for details.
 
 @subheading ASCII export commands
 
 @table @kbd
 @orgcmd{C-c C-e t a/l/u,org-ascii-export-to-ascii}
-Export as an ASCII file.  For an Org file, @file{myfile.org}, the ASCII file
-will be @file{myfile.txt}.  The file will be overwritten without warning.
-When the original file is @file{myfile.txt}, the resulting file becomes
address@hidden in order to prevent data loss.
+Export as an ASCII file with a @file{.txt} extension.  For @file{myfile.org},
+Org exports to @file{myfile.txt}, overwriting without warning.  For
address@hidden, Org exports to @file{myfile.txt.txt} in order to prevent
+data loss.
 @orgcmd{C-c C-e t A/L/U,org-ascii-export-as-ascii}
-Export to a temporary buffer.  Do not create a file.
+Export to a temporary buffer.  Does not create a file.
address@hidden table
+
address@hidden ASCII specific export settings
+The ASCII export back-end has one extra keyword for customizing ASCII output.
+Setting this keyword works similar to the general options (@pxref{Export
+settings}).
+
address@hidden @samp
address@hidden SUBTITLE
address@hidden #+SUBTITLE (ASCII)
+The document subtitle.  For long subtitles, use multiple @code{#+SUBTITLE}
+lines in the Org file.  Org prints them on one continuous line, wrapping into
+multiple lines if necessary.
 @end table
 
 @subheading Header and sectioning structure
 
-In the exported version, the first three outline levels become headlines,
-defining a general document structure.  Additional levels are exported as
-lists.  The transition can also occur at a different level (@pxref{Export
-settings}).
+Org converts the first three outline levels into headlines for ASCII export.
+The remaining levels are turned into lists.  To change this cut-off point
+where levels become lists, @pxref{Export settings}.
 
 @subheading Quoting ASCII text
 
-You can insert text that will only appear when using @code{ASCII} back-end
-with the following constructs:
+To insert text within the Org file by the ASCII back-end, use one the
+following constructs, inline, keyword, or export block:
 
 @cindex #+ASCII
address@hidden #+BEGIN_ASCII
address@hidden #+BEGIN_EXPORT ascii
 @example
-Text @@@@ascii:and additional text@@@@ within a paragraph.
+Inline text @@@@ascii:and additional text@@@@ within a paragraph.
 
 #+ASCII: Some text
 
-#+BEGIN_ASCII
-All lines in this block will appear only when using this back-end.
-#+END_ASCII
+#+BEGIN_EXPORT ascii
+Org exports text in this block only when using ASCII back-end.
+#+END_EXPORT
 @end example
 
 @subheading ASCII specific attributes
 @cindex #+ATTR_ASCII
 @cindex horizontal rules, in ASCII export
 
address@hidden back-end only understands one attribute, @code{:width}, which
-specifies the length, in characters, of a given horizontal rule.  It must be
-specified using an @code{ATTR_ASCII} line, directly preceding the rule.
+ASCII back-end recognizes only one attribute, @code{:width}, which specifies
+the width of an horizontal rule in number of characters.  The keyword and
+syntax for specifying widths is:
 
 @example
 #+ATTR_ASCII: :width 10
 -----
 @end example
 
address@hidden Beamer export, HTML export, ASCII/Latin-1/UTF-8 export, Exporting
address@hidden ASCII special blocks
address@hidden special blocks, in ASCII export
address@hidden #+BEGIN_JUSTIFYLEFT
address@hidden #+BEGIN_JUSTIFYRIGHT
+
+Besides @code{#+BEGIN_CENTER} blocks (@pxref{Paragraphs}), ASCII back-end has
+these two left and right justification blocks:
+
address@hidden
+#+BEGIN_JUSTIFYLEFT
+It's just a jump to the left...
+#+END_JUSTIFYLEFT
+
+#+BEGIN_JUSTIFYRIGHT
+...and then a step to the right.
+#+END_JUSTIFYRIGHT
address@hidden example
+
address@hidden Beamer export
 @section Beamer export
 @cindex Beamer export
 
-The @LaTeX{} class @emph{Beamer} allows production of high quality
-presentations using @LaTeX{} and pdf processing.  Org mode has special
-support for turning an Org mode file or tree into a Beamer presentation.
+Org uses @emph{Beamer} export to convert an Org file tree structure into a
+high-quality interactive slides for presentations.  @emph{Beamer} is a
address@hidden document class for creating presentations in PDF, HTML, and other
+popular display formats.
+
address@hidden
+* Beamer export commands::      For creating Beamer documents.
+* Beamer specific export settings::  For customizing Beamer export.
+* Sectioning Frames and Blocks in Beamer::  For composing Beamer slides.
+* Beamer specific syntax::      For using in Org documents.
+* Editing support::             For using helper functions.
+* A Beamer example::            A complete presentation.
address@hidden menu
 
address@hidden Beamer export commands
address@hidden Beamer export commands
address@hidden Beamer export commands
 
 @table @kbd
 @orgcmd{C-c C-e l b,org-beamer-export-to-latex}
-Export as a @LaTeX{} file.  For an Org file @file{myfile.org}, the @LaTeX{}
-file will be @file{myfile.tex}.  The file will be overwritten without
-warning.
+Export as @LaTeX{} file with a @file{.tex} extension.  For @file{myfile.org},
+Org exports to @file{myfile.tex}, overwriting without warning.
 @orgcmd{C-c C-e l B,org-beamer-export-as-latex}
-Export to a temporary buffer.  Do not create a file.
+Export to a temporary buffer.  Does not create a file.
 @orgcmd{C-c C-e l P,org-beamer-export-to-pdf}
-Export as @LaTeX{} and then process to PDF.
+Export as @LaTeX{} file and then convert it to PDF format.
 @item C-c C-e l O
-Export as @LaTeX{} and then process to PDF, then open the resulting PDF file.
+Export as @LaTeX{} file, convert it to PDF format, and then open the PDF
+file.
 @end table
 
address@hidden Sectioning, Frames and Blocks
address@hidden Beamer specific export settings
address@hidden Beamer specific export settings
+
+Beamer export back-end has several additional keywords for customizing Beamer
+output.  These keywords work similar to the general options settings
+(@pxref{Export settings}).
+
address@hidden @samp
address@hidden BEAMER_THEME
address@hidden #+BEAMER_THEME
address@hidden org-beamer-theme
+The Beamer layout theme (@code{org-beamer-theme}).  Use square brackets for
+options.  For example:
address@hidden
+#+BEAMER_THEME: Rochester [height=20pt]
address@hidden smallexample
+
address@hidden BEAMER_FONT_THEME
address@hidden #+BEAMER_FONT_THEME
+The Beamer font theme.
+
address@hidden BEAMER_INNER_THEME
address@hidden #+BEAMER_INNER_THEME
+The Beamer inner theme.
+
address@hidden BEAMER_OUTER_THEME
address@hidden #+BEAMER_OUTER_THEME
+The Beamer outer theme.
 
-Any tree with not-too-deep level nesting should in principle be exportable as
-a Beamer presentation.  Headlines fall into three categories: sectioning
-elements, frames and blocks.
address@hidden BEAMER_HEADER
address@hidden #+BEAMER_HEADER
+Arbitrary lines inserted in the preamble, just before the @samp{hyperref}
+settings.
+
address@hidden DESCRIPTION
address@hidden #+DESCRIPTION (Beamer)
+The document description.  For long descriptions, use multiple
address@hidden keywords.  By default, @samp{hyperref} inserts
address@hidden as metadata.  Use @code{org-latex-hyperref-template} to
+configure document metadata.  Use @code{org-latex-title-command} to configure
+typesetting of description as part of front matter.
+
address@hidden KEYWORDS
address@hidden #+KEYWORDS (Beamer)
+The keywords for defining the contents of the document.  Use multiple
address@hidden lines if necessary.  By default, @samp{hyperref} inserts
address@hidden as metadata.  Use @code{org-latex-hyperref-template} to
+configure document metadata.  Use @code{org-latex-title-command} to configure
+typesetting of keywords as part of front matter.
+
address@hidden SUBTITLE
address@hidden #+SUBTITLE (Beamer)
address@hidden org-beamer-subtitle-format
+Document's subtitle.  For typesetting, use @code{org-beamer-subtitle-format}
+string.  Use @code{org-latex-hyperref-template} to configure document
+metadata.  Use @code{org-latex-title-command} to configure typesetting of
+subtitle as part of front matter.
address@hidden table
+
address@hidden Sectioning Frames and Blocks in Beamer
address@hidden Sectioning, Frames and Blocks in Beamer
+
+Org transforms heading levels into Beamer's sectioning elements, frames and
+blocks.  Any Org tree with a not-too-deep-level nesting should in principle
+be exportable as a Beamer presentation.
 
 @itemize @minus
 @item
 @vindex org-beamer-frame-level
-Headlines become frames when their level is equal to
+Org headlines become Beamer frames when the heading level in Org is equal to
 @code{org-beamer-frame-level} or @code{H} value in an @code{OPTIONS} line
 (@pxref{Export settings}).
 
 @cindex property, BEAMER_ENV
-Though, if a headline in the current tree has a @code{BEAMER_ENV} property
-set to either to @code{frame} or @code{fullframe}, its level overrides the
-variable.  A @code{fullframe} is a frame with an empty (ignored) title.
+Org overrides headlines to frames conversion for the current tree of an Org
+file if it encounters the @code{BEAMER_ENV} property set to @code{frame} or
address@hidden  Org ignores whatever @code{org-beamer-frame-level} happens
+to be for that headline level in the Org tree.  In Beamer terminology, a
address@hidden is a frame without its title.
 
 @item
 @vindex org-beamer-environments-default
 @vindex org-beamer-environments-extra
-All frame's children become @code{block} environments.  Special block types
-can be enforced by setting headline's @code{BEAMER_ENV} address@hidden
-this property is set, the entry will also get a @code{:B_environment:} tag to
-make this visible.  This tag has no semantic meaning, it is only a visual
-aid.} to an appropriate value (see @code{org-beamer-environments-default} for
-supported values and @code{org-beamer-environments-extra} for adding more).
+Org exports a Beamer frame's objects as @code{block} environments.  Org can
+enforce wrapping in special block types when @code{BEAMER_ENV} property is
address@hidden @code{BEAMER_ENV} is set, Org export adds
address@hidden:B_environment:} tag to make it visible.  The tag serves as a 
visual
+aid and has no semantic relevance.}.  For valid values see
address@hidden  To add more values, see
address@hidden
 
 @item
 @cindex property, BEAMER_REF
-As a special case, if the @code{BEAMER_ENV} property is set to either
address@hidden, @code{note}, @code{noteNH} or @code{againframe}, the
-headline will become, respectively, an appendix, a note (within frame or
-between frame, depending on its level), a note with its title ignored or an
address@hidden command.  In the latter case, a @code{BEAMER_REF} property
-is mandatory in order to refer to the frame being resumed, and contents are
-ignored.
-
-Also, a headline with an @code{ignoreheading} environment will have its
-contents only inserted in the output.  This special value is useful to have
-data between frames, or to properly close a @code{column} environment.
+If @code{BEAMER_ENV} is set to @code{appendix}, Org exports the entry as an
+appendix.  When set to @code{note}, Org exports the entry as a note within
+the frame or between frames, depending on the entry's heading level.  When
+set to @code{noteNH}, Org exports the entry as a note without its title.
+When set to @code{againframe}, Org exports the entry with @code{\againframe}
+command, which makes setting the @code{BEAMER_REF} property mandatory because
address@hidden needs frame to resume.
+
+When @code{ignoreheading} is set, Org export ignores the entry's headline but
+not its content.  This is useful for inserting content between frames.  It is
+also useful for properly closing a @code{column} environment.
 @end itemize
 
 @cindex property, BEAMER_ACT
 @cindex property, BEAMER_OPT
-Headlines also support @code{BEAMER_ACT} and @code{BEAMER_OPT} properties.
-The former is translated as an overlay/action specification, or a default
-overlay specification when enclosed within square brackets.  The latter
-specifies address@hidden @code{fragile} option is added automatically
-if it contains code that requires a verbatim environment, though.} for the
-current frame or block.  The export back-end will automatically wrap
-properties within angular or square brackets when appropriate.
+When @code{BEAMER_ACT} is set for a headline, Org export translates that
+headline as an overlay or action specification.  When enclosed in square
+brackets, Org export makes the overlay specification a default.  Use
address@hidden to set any options applicable to the current Beamer frame
+or block.  The Beamer export back-end wraps with appropriate angular or
+square brackets.  It also adds the @code{fragile} option for any code that may
+require a verbatim block.
 
 @cindex property, BEAMER_COL
-Moreover, headlines handle the @code{BEAMER_COL} property.  Its value should
-be a decimal number representing the width of the column as a fraction of the
-total text width.  If the headline has no specific environment, its title
-will be ignored and its contents will fill the column created.  Otherwise,
-the block will fill the whole column and the title will be preserved.  Two
-contiguous headlines with a address@hidden @code{BEAMER_COL} value share the 
same
address@hidden @LaTeX{} environment.  It will end before the next headline
-without such a property.  This environment is generated automatically.
-Although, it can also be explicitly created, with a special @code{columns}
-value for @code{BEAMER_ENV} property (if it needs to be set up with some
-specific options, for example).
-
address@hidden Beamer specific syntax
-
-Beamer back-end is an extension of @LaTeX{} back-end.  As such, all @LaTeX{}
-specific syntax (e.g., @samp{#+LATEX:} or @samp{#+ATTR_LATEX:}) is
-recognized.  See @address@hidden and PDF export} for more information.
-
address@hidden #+BEAMER_THEME
address@hidden #+BEAMER_COLOR_THEME
address@hidden #+BEAMER_FONT_THEME
address@hidden #+BEAMER_INNER_THEME
address@hidden #+BEAMER_OUTER_THEME
-Beamer export introduces a number of keywords to insert code in the
-document's header.  Four control appearance of the presentation:
address@hidden, @code{#+BEAMER_COLOR_THEME},
address@hidden, @code{#+BEAMER_INNER_THEME} and
address@hidden  All of them accept optional arguments
-within square brackets.  The last one, @code{#+BEAMER_HEADER}, is more
-generic and allows you to append any line of code in the header.
-
address@hidden
-#+BEAMER_THEME: Rochester [height=20pt]
-#+BEAMER_COLOR_THEME: spruce
address@hidden example
-
-Table of contents generated from @code{toc:t} @code{OPTION} keyword are
-wrapped within a @code{frame} environment.  Those generated from a @code{TOC}
-keyword (@pxref{Table of contents}) are not.  In that case, it is also
-possible to specify options, enclosed within square brackets.
+To create a column on the Beamer slide, use the @code{BEAMER_COL} property
+for its headline in the Org file.  Set the value of @code{BEAMER_COL} to a
+decimal number representing the fraction of the total text width.  Beamer
+export uses this value to set the column's width and fills the column with
+the contents of the Org entry.  If the Org entry has no specific environment
+defined, Beamer export ignores the heading.  If the Org entry has a defined
+environment, Beamer export uses the heading as title.  Behind the scenes,
+Beamer export automatically handles @LaTeX{} column separations for
+contiguous headlines.  To manually adjust them for any unique configurations
+needs, use the @code{BEAMER_ENV} property.
+
address@hidden Beamer specific syntax
address@hidden Beamer specific syntax
+Since Org's Beamer export back-end is an extension of the @LaTeX{} back-end,
+it recognizes other @LaTeX{} specific syntax---for example, @samp{#+LATEX:}
+or @samp{#+ATTR_LATEX:}.  @address@hidden export}, for details.
+
+Beamer export wraps the table of contents generated with @code{toc:t}
address@hidden keyword in a @code{frame} environment.  Beamer export does not
+wrap the table of contents generated with @code{TOC} keyword (@pxref{Table of
+contents}).  Use square brackets for specifying options.
 
 @example
 #+TOC: headlines [currentsection]
 @end example
 
-Beamer specific code can be inserted with the following constructs:
+Insert Beamer-specific code using the following constructs:
 
 @cindex #+BEAMER
address@hidden #+BEGIN_BEAMER
address@hidden #+BEGIN_EXPORT beamer
 @example
 #+BEAMER: \pause
 
-#+BEGIN_BEAMER
-All lines in this block will appear only when using this back-end.
+#+BEGIN_EXPORT beamer
+Only Beamer export back-end will export this line.
 #+END_BEAMER
 
 Text @@@@beamer:some code@@@@ within a paragraph.
 @end example
 
-In particular, this last example can be used to add overlay specifications to
-objects whose type is among @code{bold}, @code{item}, @code{link},
address@hidden and @code{target}, when the value is enclosed within
-angular brackets and put at the beginning the object.
+Inline constructs, such as the last one above, are useful for adding overlay
+specifications to objects with @code{bold}, @code{item}, @code{link},
address@hidden and @code{target} types.  Enclose the value in angular
+brackets and place the specification at the beginning the object as shown in
+this example:
 
 @example
 A *@@@@beamer:<2->@@@@useful* feature
 @end example
 
 @cindex #+ATTR_BEAMER
-Eventually, every plain list has support for @code{:environment},
address@hidden:overlay} and @code{:options} attributes through
address@hidden affiliated keyword.  The first one allows the use
-of a different environment, the second sets overlay specifications and
-the last one inserts optional arguments in current list environment.
+Beamer export recognizes the @code{ATTR_BEAMER} keyword with the following
+attributes from Beamer configurations: @code{:environment} for changing local
+Beamer environment, @code{:overlay} for specifying Beamer overlays in angular
+or square brackets, and @code{:options} for inserting optional arguments.
 
 @example
-#+ATTR_BEAMER: :overlay +-
+#+ATTR_BEAMER: :environment nonindentlist
+- item 1, not indented
+- item 2, not indented
+- item 3, not indented
address@hidden example
+
address@hidden
+#+ATTR_BEAMER: :overlay <+->
 - item 1
 - item 2
 @end example
 
address@hidden Editing support
address@hidden
+#+ATTR_BEAMER: :options [Lagrange]
+Let $G$ be a finite group, and let $H$ be
+a subgroup of $G$.  Then the order of $H$ divides the order of $G$.
address@hidden example
+
address@hidden Editing support
address@hidden Editing support
 
-You can turn on a special minor mode @code{org-beamer-mode} for faster
-editing with:
+
+The @code{org-beamer-mode} is a special minor mode for faster editing of
+Beamer documents.
 
 @example
 #+STARTUP: beamer
@@ -10959,23 +11251,19 @@ editing with:
 
 @table @kbd
 @orgcmd{C-c C-b,org-beamer-select-environment}
-In @code{org-beamer-mode}, this key offers fast selection of a Beamer
-environment or the @code{BEAMER_COL} property.
+The @code{org-beamer-mode} provides this key for quicker selections in Beamer
+normal environments, and for selecting the @code{BEAMER_COL} property.
 @end table
 
-Also, a template for useful in-buffer settings or properties can be inserted
-into the buffer with @kbd{M-x org-beamer-insert-options-template}.  Among
-other things, this will install a column view format which is very handy for
-editing special properties used by Beamer.
-
address@hidden An example
address@hidden A Beamer example
address@hidden A Beamer example
 
-Here is a simple example Org document that is intended for Beamer export.
+Here is an example of an Org document ready for Beamer export.
 
address@hidden
address@hidden
 #+TITLE: Example Presentation
 #+AUTHOR: Carsten Dominik
-#+OPTIONS: H:2
+#+OPTIONS: H:2 toc:t num:t
 #+LATEX_CLASS: beamer
 #+LATEX_CLASS_OPTIONS: [presentation]
 #+BEAMER_THEME: Madrid
@@ -10984,91 +11272,148 @@ Here is a simple example Org document that is 
intended for Beamer export.
 * This is the first structural section
 
 ** Frame 1
-*** Thanks to Eric Fraga                                           
:B_block:BMCOL:
+*** Thanks to Eric Fraga                                           :B_block:
     :PROPERTIES:
     :BEAMER_COL: 0.48
     :BEAMER_ENV: block
     :END:
     for the first viable Beamer setup in Org
-*** Thanks to everyone else                                        
:B_block:BMCOL:
+*** Thanks to everyone else                                        :B_block:
     :PROPERTIES:
     :BEAMER_COL: 0.48
     :BEAMER_ACT: <2->
     :BEAMER_ENV: block
     :END:
     for contributing to the discussion
-**** This will be formatted as a beamer note                              
:B_note:
+**** This will be formatted as a beamer note                       :B_note:
      :PROPERTIES:
      :BEAMER_env: note
      :END:
 ** Frame 2 (where we will not use columns)
 *** Request
     Please test this stuff!
address@hidden smallexample
address@hidden example
 
address@hidden HTML export, @LaTeX{} and PDF export, Beamer export, Exporting
address@hidden HTML export
 @section HTML export
 @cindex HTML export
 
-Org mode contains an HTML (XHTML 1.0 strict) exporter with extensive
-HTML formatting, in ways similar to John Gruber's @emph{markdown}
-language, but with additional support for tables.
+Org mode contains an HTML exporter with extensive HTML formatting compatible
+with XHTML 1.0 strict standard.
 
 @menu
-* HTML Export commands::        How to invoke HTML export
-* HTML doctypes::               Org can export to various (X)HTML flavors
-* HTML preamble and postamble::  How to insert a preamble and a postamble
-* Quoting HTML tags::           Using direct HTML in Org mode
-* Links in HTML export::        How links will be interpreted and formatted
-* Tables in HTML export::       How to modify the formatting of tables
-* Images in HTML export::       How to insert figures into HTML output
-* Math formatting in HTML export::  Beautiful math also on the web
-* Text areas in HTML export::   An alternative way to show an example
-* CSS support::                 Changing the appearance of the output
-* JavaScript support::          Info and Folding in a web browser
+* HTML Export commands::        Invoking HTML export
+* HTML Specific export settings::  Settings for HTML export
+* HTML doctypes::               Exporting various (X)HTML flavors
+* HTML preamble and postamble::  Inserting preamble and postamble
+* Quoting HTML tags::           Using direct HTML in Org files
+* Links in HTML export::        Interpreting and formatting links
+* Tables in HTML export::       Formatting and modifying tables
+* Images in HTML export::       Inserting figures with HTML output
+* Math formatting in HTML export::  Handling math equations
+* Text areas in HTML export::   Showing an alternate approach, an example
+* CSS support::                 Styling HTML output
+* JavaScript support::          Folding scripting in the web browser
 @end menu
 
address@hidden HTML Export commands, HTML doctypes, HTML export, HTML export
+
address@hidden HTML Export commands
 @subsection HTML export commands
 
 @table @kbd
 @orgcmd{C-c C-e h h,org-html-export-to-html}
-Export as an HTML file.  For an Org file @file{myfile.org},
-the HTML file will be @file{myfile.html}.  The file will be overwritten
-without warning.
address@hidden C-e h o}
-Export as an HTML file and immediately open it with a browser.
+Export as HTML file with a @file{.html} extension.  For @file{myfile.org},
+Org exports to @file{myfile.html}, overwriting without warning.  @kbd{C-c C-e
+h o} Exports to HTML and opens it in a web browser.
+
 @orgcmd{C-c C-e h H,org-html-export-as-html}
-Export to a temporary buffer.  Do not create a file.
+Exports to a temporary buffer.  Does not create a file.
 @end table
 
address@hidden FIXME Exporting sublevels
address@hidden @cindex headline levels, for exporting
address@hidden In the exported version, the first 3 outline levels will become 
headlines,
address@hidden defining a general document structure.  Additional levels will 
be exported as
address@hidden itemized lists.  If you want that transition to occur at a 
different level,
address@hidden specify it with a numeric prefix argument.  For example,
address@hidden HTML Specific export settings
address@hidden HTML Specific export settings
+HTML export has a number of keywords, similar to the general options settings
+described in @ref{Export settings}.
+
address@hidden @samp
address@hidden DESCRIPTION
address@hidden #+DESCRIPTION (HTML)
+This is the document's description, which the HTML exporter inserts it as a
+HTML meta tag in the HTML file.  For long descriptions, use multiple
address@hidden lines.  The exporter takes care of wrapping the lines
+properly.
+
address@hidden HTML_DOCTYPE
address@hidden #+HTML_DOCTYPE
address@hidden org-html-doctype
+Specify the document type, for example: HTML5 (@code{org-html-doctype}).
 
address@hidden @example
address@hidden @kbd{C-2 C-c C-e b}
address@hidden @end example
address@hidden HTML_CONTAINER
address@hidden #+HTML_CONTAINER
address@hidden org-html-container-element
+Specify the HTML container, such as @samp{div}, for wrapping sections and
+elements (@code{org-html-container-element}).
 
address@hidden @noindent
address@hidden creates two levels of headings and does the rest as items.
address@hidden HTML_LINK_HOME
address@hidden #+HTML_LINK_HOME
address@hidden org-html-link-home
+The URL for home link (@code{org-html-link-home}).
 
address@hidden HTML doctypes, HTML preamble and postamble, HTML Export 
commands, HTML export
address@hidden HTML_LINK_UP
address@hidden #+HTML_LINK_UP
address@hidden org-html-link-up
+The URL for the up link of exported HTML pages (@code{org-html-link-up}).
+
address@hidden HTML_MATHJAX
address@hidden #+HTML_MATHJAX
address@hidden org-html-mathjax-options
+Options for MathJax (@code{org-html-mathjax-options}).  MathJax is used to
+typeset @LaTeX{} math in HTML documents.  @xref{Math formatting in HTML
+export}, for an example.
+
address@hidden HTML_HEAD
address@hidden #+HTML_HEAD
address@hidden org-html-head
+Arbitrary lines for appending to the HTML document's head
+(@code{org-html-head}).
+
address@hidden HTML_HEAD_EXTRA
address@hidden #+HTML_HEAD_EXTRA
address@hidden org-html-head-extra
+More arbitrary lines for appending to the HTML document's head
+(@code{org-html-head-extra}).
+
address@hidden KEYWORDS
address@hidden #+KEYWORDS (HTML)
+Keywords to describe the document's content.  HTML exporter inserts these
+keywords as HTML meta tags.  For long keywords, use multiple
address@hidden lines.
+
address@hidden LATEX_HEADER
address@hidden #+LATEX_HEADER (HTML)
+Arbitrary lines for appending to the preamble; HTML exporter appends when
+transcoding @LaTeX{} fragments to images (@pxref{Math formatting in HTML
+export}).
+
address@hidden SUBTITLE
address@hidden #+SUBTILE (HTML)
+The document's subtitle.  HTML exporter formats subtitle if document type is
address@hidden and the CSS has a @samp{subtitle} class.
address@hidden table
+
+Some of these keywords are explained in more detail in the following sections
+of the manual.
+
address@hidden HTML doctypes
 @subsection HTML doctypes
address@hidden org-html-doctype
address@hidden org-html-doctype-alist
 
 Org can export to various (X)HTML flavors.
 
-Setting the variable @code{org-html-doctype} allows you to export to different
-(X)HTML variants.  The exported HTML will be adjusted according to the syntax
-requirements of that variant.  You can either set this variable to a doctype
-string directly, in which case the exporter will try to adjust the syntax
-automatically, or you can use a ready-made doctype.  The ready-made options
-are:
address@hidden org-html-doctype
address@hidden org-html-doctype-alist
+Set the @code{org-html-doctype} variable for different (X)HTML variants.
+Depending on the variant, the HTML exporter adjusts the syntax of HTML
+conversion accordingly.  Org includes the following ready-made variants:
 
 @itemize
 @item
@@ -11091,23 +11436,21 @@ are:
 ``xhtml5''
 @end itemize
 
-See the variable @code{org-html-doctype-alist} for details.  The default is
-``xhtml-strict''.
address@hidden See the variable @code{org-html-doctype-alist} for details.
+The default is ``xhtml-strict''.
 
address@hidden Fancy HTML5 export
 @vindex org-html-html5-fancy
address@hidden org-html-html5-elements
-
-HTML5 introduces several new element types.  By default, Org will not make
-use of these element types, but you can set @code{org-html-html5-fancy} to
address@hidden (or set @code{html5-fancy} item in an @code{OPTIONS} line), to
-enable a few new block-level elements.  These are created using arbitrary
-#+BEGIN and #+END blocks. For instance:
address@hidden HTML5, export new elements
+Org's HTML exporter does not by default enable new block elements introduced
+with the HTML5 standard.  To enable them, set @code{org-html-html5-fancy} to
address@hidden  Or use an @code{OPTIONS} line in the file to set
address@hidden  HTML5 documents can now have arbitrary #+BEGIN and #+END
+blocks.  For example:
 
 @example
-#+BEGIN_ASIDE
+#+BEGIN_aside
 Lorem ipsum
-#+END_ASIDE
+#+END_aside
 @end example
 
 Will export to:
@@ -11122,14 +11465,14 @@ While this:
 
 @example
 #+ATTR_HTML: :controls controls :width 350
-#+BEGIN_VIDEO
+#+BEGIN_video
 #+HTML: <source src="movie.mp4" type="video/mp4">
 #+HTML: <source src="movie.ogg" type="video/ogg">
 Your browser does not support the video tag.
-#+END_VIDEO
+#+END_video
 @end example
 
-Becomes:
+Exports to:
 
 @example
 <video controls="controls" width="350">
@@ -11139,15 +11482,17 @@ Becomes:
 </video>
 @end example
 
-Special blocks that do not correspond to HTML5 elements (see
address@hidden) will revert to the usual behavior, i.e.,
address@hidden will still export to @samp{<div class="lederhosen">}.
address@hidden org-html-html5-elements
+When special blocks do not have a corresponding HTML5 element, the HTML
+exporter reverts to standard translation (see
address@hidden).  For example, @code{#+BEGIN_lederhosen}
+exports to @samp{<div class="lederhosen">}.
 
-Headlines cannot appear within special blocks.  To wrap a headline and its
-contents in e.g., @samp{<section>} or @samp{<article>} tags, set the
address@hidden property on the headline itself.
+Special blocks cannot have headlines.  For the HTML exporter to wrap the
+headline and its contents in @samp{<section>} or @samp{<article>} tags, set
+the @code{HTML_CONTAINER} property for the headline.
 
address@hidden HTML preamble and postamble, Quoting HTML tags, HTML doctypes, 
HTML export
address@hidden HTML preamble and postamble
 @subsection HTML preamble and postamble
 @vindex org-html-preamble
 @vindex org-html-postamble
@@ -11157,69 +11502,77 @@ contents in e.g., @samp{<section>} or 
@samp{<article>} tags, set the
 @vindex org-export-creator-string
 @vindex org-export-time-stamp-file
 
-The HTML exporter lets you define a preamble and a postamble.
-
-The default value for @code{org-html-preamble} is @code{t}, which means
-that the preamble is inserted depending on the relevant format string in
address@hidden
-
-Setting @code{org-html-preamble} to a string will override the default format
-string.  If you set it to a function, it will insert the output of the
-function, which must be a string.  Setting to @code{nil} will not insert any
-preamble.
-
-The default value for @code{org-html-postamble} is @code{'auto}, which means
-that the HTML exporter will look for information about the author, the email,
-the creator and the date, and build the postamble from these values.  Setting
address@hidden to @code{t} will insert the postamble from the
-relevant format string found in @code{org-html-postamble-format}.  Setting it
-to @code{nil} will not insert any postamble.
-
address@hidden Quoting HTML tags, Links in HTML export, HTML preamble and 
postamble, HTML export
+The HTML exporter has delineations for preamble and postamble.  The default
+value for @code{org-html-preamble} is @code{t}, which makes the HTML exporter
+insert the preamble.  See the variable @code{org-html-preamble-format} for
+the format string.
+
+Set @code{org-html-preamble} to a string to override the default format
+string.  If the string is a function, the HTML exporter expects the function
+to return a string upon execution.  The HTML exporter inserts this string in
+the preamble.  The HTML exporter will not insert a preamble if
address@hidden is set @code{nil}.
+
+The default value for @code{org-html-postamble} is @code{auto}, which makes
+the HTML exporter build a postamble from looking up author's name, email
+address, creator's name, and date.  Set @code{org-html-postamble} to @code{t}
+to insert the postamble in the format specified in the
address@hidden variable.  The HTML exporter will not insert
+a postamble if @code{org-html-postamble} is set to @code{nil}.
+
address@hidden Quoting HTML tags
 @subsection Quoting HTML tags
 
-Plain @samp{<} and @samp{>} are always transformed to @samp{&lt;} and
address@hidden&gt;} in HTML export.  If you want to include raw HTML code, which
-should only appear in HTML export, mark it with @samp{@@@@html:} as in
address@hidden@@@@html:<b>@@@@bold text@@@@html:</b>@@@@}.  For more extensive 
HTML
-that should be copied verbatim to the exported file use either
+The HTML export back-end transforms @samp{<} and @samp{>} to @samp{&lt;} and
address@hidden&gt;}.  To include raw HTML code in the Org file so the HTML 
export
+back-end can insert that HTML code in the output, use this inline syntax:
address@hidden@@@@html:}.  For example: @samp{@@@@html:<b>@@@@bold
+text@@@@html:</b>@@@@}.  For larger raw HTML code blocks, use these HTML
+export code blocks:
 
 @cindex #+HTML
address@hidden #+BEGIN_HTML
address@hidden #+BEGIN_EXPORT html
 @example
 #+HTML: Literal HTML code for export
 @end example
 
 @noindent or
address@hidden #+BEGIN_HTML
address@hidden #+BEGIN_EXPORT html
 
 @example
-#+BEGIN_HTML
+#+BEGIN_EXPORT html
 All lines between these markers are exported literally
-#+END_HTML
+#+END_EXPORT
 @end example
 
 
address@hidden Links in HTML export, Tables in HTML export, Quoting HTML tags, 
HTML export
address@hidden Links in HTML export
 @subsection Links in HTML export
 
 @cindex links, in HTML export
 @cindex internal links, in HTML export
 @cindex external links, in HTML export
-Internal links (@pxref{Internal links}) will continue to work in 
address@hidden  This
-includes automatic links created by radio targets (@pxref{Radio
-targets}).  Links to external files will still work if the target file is on
-the same @i{relative} path as the published Org file.  Links to other
address@hidden files will be translated into HTML links under the assumption
-that an HTML version also exists of the linked file, at the same relative
-path.  @samp{id:} links can then be used to jump to specific entries across
-files.  For information related to linking files while publishing them to a
-publishing directory see @ref{Publishing links}.
-
-If you want to specify attributes for links, you can do so using a special
address@hidden line to define attributes that will be added to the
address@hidden<a>} or @code{<img>} tags.  Here is an example that sets 
@code{title}
-and @code{style} attributes for a link:
address@hidden org-html-link-org-files-as-html
+The HTML export back-end transforms Org's internal links (@pxref{Internal
+links}) to equivalent HTML links in the output.  The back-end similarly
+handles Org's automatic links created by radio targets (@pxref{Radio
+targets}) similarly.  For Org links to external files, the back-end
+transforms the links to @emph{relative} paths.
+
+For Org links to other @file{.org} files, the back-end automatically changes
+the file extension to @file{.html} and makes file paths relative.  If the
address@hidden files have an equivalent @file{.html} version at the same
+location, then the converted links should work without any further manual
+intervention.  However, to disable this automatic path translation, set
address@hidden to @code{nil}.  When disabled, the
+HTML export back-end substitutes the @samp{id:}-based links in the HTML
+output.  For more about linking files when publishing to a directory,
address@hidden links}.
+
+Org files can also have special directives to the HTML export back-end.  For
+example, by using @code{#+ATTR_HTML} lines to specify new format attributes
+to @code{<a>} or @code{<img>} tags.  This example shows changing the link's
address@hidden and @code{style}:
 
 @cindex #+ATTR_HTML
 @example
@@ -11227,15 +11580,15 @@ and @code{style} attributes for a link:
 [[http://orgmode.org]]
 @end example
 
address@hidden Tables in HTML export, Images in HTML export, Links in HTML 
export, HTML export
address@hidden Tables
address@hidden Tables in HTML export
address@hidden Tables in HTML export
 @cindex tables, in HTML
 @vindex org-html-table-default-attributes
 
-Org mode tables are exported to HTML using the table attributes defined in
address@hidden  The default setting makes tables
-without cell borders and frame.  If you would like to change this for
-individual tables, place something like the following before the table:
+The HTML export back-end uses @code{org-html-table-default-attributes} when
+exporting Org tables to HTML.  By default, the exporter does not draw frames
+and cell borders.  To change for this for a table, use the following lines
+before the table in the Org file:
 
 @cindex #+CAPTION
 @cindex #+ATTR_HTML
@@ -11244,36 +11597,72 @@ individual tables, place something like the following 
before the table:
 #+ATTR_HTML: :border 2 :rules all :frame border
 @end example
 
+The HTML export back-end preserves column groupings in Org tables
+(@pxref{Column groups}) when exporting to HTML.
+
+Additional options for customizing tables for  HTML export.
+
address@hidden @code
address@hidden org-html-table-align-individual-fields
address@hidden org-html-table-align-individual-fields
address@hidden attaches style attributes for alignment to each table field.
+
address@hidden org-html-table-caption-above
address@hidden org-html-table-caption-above
address@hidden places caption string at the beginning of the table.
+
address@hidden org-html-table-data-tags
address@hidden org-html-table-data-tags
+Opening and ending tags for table data fields.
+
address@hidden org-html-table-default-attributes
address@hidden org-html-table-default-attributes
+Default attributes and values for table tags.
+
address@hidden org-html-table-header-tags
address@hidden org-html-table-header-tags
+Opening and ending tags for table's header fields.
+
 @vindex org-html-table-row-tags
-You can also modify the default tags used for each row by setting
address@hidden  See the docstring for an example on
-how to use this option.
address@hidden org-html-table-row-tags
+Opening and ending tags for table rows.
+
address@hidden org-html-table-use-header-tags-for-first-column
address@hidden org-html-table-use-header-tags-for-first-column
address@hidden formats column one in tables with header tags.
address@hidden table
 
address@hidden Images in HTML export, Math formatting in HTML export, Tables in 
HTML export, HTML export
address@hidden Images in HTML export
 @subsection Images in HTML export
 
 @cindex images, inline in HTML
 @cindex inlining images in HTML
 @vindex org-html-inline-images
-HTML export can inline images given as links in the Org file, and
-it can make an image the clickable part of a link.  By
address@hidden see the variable
address@hidden, images are inlined if a link does
-not have a description.  So @samp{[[file:myimg.jpg]]} will be inlined,
-while @samp{[[file:myimg.jpg][the image]]} will just produce a link
address@hidden image} that points to the image.  If the description part
-itself is a @code{file:} link or a @code{http:} URL pointing to an
-image, this image will be inlined and activated so that clicking on the
-image will activate the link.  For example, to include a thumbnail that
-will link to a high resolution version of the image, you could use:
+
+The HTML export back-end has features to convert Org image links to HTML
+inline images and HTML clickable image links.
+
+When the link in the Org file has no description, the HTML export back-end by
+default in-lines that image.  For example: @samp{[[file:myimg.jpg]]} is
+in-lined, while @samp{[[file:myimg.jpg][the image]]} links to the text,
address@hidden image}.
+
+For more details, see the variable @code{org-html-inline-images}.
+
+On the other hand, if the description part of the Org link is itself another
+link, such as @code{file:} or @code{http:} URL pointing to an image, the HTML
+export back-end in-lines this image and links to the main image.  This Org
+syntax enables the back-end to link low-resolution thumbnail to the
+high-resolution version of the image, as shown in this example:
 
 @example
 [[file:highres.jpg][file:thumb.jpg]]
 @end example
 
-If you need to add attributes to an inlined image, use a @code{#+ATTR_HTML}.
-In the example below we specify the @code{alt} and @code{title} attributes to
-support text viewers and accessibility, and align it to the right.
+To change attributes of in-lined images, use @code{#+ATTR_HTML} lines in the
+Org file.  This example shows realignment to right, and adds @code{alt} and
address@hidden attributes in support of text viewers and modern web 
accessibility
+standards.
 
 @cindex #+CAPTION
 @cindex #+ATTR_HTML
@@ -11284,63 +11673,72 @@ support text viewers and accessibility, and align it 
to the right.
 @end example
 
 @noindent
-You could use @code{http} addresses just as well.
+The HTML export back-end copies the @code{http} links from the Org file as
+is.
 
address@hidden Math formatting in HTML export, Text areas in HTML export, 
Images in HTML export, HTML export
address@hidden Math formatting in HTML export
 @subsection Math formatting in HTML export
 @cindex MathJax
 @cindex dvipng
address@hidden dvisvgm
 @cindex imagemagick
 
 @LaTeX{} math snippets (@address@hidden fragments}) can be displayed in two
-different ways on HTML pages.  The default is to use the
address@hidden://www.mathjax.org, MathJax system} which should work out of the
-box with Org mode installation because @uref{http://orgmode.org} serves
address@hidden for Org mode users for small applications and for testing
-purposes.  @b{If you plan to use this regularly or on pages with significant
-page views, you should address@hidden instructions can be
-found on the MathJax website, see
address@hidden://www.mathjax.org/resources/docs/?installation.html}.} MathJax on
-your own server in order to limit the load of our server.}  To configure
address@hidden, use the variable @code{org-html-mathjax-options} or
-insert something like the following into the buffer:
-
address@hidden
-#+HTML_MATHJAX: align:"left" mathml:t path:"/MathJax/MathJax.js"
address@hidden example
+different ways on HTML pages.  The default is to use
address@hidden://www.mathjax.org, MathJax} which should work out of the box with
address@hidden default Org loads MathJax from @uref{https://cdnjs.com, 
cdnjs.com} as
+recommended by @uref{http://www.mathjax.org, MathJax}.}.  Some MathJax display
+options can be configured via @code{org-html-mathjax-options}, or in the
+buffer.  For example, with the following settings,
address@hidden
+#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
address@hidden smallexample
+equation labels will be displayed on the left marign and equations will be
+five ems from the left margin.
 
address@hidden See the docstring of the variable
address@hidden for the meaning of the parameters in
-this line.
address@hidden See the docstring of
address@hidden for all supported variables.  The MathJax
+template can be configure via @code{org-html-mathjax-template}.
 
 If you prefer, you can also request that @LaTeX{} fragments are processed
 into small images that will be inserted into the browser page.  Before the
 availability of MathJax, this was the default method for Org files.  This
-method requires that the @file{dvipng} program or @file{imagemagick} suite is
-available on your system.  You can still get this processing with
+method requires that the @file{dvipng} program, @file{dvisvgm} or
address@hidden suite is available on your system.  You can still get
+this processing with
 
 @example
 #+OPTIONS: tex:dvipng
 @end example
 
address@hidden
+#+OPTIONS: tex:dvisvgm
address@hidden example
+
 or:
 
 @example
 #+OPTIONS: tex:imagemagick
 @end example
 
address@hidden Text areas in HTML export, CSS support, Math formatting in HTML 
export, HTML export
address@hidden Text areas in HTML export
 @subsection Text areas in HTML export
 
 @cindex text areas, in HTML
-An alternative way to publish literal code examples in HTML is to use text
-areas, where the example can even be edited before pasting it into an
-application.  It is triggered by @code{:textarea} attribute at an
address@hidden or @code{src} block.
+Before Org mode's Babel, one popular approach to publishing code in HTML was
+by using @code{:textarea}.  The advantage of this approach was that copying
+and pasting was built into browsers with simple JavaScript commands.  Even
+editing before pasting was made simple.
+
+The HTML export back-end can create such text areas.  It requires an
address@hidden:} line as shown in the example below with the
address@hidden:textarea} option.  This must be followed by either an
address@hidden or a @code{src} code block.  Other Org block types will not
+honor the @code{:textarea} option.
 
-You may also use @code{:height} and @code{:width} attributes to specify the
-height and width of the text area, which default to the number of lines in
-the example, and 80, respectively.  For example
+By default, the HTML export back-end creates a text area 80 characters wide
+and height just enough to fit the content.  Override these defaults with
address@hidden:width} and @code{:height} options on the @code{#+ATTR_HTML:} 
line.
 
 @example
 #+ATTR_HTML: :textarea t :width 40
@@ -11352,7 +11750,7 @@ the example, and 80, respectively.  For example
 @end example
 
 
address@hidden CSS support, JavaScript support, Text areas in HTML export, HTML 
export
address@hidden CSS support
 @subsection CSS support
 @cindex CSS, for HTML export
 @cindex HTML export, CSS
@@ -11371,6 +11769,7 @@ p.author            @r{author information, including 
email}
 p.date              @r{publishing date}
 p.creator           @r{creator info, about org mode version}
 .title              @r{document title}
+.subtitle           @r{document subtitle}
 .todo               @r{TODO keywords, all not-done states}
 .done               @r{the DONE keywords, all states that count as done}
 .WAITING            @r{each TODO keyword also uses a class named after itself}
@@ -11388,7 +11787,7 @@ div.outline-text-N  @r{extra div for text at outline 
level N}
 .figure-number      @r{label like "Figure 1:"}
 .table-number       @r{label like "Table 1:"}
 .listing-number     @r{label like "Listing 1:"}
-div.figure          @r{how to format an inlined image}
+div.figure          @r{how to format an in-lined image}
 pre.src             @r{formatted source code}
 pre.example         @r{normal example}
 p.verse             @r{verse paragraph}
@@ -11396,6 +11795,7 @@ div.footnotes       @r{footnote section headline}
 p.footnote          @r{footnote definition paragraph, containing a footnote}
 .footref            @r{a footnote reference number (always a <sup>)}
 .footnum            @r{footnote number in footnote definition (always <sup>)}
+.org-svg            @r{default class for a linked @file{.svg} image}
 @end example
 
 @vindex org-html-style-default
@@ -11403,15 +11803,10 @@ p.footnote          @r{footnote definition paragraph, 
containing a footnote}
 @vindex org-html-head
 @vindex org-html-head-extra
 @cindex #+HTML_INCLUDE_STYLE
-Each exported file contains a compact default style that defines these
-classes in a basic address@hidden style is defined in the constant
address@hidden, which you should not modify.  To turn
-inclusion of these defaults off, customize
address@hidden or set @code{html-style} to
address@hidden in an @code{OPTIONS} line.}.  You may overwrite these settings, 
or
-add to them by using the variables @code{org-html-head} and
address@hidden  You can override the global values of these
-variables for each file by using these keywords:
+The HTML export back-end includes a compact default style in each exported
+HTML file.  To override the default style with another style, use these
+keywords in the Org file.  They will replace the global defaults the HTML
+exporter uses.
 
 @cindex #+HTML_HEAD
 @cindex #+HTML_HEAD_EXTRA
@@ -11420,38 +11815,49 @@ variables for each file by using these keywords:
 #+HTML_HEAD_EXTRA: <link rel="alternate stylesheet" type="text/css" 
href="style2.css" />
 @end example
 
+To just turn off the default style, customize
address@hidden variable, or use this option line in
+the Org file.
+
address@hidden
+#+OPTIONS: html-style:nil
address@hidden example
+
 @noindent
-For longer style definitions, you can use several such lines.  You could also
-directly write a @code{<style>} @code{</style>} section in this way, without
-referring to an external file.
+For longer style definitions, either use several @code{#+HTML_HEAD} and
address@hidden lines, or use @code{<style>} @code{</style>} blocks
+around them.  Both of these approaches can avoid referring to an external
+file.
 
-In order to add styles to a subtree, use the @code{:HTML_CONTAINER_CLASS:}
+In order to add styles to a sub-tree, use the @code{:HTML_CONTAINER_CLASS:}
 property to assign a class to the tree.  In order to specify CSS styles for a
 particular headline, you can use the id specified in a @code{:CUSTOM_ID:}
 property.
 
+Never change the @code{org-html-style-default} constant.  Instead use other
+simpler ways of customizing as described above.
+
+
 @c FIXME: More about header and footer styles
 @c FIXME: Talk about links and targets.
 
address@hidden JavaScript support,  , CSS support, HTML export
address@hidden JavaScript support
 @subsection JavaScript supported display of web pages
 
 @cindex Rose, Sebastian
 Sebastian Rose has written a JavaScript program especially designed to
 enhance the web viewing experience of HTML files created with Org.  This
-program allows you to view large files in two different ways.  The first one
-is an @emph{Info}-like mode where each section is displayed separately and
+program enhances large files in two different ways of viewing.  One is an
address@hidden mode where each section is displayed separately and
 navigation can be done with the @kbd{n} and @kbd{p} keys (and some other keys
 as well, press @kbd{?} for an overview of the available keys).  The second
-view type is a @emph{folding} view much like Org provides inside Emacs.  The
-script is available at @url{http://orgmode.org/org-info.js} and you can find
-the documentation for it at @url{http://orgmode.org/worg/code/org-info-js/}.
-We host the script at our site, but if you use it a lot, you might not want
-to be dependent on @url{http://orgmode.org} and prefer to install a local
-copy on your own web server.
+one has a @emph{folding} view, much like Org provides inside Emacs.  The
+script is available at @url{http://orgmode.org/org-info.js} and the
+documentation at @url{http://orgmode.org/worg/code/org-info-js/}.  The script
+is hosted on @url{http://orgmode.org}, but for reliability, prefer installing
+it on your own web server.
 
-All it then takes to use this program is adding a single line to the Org
-file:
+To use this program, just add this line to the Org file:
 
 @cindex #+INFOJS_OPT
 @example
@@ -11459,12 +11865,12 @@ file:
 @end example
 
 @noindent
-If this line is found, the HTML header will automatically contain the code
-needed to invoke the script.  Using the line above, you can set the following
-viewing options:
+The HTML header now has the code needed to automatically invoke the script.
+For setting options, use the syntax from the above line for options described
+below:
 
 @example
-path:    @r{The path to the script.  The default is to grab the script from}
+path:    @r{The path to the script.  The default grabs the script from}
          @address@hidden://orgmode.org/org-info.js}, but you might want to 
have}
          @r{a local copy and use a path like @samp{../scripts/org-info.js}.}
 view:    @r{Initial view when the website is first shown.  Possible values 
are:}
@@ -11494,105 +11900,204 @@ buttons: @r{Should view-toggle buttons be 
everywhere?  When @code{nil} (the}
 @vindex org-html-infojs-options
 @vindex org-html-use-infojs
 You can choose default values for these options by customizing the variable
address@hidden  If you always want to apply the script to your
-pages, configure the variable @code{org-html-use-infojs}.
address@hidden  If you want the script to always apply to
+your pages, configure the variable @code{org-html-use-infojs}.
 
address@hidden @LaTeX{} and PDF export, Markdown export, HTML export, Exporting
address@hidden @LaTeX{} and PDF export
address@hidden @LaTeX{} export
address@hidden @LaTeX{} export
 @cindex @LaTeX{} export
 @cindex PDF export
 
address@hidden export can produce an arbitrarily complex LaTeX document of any
-standard or custom document class.  With further address@hidden
-default @LaTeX{} output is designed for processing with @code{pdftex} or
address@hidden  It includes packages that are not compatible with @code{xetex} 
and
-possibly @code{luatex}.  The @LaTeX{} exporter can be configured to support
-alternative TeX engines, see the options
address@hidden and @code{org-latex-packages-alist}.},
-which the @LaTeX{} exporter is able to control, this back-end is able to
-produce PDF output.  Because the @LaTeX{} exporter can be configured to use
-the @code{hyperref} package, the default setup produces fully-linked PDF
-output.
-
-As in @LaTeX{}, blank lines are meaningful for this back-end: a paragraph
-will not be started if two contiguous syntactical elements are not separated
-by an empty line.
-
-This back-end also offers enhanced support for footnotes.  Thus, it handles
-nested footnotes, footnotes in tables and footnotes in a list item's
-description.
+The @LaTeX{} export back-end can handle complex documents, incorporate
+standard or custom @LaTeX{} document classes, generate documents using
+alternate @LaTeX{} engines, and produce fully linked PDF files with indexes,
+bibliographies, and tables of contents, destined for interactive online
+viewing or high-quality print publication.
+
+While the details are covered in-depth in this section, here are some quick
+references to variables for the impatient: for engines, see
address@hidden; for build sequences, see
address@hidden; for packages, see
address@hidden and @code{org-latex-packages-alist}.
+
+An important note about the @LaTeX{} export back-end: it is sensitive to
+blank lines in the Org document.  That's because @LaTeX{} itself depends on
+blank lines to tell apart syntactical elements, such as paragraphs.
 
 @menu
-* @LaTeX{} export commands::    How to export to LaTeX and PDF
-* Header and sectioning::       Setting up the export file structure
-* Quoting @LaTeX{} code::       Incorporating literal @LaTeX{} code
-* @LaTeX{} specific attributes::  Controlling @LaTeX{} output
+* @LaTeX{} export commands::    For producing @LaTeX{} and PDF documents.
+* @LaTeX{} specific export settings::  Unique to this @LaTeX{} back-end.
+* @LaTeX{} header and sectioning::  For file structure.
+* Quoting @LaTeX{} code::       Directly in the Org document.
+* Tables in @LaTeX{} export::   Attributes specific to tables.
+* Images in @LaTeX{} export::   Attributes specific to images.
+* Plain lists in @LaTeX{} export::  Attributes specific to lists.
+* Source blocks in @LaTeX{} export::  Attributes specific to source code 
blocks.
+* Example blocks in @LaTeX{} export::  Attributes specific to example blocks.
+* Special blocks in @LaTeX{} export::  Attributes specific to special blocks.
+* Horizontal rules in @LaTeX{} export::  Attributes specific to horizontal 
rules.
 @end menu
 
address@hidden @LaTeX{} export commands, Header and sectioning, @LaTeX{} and 
PDF export, @LaTeX{} and PDF export
address@hidden @LaTeX{} export commands
 @subsection @LaTeX{} export commands
 
 @table @kbd
 @orgcmd{C-c C-e l l,org-latex-export-to-latex}
-Export as a @LaTeX{} file.  For an Org file @file{myfile.org}, the @LaTeX{}
-file will be @file{myfile.tex}.  The file will be overwritten without
-warning.
+Export as @LaTeX{} file with a @file{.tex} extension.  For @file{myfile.org},
+Org exports to @file{myfile.tex}, overwriting without warning.  @kbd{C-c C-e
+l l} Exports to @LaTeX{} file.
+
 @orgcmd{C-c C-e l L,org-latex-export-as-latex}
 Export to a temporary buffer.  Do not create a file.
 @orgcmd{C-c C-e l p,org-latex-export-to-pdf}
-Export as @LaTeX{} and then process to PDF.
+Export as @LaTeX{} file and convert it to PDF file.
 @item C-c C-e l o
-Export as @LaTeX{} and then process to PDF, then open the resulting PDF file.
+Export as @LaTeX{} file and convert it to PDF, then open the PDF using the 
default viewer.
address@hidden table
+
address@hidden org-latex-compiler
address@hidden org-latex-bibtex-compiler
address@hidden org-latex-default-packages-alist
+The @LaTeX{} export back-end can use any of these @LaTeX{} engines:
address@hidden, @samp{xelatex}, and @samp{lualatex}.  These engines compile
address@hidden files with different compilers, packages, and output options.  
The
address@hidden export back-end finds the compiler version to use from
address@hidden variable or the @code{#+LATEX_COMPILER} keyword in
+the Org file.  See the docstring for the
address@hidden for loading packages with certain
+compilers.  Also see @code{org-latex-bibtex-compiler} to set the bibliography
address@hidden does not allow setting different bibliography
+compilers for different files.  However, ``smart'' @LaTeX{} compilation
+systems, such as @samp{latexmk}, can select the correct bibliography
+compiler.}.
+
address@hidden @LaTeX{} specific export settings
address@hidden @LaTeX{} specific export settings
+
+The @LaTeX{} export back-end has several additional keywords for customizing
address@hidden output.  Setting these keywords works similar to the general 
options
+(@pxref{Export settings}).
+
address@hidden @samp
address@hidden DESCRIPTION
address@hidden #+DESCRIPTION (@LaTeX{})
+The document's description.  The description along with author name,
+keywords, and related file metadata are inserted in the output file by the
address@hidden package.  See @code{org-latex-hyperref-template} for
+customizing metadata items.  See @code{org-latex-title-command} for
+typesetting description into the document's front matter.  Use multiple
address@hidden lines for long descriptions.
+
address@hidden LATEX_CLASS
address@hidden #+LATEX_CLASS
address@hidden org-latex-default-class
address@hidden org-latex-classes
+This is @LaTeX{} document class, such as @code{article}, @code{report},
address@hidden, and so on, which contain predefined preamble and headline level
+mapping that the @LaTeX{} export back-end needs.  The back-end reads the
+default class name from the @code{org-latex-default-class} variable.  Org has
address@hidden as the default class.  A valid default class must be an
+element of @code{org-latex-classes}.
+
address@hidden LATEX_CLASS_OPTIONS
address@hidden #+LATEX_CLASS_OPTIONS
+Options the @LaTeX{} export back-end uses when calling the @LaTeX{} document
+class.
+
address@hidden LATEX_COMPILER
address@hidden #+LATEX_COMPILER
address@hidden org-latex-compiler
+The compiler, such as @samp{pdflatex}, @samp{xelatex}, @samp{lualatex}, for
+producing the PDF (@code{org-latex-compiler}).
+
address@hidden LATEX_HEADER
address@hidden #+LATEX_HEADER
address@hidden org-latex-classes
+Arbitrary lines to add to the document's preamble, before the @samp{hyperref}
+settings.  See @code{org-latex-classes} for adjusting the structure and order
+of the @LaTeX{} headers.
+
address@hidden LATEX_HEADER_EXTRA
address@hidden #+LATEX_HEADER_EXTRA
address@hidden org-latex-classes
+Arbitrary lines to add to the document's preamble, before the @samp{hyperref}
+settings.  See @code{org-latex-classes} for adjusting the structure and order
+of the @LaTeX{} headers.
+
address@hidden KEYWORDS
address@hidden #+KEYWORDS (@LaTeX{})
+The keywords for the document.  The description along with author name,
+keywords, and related file metadata are inserted in the output file by the
address@hidden package.  See @code{org-latex-hyperref-template} for
+customizing metadata items.  See @code{org-latex-title-command} for
+typesetting description into the document's front matter.  Use multiple
address@hidden lines if necessary.
+
address@hidden SUBTITLE
address@hidden #+SUBTITLE (@LaTeX{})
address@hidden org-latex-subtitle-separate
address@hidden org-latex-subtitle-format
+The document's subtitle.  It is typeset as per
address@hidden  If @code{org-latex-subtitle-separate} is
address@hidden, it is typed as part of the @samp{\title}-macro.  See
address@hidden for customizing metadata items.  See
address@hidden for typesetting description into the
+document's front matter.
 @end table
 
address@hidden Header and sectioning, Quoting @LaTeX{} code, @LaTeX{} export 
commands, @LaTeX{} and PDF export
address@hidden Header and sectioning structure
+The following sections have further details.
+
address@hidden @LaTeX{} header and sectioning
address@hidden @LaTeX{} header and sectioning structure
 @cindex @LaTeX{} class
 @cindex @LaTeX{} sectioning structure
 @cindex @LaTeX{} header
 @cindex header, for @LaTeX{} files
 @cindex sectioning structure, for @LaTeX{} export
 
-By default, the first three outline levels become headlines, defining a
-general document structure.  Additional levels are exported as @code{itemize}
-or @code{enumerate} lists.  The transition can also occur at a different
-level (@pxref{Export settings}).
+The @LaTeX{} export back-end converts the first three of Org's outline levels
+into @LaTeX{} headlines.  The remaining Org levels are exported as
address@hidden or @code{enumerate} lists.  To change this globally for the
+cut-off point between levels and lists, (@pxref{Export settings}).
 
-By default, the @LaTeX{} output uses the class @code{article}.
+By default, the @LaTeX{} export back-end uses the @code{article} class.
 
 @vindex org-latex-default-class
 @vindex org-latex-classes
 @vindex org-latex-default-packages-alist
 @vindex org-latex-packages-alist
-You can change this globally by setting a different value for
address@hidden or locally by adding an option like
address@hidden: myclass} in your file, or with
-a @code{EXPORT_LATEX_CLASS} property that applies when exporting a region
-containing only this (sub)tree.  The class must be listed in
address@hidden  This variable defines a header template for each
address@hidden which the values of
address@hidden and @code{org-latex-packages-alist}
-are spliced.}, and allows you to define the sectioning structure for each
-class.  You can also define your own classes there.
+To change the default class globally, edit @code{org-latex-default-class}.
+To change the default class locally in an Org file, add option lines
address@hidden: myclass}.  To change the default class for just a part
+of the Org file, set a sub-tree property, @code{EXPORT_LATEX_CLASS}.  The
+class name entered here must be valid member of @code{org-latex-classes}.
+This variable defines a header template for each class into which the
+exporter splices the values of @code{org-latex-default-packages-alist} and
address@hidden  Use the same three variables to define
+custom sectioning or custom classes.
 
 @cindex #+LATEX_CLASS
 @cindex #+LATEX_CLASS_OPTIONS
 @cindex property, EXPORT_LATEX_CLASS
 @cindex property, EXPORT_LATEX_CLASS_OPTIONS
-The @code{LATEX_CLASS_OPTIONS} keyword or @code{EXPORT_LATEX_CLASS_OPTIONS}
-property can specify the options for the @code{\documentclass} macro.  These
-options have to be provided, as expected by @LaTeX{}, within square brackets.
+The @LaTeX{} export back-end sends the @code{LATEX_CLASS_OPTIONS} keyword and
address@hidden property as options to the @LaTeX{}
address@hidden macro.  The options and the syntax for specifying them,
+including enclosing them in square brackets, follow @LaTeX{} conventions.
+
address@hidden
+#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside,twocolumn]
address@hidden example
 
 @cindex #+LATEX_HEADER
 @cindex #+LATEX_HEADER_EXTRA
-You can also use the @code{LATEX_HEADER} and
address@hidden@footnote{Unlike @code{LATEX_HEADER}, contents
-from @code{LATEX_HEADER_EXTRA} keywords will not be loaded when previewing
address@hidden snippets (@pxref{Previewing @LaTeX{} fragments}).} keywords in 
order
-to add lines to the header.  See the docstring of @code{org-latex-classes} for
-more information.
+The @LaTeX{} export back-end appends values from @code{LATEX_HEADER} and
address@hidden keywords to the @LaTeX{} header.  The docstring for
address@hidden explains in more detail.  Also note that @LaTeX{}
+export back-end does not append @code{LATEX_HEADER_EXTRA} to the header when
+previewing @LaTeX{} snippets (@pxref{Previewing @LaTeX{} fragments}).
 
-An example is shown below.
+A sample Org file with the above headers:
 
 @example
 #+LATEX_CLASS: article
@@ -11601,103 +12106,117 @@ An example is shown below.
 
 * Headline 1
   some text
+* Headline 2
+  some more text
 @end example
 
address@hidden Quoting @LaTeX{} code, @LaTeX{} specific attributes, Header and 
sectioning, @LaTeX{} and PDF export
address@hidden Quoting @LaTeX{} code
 @subsection Quoting @LaTeX{} code
 
-Embedded @LaTeX{} as described in @ref{Embedded @LaTeX{}}, will be correctly
-inserted into the @LaTeX{} file.  Furthermore, you can add special code that
-should only be present in @LaTeX{} export with the following constructs:
+The @LaTeX{} export back-end can insert any arbitrary @LaTeX{} code,
address@hidden @LaTeX{}}.  There are three ways to embed such code in the
+Org file and they all use different quoting syntax.
 
address@hidden #+LATEX
address@hidden #+BEGIN_LATEX
+Inserting in-line quoted with @ symbols:
address@hidden inline, in @LaTeX{} export
 @example
-Code within @@@@latex:some code@@@@ a paragraph.
-
-#+LATEX: Literal @LaTeX{} code for export
-
-#+BEGIN_LATEX
-All lines between these markers are exported literally
-#+END_LATEX
+Code embedded in-line @@@@latex:any arbitrary LaTeX code@@@@ in a paragraph.
 @end example
 
address@hidden @LaTeX{} specific attributes,  , Quoting @LaTeX{} code, @LaTeX{} 
and PDF export
address@hidden @LaTeX{} specific attributes
address@hidden #+ATTR_LATEX
+Inserting as one or more keyword lines in the Org file:
address@hidden #+LATEX
address@hidden
+#+LATEX: any arbitrary LaTeX code
address@hidden example
 
address@hidden understands attributes specified in an @code{ATTR_LATEX} line.  
They
-affect tables, images, plain lists, special blocks and source blocks.
+Inserting as an export block in the Org file, where the back-end exports any
+code between begin and end markers:
address@hidden #+BEGIN_EXPORT latex
address@hidden
+#+BEGIN_EXPORT latex
+any arbitrary LaTeX code
+#+END_EXPORT
address@hidden example
 
address@hidden Tables in @LaTeX{} export
address@hidden Tables in @LaTeX{} export
address@hidden Tables in @LaTeX{} export
 @cindex tables, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in tables
 
-For @LaTeX{} export of a table, you can specify a label and a caption
-(@pxref{Images and tables}).  You can also use attributes to control table
-layout and contents.  Valid @LaTeX{} attributes include:
+The @LaTeX{} export back-end can pass several @LaTeX{} attributes for table
+contents and layout.  Besides specifying label and caption (@pxref{Images and
+tables}), the other valid @LaTeX{} attributes include:
 
 @table @code
 @item :mode
 @vindex org-latex-default-table-mode
-Nature of table's contents.  It can be set to @code{table}, @code{math},
address@hidden or @code{verbatim}.  In particular, when in @code{math} or
address@hidden mode, every cell is exported as-is, horizontal rules are
-ignored and the table will be wrapped in a math environment.  Also,
-contiguous tables sharing the same math mode will be wrapped within the same
-environment.  Default mode is determined in
address@hidden
+The @LaTeX{} export back-end wraps the table differently depending on the
+mode for accurate rendering of math symbols.  Mode is either @code{table},
address@hidden, @code{inline-math} or @code{verbatim}.  For @code{math} or
address@hidden mode, @LaTeX{} export back-end wraps the table in a math
+environment, but every cell in it is exported as-is.  The @LaTeX{} export
+back-end determines the default mode from
address@hidden  For , The @LaTeX{} export back-end
+merges contiguous tables in the same mode into a single environment.
 @item :environment
 @vindex org-latex-default-table-environment
-Environment used for the table.  It can be set to any @LaTeX{} table
-environment, like @address@hidden adding the
address@hidden package to @code{org-latex-packages-alist}.},
address@hidden, @code{array}, @address@hidden adding the
address@hidden package to @code{org-latex-packages-alist}.},
address@hidden@enddots{} It defaults to
address@hidden value.
+Set the default @LaTeX{} table environment for the @LaTeX{} export back-end
+to use when exporting Org tables.  Common @LaTeX{} table environments are
+provided by these packages: @code{tabularx}, @code{longtable}, @code{array},
address@hidden, and @code{bmatrix}.  For packages, such as @code{tabularx} and
address@hidden, or any newer replacements, include them in the
address@hidden variable so the @LaTeX{} export back-end can
+insert the appropriate load package headers in the converted @LaTeX{} file.
+Look in the docstring for the @code{org-latex-packages-alist} variable for
+configuring these packages for @LaTeX{} snippet previews, if any.
 @item :caption
address@hidden keyword is the simplest way to set a caption for a table
-(@pxref{Images and tables}).  If you need more advanced commands for that
-task, you can use @code{:caption} attribute instead.  Its value should be raw
address@hidden code.  It has precedence over @code{#+CAPTION}.
+Use @code{#+CAPTION} keyword to set a simple caption for a table
+(@pxref{Images and tables}).  For custom captions, use @code{:caption}
+attribute, which accepts raw @LaTeX{} code.  @code{:caption} value overrides
address@hidden value.
 @item :float
 @itemx :placement
-Float environment for the table.  Possible values are @code{sidewaystable},
address@hidden, @code{t} and @code{nil}.  When unspecified, a table with
-a caption will have a @code{table} environment.  Moreover, @code{:placement}
-attribute can specify the positioning of the float.
+The table environments by default are not floats in @LaTeX{}.  To make them
+floating objects use @code{:float} with one of the following options:
address@hidden, @code{multicolumn}, @code{t}, and @code{nil}.  Note that
address@hidden has been deprecated since Org 8.3.  @LaTeX{} floats can
+also have additional layout @code{:placement} attributes.  These are the
+usual @code{[h t b p ! H]} permissions specified in square brackets.  Note
+that for @code{:float sideways} tables, the @LaTeX{} export back-end ignores
address@hidden:placement} attributes.
 @item :align
 @itemx :font
 @itemx :width
-Set, respectively, the alignment string of the table, its font size and its
-width.  They only apply on regular tables.
+The @LaTeX{} export back-end uses these attributes for regular tables to set
+their alignments, fonts, and widths.
 @item :spread
-Boolean specific to the @code{tabu} and @code{longtabu} environments, and
-only takes effect when used in conjunction with the @code{:width} attribute.
-When @code{:spread} is address@hidden, the table will be spread or shrunk by 
the
-value of @code{:width}.
+When @code{:spread} is address@hidden, the @LaTeX{} export back-end spreads
+or shrinks the table by the @code{:width} for @code{tabu} and @code{longtabu}
+environments.  @code{:spread} has no effect if @code{:width} is not set.
 @item :booktabs
 @itemx :center
 @itemx :rmlines
 @vindex org-latex-tables-booktabs
 @vindex org-latex-tables-centered
-They toggle, respectively, @code{booktabs} usage (assuming the package is
-properly loaded), table centering and removal of every horizontal rule but
-the first one (in a "table.el" table only).  In particular,
address@hidden (respectively @code{org-latex-tables-centered})
-activates the first (respectively second) attribute globally.
+All three commands are toggles.  @code{:booktabs} brings in modern
+typesetting enhancements to regular tables.  The @code{booktabs} package has
+to be loaded through @code{org-latex-packages-alist}.  @code{:center} is for
+centering the table.  @code{:rmlines} removes all but the very first
+horizontal line made of ASCII characters from "table.el" tables only.
 @item :math-prefix
 @itemx :math-suffix
 @itemx :math-arguments
-A string that will be inserted, respectively, before the table within the
-math environment, after the table within the math environment, and between
-the macro name and the contents of the table.  The @code{:math-arguments}
-attribute is used for matrix macros that require more than one argument
-(e.g., @code{qbordermatrix}).
+The @LaTeX{} export back-end inserts @code{:math-prefix} string value in a
+math environment before the table.  The @LaTeX{} export back-end inserts
address@hidden:math-suffix} string value in a math environment after the table. 
 The
address@hidden export back-end inserts @code{:math-arguments} string value 
between
+the macro name and the table's contents.  @code{:math-arguments} comes in use
+for matrix macros that require more than one argument, such as
address@hidden
 @end table
 
-Thus, attributes can be used in a wide array of situations, like writing
-a table that will span over multiple pages, or a matrix product:
address@hidden table attributes help formatting tables for a wide range of
+situations, such as matrix product or spanning multiple pages:
 
 @example
 #+ATTR_LATEX: :environment longtable :align l|address@hidden@}r|l
@@ -11712,8 +12231,8 @@ a table that will span over multiple pages, or a matrix 
product:
 | 3 | 4 |
 @end example
 
-In the example below, @LaTeX{} command
address@hidden@address@hidden@address@hidden will set the caption.
+Set the caption with the @LaTeX{} command
address@hidden@address@hidden@address@hidden:
 
 @example
 #+ATTR_LATEX: :caption address@hidden@address@hidden@}
@@ -11722,128 +12241,203 @@ In the example below, @LaTeX{} command
 @end example
 
 
address@hidden Images in @LaTeX{} export
address@hidden Images in @LaTeX{} export
address@hidden Images in @LaTeX{} export
 @cindex images, inline in @LaTeX{}
 @cindex inlining images in @LaTeX{}
address@hidden #+ATTR_LATEX, in images
 
-Images that are linked to without a description part in the link, like
address@hidden:img.jpg]]} or @samp{[[./img.jpg]]} will be inserted into the PDF
-output file resulting from @LaTeX{} processing.  Org will use an
address@hidden macro to insert the address@hidden the case of
-TikZ (@url{http://sourceforge.net/projects/pgf/}) images, it will become an
address@hidden macro wrapped within a @code{tikzpicture} environment.}.
+The @LaTeX{} export back-end processes image links in Org files that do not
+have descriptions, such as these links @samp{[[file:img.jpg]]} or
address@hidden/img.jpg]]}, as direct image insertions in the final PDF output.  
In
+the PDF, they are no longer links but actual images embedded on the page.
+The @LaTeX{} export back-end uses @code{\includegraphics} macro to insert the
+image.  But for address@hidden@url{http://sourceforge.net/projects/pgf/}}
+images, the back-end uses an @code{\input} macro wrapped within
+a @code{tikzpicture} environment.
 
-You can specify specify image width or height with, respectively,
address@hidden:width} and @code{:height} attributes.  It is also possible to 
add any
-other option with the @code{:options} attribute, as shown in the following
-example:
+For specifying image @code{:width}, @code{:height}, and other
address@hidden:options}, use this syntax:
 
 @example
 #+ATTR_LATEX: :width 5cm :options angle=90
 [[./img/sed-hr4049.pdf]]
 @end example
 
-If you need a specific command for the caption, use @code{:caption}
-attribute.  It will override standard @code{#+CAPTION} value, if any.
+For custom commands for captions, use the @code{:caption} attribute.  It will
+override the default @code{#+CAPTION} value:
 
 @example
 #+ATTR_LATEX: :caption address@hidden@address@hidden@}
 [[./img/sed-hr4049.pdf]]
 @end example
 
-If you have specified a caption as described in @ref{Images and tables}, the
-picture will be wrapped into a @code{figure} environment and thus become
-a floating element.  You can also ask Org to export an image as a float
-without specifying caption by setting the @code{:float} attribute.  You may
-also set it to:
+When captions follow the method as described in @ref{Images and tables}, the
address@hidden export back-end wraps the picture in a floating @code{figure}
+environment.  To float an image without specifying a caption, set the
address@hidden:float} attribute to one of the following:
 @itemize @minus
 @item
address@hidden: if you want to use the standard @samp{figure} environment.  It 
is
-used by default if you provide a caption to the image.
address@hidden: for a standard @samp{figure} environment; used by default 
whenever
+an image has a caption.
 @item
address@hidden: if you wish to include an image which spans multiple
-columns in a page.  This will export the image wrapped in a @code{figure*}
-environment.
address@hidden: to span the image across multiple columns of a page; the
+back-end wraps the image in a @code{figure*} environment.
address@hidden
address@hidden: for text to flow around the image on the right; the figure
+occupies the left half of the page.
 @item
address@hidden: if you would like to let text flow around the image.  It will
-make the figure occupy the left half of the page.
address@hidden: for a new page with the image sideways, rotated ninety
+degrees, in a @code{sidewaysfigure} environment; overrides @code{:placement}
+setting.
 @item
address@hidden: if you need to avoid any floating environment, even when
-a caption is provided.
address@hidden: to avoid a @code{:float} even if using a caption.
 @end itemize
 @noindent
-To modify the placement option of any floating environment, set the
address@hidden attribute.
+Use the @code{placement} attribute to modify a floating environment's 
placement.
 
 @example
-#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement 
@address@hidden@address@hidden
-[[./img/hst.png]]
+#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement
address@hidden@address@hidden@} [[./img/hst.png]]
 @end example
 
-If the @code{:comment-include} attribute is set to a address@hidden value,
-the @LaTeX{} @code{\includegraphics} macro will be commented out.
address@hidden org-latex-images-centered
address@hidden center image (@LaTeX{} export)
address@hidden image, centering (@LaTeX{} export)
+
+The @LaTeX{} export back-end centers all images by default.  Setting
address@hidden:center} attribute to @code{nil} disables centering.  To disable
+centering globally, set @code{org-latex-images-centered} to @code{t}.
+
+Set the @code{:comment-include} attribute to address@hidden value for the
address@hidden export back-end to comment out the @code{\includegraphics} macro.
 
address@hidden Plain lists in @LaTeX{} export
address@hidden Plain lists in @LaTeX{} export
address@hidden Plain lists in @LaTeX{} export
 @cindex plain lists, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in plain lists
+
+The @LaTeX{} export back-end accepts the @code{:environment} and
address@hidden:options} attributes for plain lists.  Both attributes work 
together
+for customizing lists, as shown in the examples:
+
address@hidden
+#+LATEX_HEADER: address@hidden@}
+Some ways to say "Hello":
+#+ATTR_LATEX: :environment itemize*
+#+ATTR_LATEX: :options address@hidden@}, address@hidden,@}, address@hidden, 
address@hidden
+- Hola
+- Bonjour
+- Guten Tag.
address@hidden example
 
-Plain lists accept two optional attributes: @code{:environment} and
address@hidden:options}.  The first one allows the use of a non-standard 
environment
-(e.g., @samp{inparaenum}).  The second one specifies additional arguments for
-that environment.
+Since @LaTeX{} supports only four levels of nesting for lists, use an
+external package, such as @samp{enumitem} in @LaTeX{}, for levels deeper than
+four:
 
 @example
-#+ATTR_LATEX: :environment compactitem :options [$\circ$]
-- you need ``paralist'' package to reproduce this example.
+#+LATEX_HEADER: address@hidden@}
+#+LATEX_HEADER: address@hidden@address@hidden@address@hidden@}
+#+LATEX_HEADER: address@hidden@}
+- One
+  - Two
+    - Three
+      - Four
+        - Five
 @end example
 
address@hidden Source blocks in @LaTeX{} export
address@hidden Source blocks in @LaTeX{} export
address@hidden Source blocks in @LaTeX{} export
 @cindex source blocks, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in source blocks
+
+The @LaTeX{} export back-end can make source code blocks into floating
+objects through the attributes @code{:float} and @code{:options}.  For
address@hidden:float}:
 
-In addition to syntax defined in @ref{Literal examples}, names and captions
-(@pxref{Images and tables}), source blocks also accept a @code{:float}
-attribute.  You may set it to:
 @itemize @minus
 @item
address@hidden: if you want to make the source block a float.  It is the default
-value when a caption is provided.
address@hidden: makes a source block float; by default floats any source block 
with
+a caption.
 @item
address@hidden: if you wish to include a source block which spans multiple
-columns in a page.
address@hidden: spans the source block across multiple columns of a page.
 @item
address@hidden: if you need to avoid any floating environment, even when a 
caption
-is provided.  It is useful for source code that may not fit in a single page.
address@hidden: avoids a @code{:float} even if using a caption; useful for
+source code blocks that may not fit on a page.
 @end itemize
 
 @example
 #+ATTR_LATEX: :float nil
 #+BEGIN_SRC emacs-lisp
-Code that may not fit in a single page.
+Lisp code that may not fit in a single page.
+#+END_SRC
address@hidden example
+
address@hidden org-latex-listings-options
address@hidden org-latex-minted-options
+The @LaTeX{} export back-end passes string values in @code{:options} to
address@hidden packages for customization of that specific source block.  In the
+example below, the @code{:options} are set for Minted.  Minted is a source
+code highlighting @LaTeX{}package with many configurable options.
+
address@hidden
+#+ATTR_LATEX: :options commentstyle=\bfseries
+#+BEGIN_SRC emacs-lisp
+  (defun Fib (n)
+    (if (< n 2) n (+ (Fib (- n 1)) (Fib (- n 2)))))
 #+END_SRC
 @end example
 
address@hidden Special blocks in @LaTeX{} export
+To apply similar configuration options for all source blocks in a file, use
+the @code{org-latex-listings-options} and @code{org-latex-minted-options}
+variables.
+
address@hidden Example blocks in @LaTeX{} export
address@hidden Example blocks in @LaTeX{} export
address@hidden example blocks, in @LaTeX{} export
address@hidden verbatim blocks, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in example blocks
+
+The @LaTeX{} export back-end wraps the contents of example blocks in a
address@hidden environment.  To change this behavior to use another
+environment globally, specify an appropriate export filter (@pxref{Advanced
+configuration}).  To change this behavior to use another environment for each
+block, use the @code{:environment} parameter to specify a custom environment.
+
address@hidden
+#+ATTR_LATEX: :environment myverbatim
+#+BEGIN_EXAMPLE
+This sentence is false.
+#+END_EXAMPLE
address@hidden example
+
address@hidden Special blocks in @LaTeX{} export
address@hidden Special blocks in @LaTeX{} export
 @cindex special blocks, in @LaTeX{} export
 @cindex abstract, in @LaTeX{} export
 @cindex proof, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in special blocks
+
 
-In @LaTeX{} back-end, special blocks become environments of the same name.
-Value of @code{:options} attribute will be appended as-is to that
-environment's opening string.  For example:
+For other special blocks in the Org file, the @LaTeX{} export back-end makes
+a special environment of the same name.  The back-end also takes
address@hidden:options}, if any, and appends as-is to that environment's opening
+string.  For example:
 
 @example
-#+BEGIN_ABSTRACT
+#+BEGIN_abstract
 We demonstrate how to solve the Syracuse problem.
-#+END_ABSTRACT
+#+END_abstract
 
 #+ATTR_LATEX: :options [Proof of important theorem]
-#+BEGIN_PROOF
+#+BEGIN_proof
 ...
 Therefore, any even number greater than 2 is the sum of two primes.
-#+END_PROOF
+#+END_proof
 @end example
 
 @noindent
-becomes
+exports to
 
 @example
 address@hidden@}
@@ -11862,43 +12456,43 @@ example:
 
 @example
 #+ATTR_LATEX: :caption address@hidden@}
-#+BEGIN_PROOF
+#+BEGIN_proof
 ...
-#+END_PROOF
+#+END_proof
 @end example
 
address@hidden Horizontal rules
address@hidden Horizontal rules in @LaTeX{} export
address@hidden Horizontal rules in @LaTeX{} export
 @cindex horizontal rules, in @LaTeX{} export
address@hidden #+ATTR_LATEX, in horizontal rules
 
-Width and thickness of a given horizontal rule can be controlled with,
-respectively, @code{:width} and @code{:thickness} attributes:
+The @LaTeX{} export back-end converts horizontal rules by the specified
address@hidden:width} and @code{:thickness} attributes.  For example:
 
 @example
 #+ATTR_LATEX: :width .6\textwidth :thickness 0.8pt
 -----
 @end example
 
address@hidden Markdown export, OpenDocument Text export, @LaTeX{} and PDF 
export, Exporting
address@hidden Markdown export
 @section Markdown export
 @cindex Markdown export
 
address@hidden export back-end generates Markdown address@hidden flavor,
-as defined at @url{http://daringfireball.net/projects/markdown/}.} for an Org
-mode buffer.
+The Markdown export back-end, @code{md}, converts an Org file to a Markdown
+format, as defined at @url{http://daringfireball.net/projects/markdown/}.
 
-It is built over HTML back-end: any construct not supported by Markdown
-syntax (e.g., tables) will be controlled and translated by @code{html}
-back-end (@pxref{HTML export}).
+Since @code{md} is built on top of the HTML back-end, any Org constructs not
+supported by Markdown, such as tables, the underlying @code{html} back-end
+(@pxref{HTML export}) converts them.
 
 @subheading Markdown export commands
 
 @table @kbd
 @orgcmd{C-c C-e m m,org-md-export-to-markdown}
-Export as a text file written in Markdown syntax.  For an Org file,
address@hidden, the resulting file will be @file{myfile.md}.  The file
-will be overwritten without warning.
+Export to a text file with Markdown syntax.  For @file{myfile.org}, Org
+exports to @file{myfile.md}, overwritten without warning.
 @orgcmd{C-c C-e m M,org-md-export-as-markdown}
-Export to a temporary buffer.  Do not create a file.
+Export to a temporary buffer.  Does not create a file.
 @item C-c C-e m o
 Export as a text file with Markdown syntax, then open it.
 @end table
@@ -11906,54 +12500,52 @@ Export as a text file with Markdown syntax, then open 
it.
 @subheading Header and sectioning structure
 
 @vindex org-md-headline-style
-Markdown export can generate both @code{atx} and @code{setext} types for
-headlines, according to @code{org-md-headline-style}.  The former introduces
-a hard limit of two levels, whereas the latter pushes it to six.  Headlines
-below that limit are exported as lists.  You can also set a soft limit before
-that one (@pxref{Export settings}).
+Based on @code{org-md-headline-style}, markdown export can generate headlines
+of both @code{atx} and @code{setext} types.  @code{atx} limits headline
+levels to two.  @code{setext} limits headline levels to six.  Beyond these
+limits, the export back-end converts headlines to lists.  To set a limit to a
+level before the absolute limit (@pxref{Export settings}).
 
 @c begin opendocument
 
address@hidden OpenDocument Text export, Org export, Markdown export, Exporting
address@hidden OpenDocument Text export
 @section OpenDocument Text export
 @cindex ODT
 @cindex OpenDocument
 @cindex export, OpenDocument
 @cindex LibreOffice
 
-Org address@hidden 7.8 or later} supports export to OpenDocument Text
-(ODT) format.  Documents created by this exporter use the
address@hidden
+The ODT export back-end handles creating of OpenDocument Text (ODT) format
+files.  The format complies with @cite{OpenDocument-v1.2
 
address@hidden@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html,
 Open Document Format for Office Applications (OpenDocument) Version 1.2}} and
-are compatible with LibreOffice 3.4.
+is compatible with LibreOffice 3.4.
 
 @menu
-* Pre-requisites for ODT export::  What packages ODT exporter relies on
-* ODT export commands::         How to invoke ODT export
-* Extending ODT export::        How to produce @samp{doc}, @samp{pdf} files
-* Applying custom styles::      How to apply custom styles to the output
-* Links in ODT export::         How links will be interpreted and formatted
-* Tables in ODT export::        How Tables are exported
-* Images in ODT export::        How to insert images
-* Math formatting in ODT export::  How @LaTeX{} fragments are formatted
-* Labels and captions in ODT export::  How captions are rendered
-* Literal examples in ODT export::  How source and example blocks are formatted
-* Advanced topics in ODT export::  Read this if you are a power user
+* Pre-requisites for ODT export::  Required packages.
+* ODT export commands::         Invoking export.
+* ODT specific export settings::  Configuration options.
+* Extending ODT export::        Producing @file{.doc}, @file{.pdf} files.
+* Applying custom styles::      Styling the output.
+* Links in ODT export::         Handling and formatting links.
+* Tables in ODT export::        Org table conversions.
+* Images in ODT export::        Inserting images.
+* Math formatting in ODT export::  Formatting @LaTeX{} fragments.
+* Labels and captions in ODT export::  Rendering objects.
+* Literal examples in ODT export::  For source code and example blocks.
+* Advanced topics in ODT export::  For power users.
 @end menu
 
address@hidden Pre-requisites for ODT export, ODT export commands, OpenDocument 
Text export, OpenDocument Text export
address@hidden Pre-requisites for ODT export
 @subsection Pre-requisites for ODT export
 @cindex zip
-The ODT exporter relies on the @file{zip} program to create the final
-output.  Check the availability of this program before proceeding further.
+The ODT export back-end relies on the @file{zip} program to create the final
+compressed ODT output.  Check if @file{zip} is locally available and
+executable.  Without @file{zip}, export cannot finish.
 
address@hidden ODT export commands, Extending ODT export, Pre-requisites for 
ODT export, OpenDocument Text export
address@hidden ODT export commands
 @subsection ODT export commands
-
address@hidden Exporting to ODT
 @anchor{x-export-to-odt}
-
 @cindex region, active
 @cindex active region
 @cindex transient-mark-mode
@@ -11964,94 +12556,121 @@ output.  Check the availability of this program 
before proceeding further.
 Export as OpenDocument Text file.
 
 @vindex org-odt-preferred-output-format
-If @code{org-odt-preferred-output-format} is specified, automatically convert
-the exported file to that format.  @xref{x-export-to-other-formats, ,
-Automatically exporting to other formats}.
-
-For an Org file @file{myfile.org}, the ODT file will be
address@hidden  The file will be overwritten without warning.  If there
-is an active region,@footnote{This requires @code{transient-mark-mode} to be
-turned on} only the region will be exported.  If the selected region is a
-single tree,@footnote{To select the current subtree, use @kbd{C-c @@}} the
-tree head will become the document title.  If the tree head entry has, or
-inherits, an @code{EXPORT_FILE_NAME} property, that name will be used for the
-export.
+If @code{org-odt-preferred-output-format} is specified, the ODT export
+back-end automatically converts the exported file to that format.
address@hidden, , Automatically exporting to other formats}.
+
+For @file{myfile.org}, Org exports to @file{myfile.odt}, overwriting without
+warning.  The ODT export back-end exports a region only if a region was
+active.  Note for exporting active regions, the @code{transient-mark-mode}
+has to be turned on.
+
+If the selected region is a single tree, the ODT export back-end makes the
+tree head the document title.  Incidentally, @kbd{C-c @@} selects the current
+sub-tree.  If the tree head entry has, or inherits, an
address@hidden property, the ODT export back-end uses that for file
+name.
 
 @kbd{C-c C-e o O}
-Export as an OpenDocument Text file and open the resulting file.
+Export to an OpenDocument Text file format and open it.
 
 @vindex org-odt-preferred-output-format
-If @code{org-odt-preferred-output-format} is specified, open the converted
+When @code{org-odt-preferred-output-format} is specified, open the converted
 file instead.  @xref{x-export-to-other-formats, , Automatically exporting to
 other formats}.
 @end table
 
address@hidden Extending ODT export, Applying custom styles, ODT export 
commands, OpenDocument Text export
address@hidden ODT specific export settings
address@hidden ODT specific export settings
+The ODT export back-end has several additional keywords for customizing ODT
+output.  Setting these keywords works similar to the general options
+(@pxref{Export settings}).
+
address@hidden @samp
address@hidden DESCRIPTION
address@hidden #+DESCRIPTION (ODT)
+This is the document's description, which the ODT export back-end inserts as
+document metadata.  For long descriptions, use multiple @code{#+DESCRIPTION}
+lines.
+
address@hidden KEYWORDS
address@hidden #+KEYWORDS (ODT)
+The keywords for the document.  The ODT export back-end inserts the
+description along with author name, keywords, and related file metadata as
+metadata in the output file.  Use multiple @code{#+KEYWORDS} lines if
+necessary.
+
address@hidden ODT_STYLES_FILE
address@hidden ODT_STYLES_FILE
address@hidden org-odt-styles-file
+The ODT export back-end uses the @code{org-odt-styles-file} by default.  See
address@hidden custom styles} for details.
+
address@hidden SUBTITLE
address@hidden SUBTITLE (ODT)
+The document subtitle.
address@hidden table
+
address@hidden Extending ODT export
 @subsection Extending ODT export
 
-The ODT exporter can interface with a variety of document
-converters and supports popular converters out of the box.  As a result, you
-can use it to export to formats like @samp{doc} or convert a document from
-one format (say @samp{csv}) to another format (say @samp{ods} or @samp{xls}).
+The ODT export back-end can produce documents in other formats besides ODT
+using a specialized ODT converter process.  Its common interface works with
+popular converters to produce formats such as @samp{doc}, or convert a
+document from one format, say @samp{csv}, to another format, say @samp{xls}.
 
 @cindex @file{unoconv}
 @cindex LibreOffice
-If you have a working installation of LibreOffice, a document converter is
-pre-configured for you and you can use it right away.  If you would like to
-use @file{unoconv} as your preferred converter, customize the variable
address@hidden to point to @code{unoconv}.  You can
-also use your own favorite converter or tweak the default settings of the
address@hidden and @samp{unoconv} converters.  @xref{Configuring a
-document converter}.
-
address@hidden Automatically exporting to other formats
+
+Customize @code{org-odt-convert-process} variable to point to @code{unoconv},
+which is the ODT's preferred converter.  Working installations of LibreOffice
+would already have @code{unoconv} installed.  Alternatively, other converters
+may be substituted here.  @xref{Configuring a document converter}.
+
address@hidden Automatically exporting to other formats
 @anchor{x-export-to-other-formats}
 
 @vindex org-odt-preferred-output-format
-Very often, you will find yourself exporting to ODT format, only to
-immediately save the exported document to other formats like @samp{doc},
address@hidden, @samp{rtf}, @samp{pdf} etc.  In such cases, you can specify your
-preferred output format by customizing the variable
address@hidden  This way, the export commands
-(@pxref{x-export-to-odt,,Exporting to ODT}) can be extended to export to a
-format that is of immediate interest to you.
-
address@hidden Converting between document formats
+If ODT format is just an intermediate step to get to other formats, such as
address@hidden, @samp{docx}, @samp{rtf}, or @samp{pdf}, etc., then extend the 
ODT
+export back-end to directly produce that format.  Specify the final format in
+the @code{org-odt-preferred-output-format} variable.  This is one way to
+extend (@pxref{x-export-to-odt,,Exporting to ODT}).
+
address@hidden Converting between document formats
 @anchor{x-convert-to-other-formats}
 
-There are many document converters in the wild which support conversion to
-and from various file formats, including, but not limited to the
-ODT format.  LibreOffice converter, mentioned above, is one such
-converter.  Once a converter is configured, you can interact with it using
-the following command.
+The Org export back-end is made to be inter-operable with a wide range of text
+document format converters.  Newer generation converters, such as LibreOffice
+and Pandoc, can handle hundreds of formats at once.  Org provides a
+consistent interaction with whatever converter is installed.  Here are some
+generic commands:
 
 @vindex org-odt-convert
 @table @kbd
 
 @item M-x org-odt-convert RET
 Convert an existing document from one format to another.  With a prefix
-argument, also open the newly produced file.
+argument, opens the newly produced file.
 @end table
 
address@hidden Applying custom styles, Links in ODT export, Extending ODT 
export, OpenDocument Text export
address@hidden Applying custom styles
 @subsection Applying custom styles
 @cindex styles, custom
 @cindex template, custom
 
-The ODT exporter ships with a set of OpenDocument styles
-(@pxref{Working with OpenDocument style files}) that ensure a well-formatted
-output.  These factory styles, however, may not cater to your specific
-tastes.  To customize the output, you can either modify the above styles
-files directly, or generate the required styles using an application like
-LibreOffice.  The latter method is suitable for expert and non-expert
-users alike, and is described here.
+The ODT export back-end comes with many OpenDocument styles (@pxref{Working
+with OpenDocument style files}).  To expand or further customize these
+built-in style sheets, either edit the style sheets directly or generate them
+using an application such as LibreOffice.  The example here shows creating a
+style using LibreOffice.
 
address@hidden Applying custom styles: the easy way
address@hidden Applying custom styles: the easy way
 
 @enumerate
 @item
-Create a sample @file{example.org} file with the below settings and export it
-to ODT format.
+Create a sample @file{example.org} file with settings as shown below, and
+export it to ODT format.
 
 @example
 #+OPTIONS: H:10 num:t
@@ -12059,9 +12678,9 @@ to ODT format.
 
 @item
 Open the above @file{example.odt} using LibreOffice.  Use the @file{Stylist}
-to locate the target styles---these typically have the @samp{Org} prefix---and
-modify those to your taste.  Save the modified file either as an
-OpenDocument Text (@file{.odt}) or OpenDocument Template (@file{.ott}) file.
+to locate the target styles, which typically have the @samp{Org} prefix.
+Open one, modify, and save as either OpenDocument Text (@file{.odt}) or
+OpenDocument Template (@file{.ott}) file.
 
 @item
 @cindex #+ODT_STYLES_FILE
@@ -12070,8 +12689,8 @@ Customize the variable @code{org-odt-styles-file} and 
point it to the
 newly created file.  For additional configuration options
 @pxref{x-overriding-factory-styles,,Overriding factory styles}.
 
-If you would like to choose a style on a per-file basis, you can use the
address@hidden option.  A typical setting will look like
+To apply and ODT style to a particular file, use the @code{#+ODT_STYLES_FILE}
+option as shown in the example below:
 
 @example
 #+ODT_STYLES_FILE: "/path/to/example.ott"
@@ -12085,51 +12704,48 @@ or
 
 @end enumerate
 
address@hidden Using third-party styles and templates
address@hidden Using third-party styles and templates
 
-You can use third-party styles and templates for customizing your output.
-This will produce the desired output only if the template provides all
-style names that the @samp{ODT} exporter relies on.  Unless this condition is
-met, the output is going to be less than satisfactory.  So it is highly
-recommended that you only work with templates that are directly derived from
-the factory settings.
+The ODT export back-end relies on many templates and style names.  Using
+third-party styles and templates can lead to mismatches.  Templates derived
+from built in ODT templates and styles seem to have fewer problems.
 
address@hidden Links in ODT export, Tables in ODT export, Applying custom 
styles, OpenDocument Text export
address@hidden Links in ODT export
 @subsection Links in ODT export
 @cindex links, in ODT export
 
-ODT exporter creates native cross-references for internal links.  It creates
-Internet-style links for all other links.
+ODT export back-end creates native cross-references for internal links and
+Internet-style links for all other link types.
 
-A link with no description and destined to a regular (un-itemized) outline
+A link with no description and pointing to a regular---un-itemized---outline
 heading is replaced with a cross-reference and section number of the heading.
 
 A @address@hidden@}}-style reference to an image, table etc.@: is replaced
 with a cross-reference and sequence number of the labeled entity.
 @xref{Labels and captions in ODT export}.
 
address@hidden Tables in ODT export, Images in ODT export, Links in ODT export, 
OpenDocument Text export
address@hidden Tables in ODT export
 @subsection Tables in ODT export
 @cindex tables, in ODT export
 
-Export of native Org mode tables (@pxref{Tables}) and simple @file{table.el}
-tables is supported.  However, export of complex @file{table.el} 
tables---tables
-that have column or row spans---is not supported.  Such tables are
-stripped from the exported document.
+The ODT export back-end handles native Org mode tables (@pxref{Tables}) and
+simple @file{table.el} tables.  Complex @file{table.el} tables having column
+or row spans are not supported.  Such tables are stripped from the exported
+document.
+
+By default, the ODT export back-end exports a table with top and bottom
+frames and with ruled lines separating row and column groups (@pxref{Column
+groups}).  All tables are typeset to occupy the same width.  The ODT export
+back-end honors any table alignments and relative widths for columns
+(@pxref{Column width and alignment}).
 
-By default, a table is exported with top and bottom frames and with rules
-separating row and column groups (@pxref{Column groups}).  Furthermore, all
-tables are typeset to occupy the same width.  If the table specifies
-alignment and relative width for its columns (@pxref{Column width and
-alignment}) then these are honored on address@hidden column widths are
-interpreted as weighted ratios with the default weight being 1}
+Note that the ODT export back-end interprets column widths as weighted
+ratios, the default weight being 1.
 
 @cindex #+ATTR_ODT
-You can control the width of the table by specifying @code{:rel-width}
-property using an @code{#+ATTR_ODT} line.
 
-For example, consider the following table which makes use of all the rules
-mentioned above.
+Specifying @code{:rel-width} property on an @code{#+ATTR_ODT} line controls
+the width of the table.  For example:
 
 @example
 #+ATTR_ODT: :rel-width 50
@@ -12144,25 +12760,25 @@ mentioned above.
 | Sum           |    16 |   123 |  2560 |  2699 |
 @end example
 
-On export, the table will occupy 50% of text area.  The columns will be sized
-(roughly) in the ratio of 13:5:5:5:6.  The first column will be left-aligned
-and rest of the columns will be right-aligned.  There will be vertical rules
-after separating the header and last columns from other columns.  There will
-be horizontal rules separating the header and last rows from other rows.
+On export, the above table takes 50% of text width area.  The exporter sizes
+the columns in the ratio: 13:5:5:5:6.  The first column is left-aligned and
+rest of the columns, right-aligned.  Vertical rules separate the header and
+the last column.  Horizontal rules separate the header and the last row.
 
-If you are not satisfied with the above formatting options, you can create
-custom table styles and associate them with a table using the
address@hidden line.  @xref{Customizing tables in ODT export}.
+For even more customization, create custom table styles and associate them
+with a table using the @code{#+ATTR_ODT} line.  @xref{Customizing tables in
+ODT export}.
 
address@hidden Images in ODT export, Math formatting in ODT export, Tables in 
ODT export, OpenDocument Text export
address@hidden Images in ODT export
 @subsection Images in ODT export
 @cindex images, embedding in ODT
 @cindex embedding images in ODT
 
 @subsubheading Embedding images
-You can embed images within the exported document by providing a link to the
-desired image file with no link description.  For example, to embed
address@hidden do either of the following:
+The ODT export back-end processes image links in Org files that do not have
+descriptions, such as these links @samp{[[file:img.jpg]]} or
address@hidden/img.jpg]]}, as direct image insertions in the final output.  
Either
+of these examples works:
 
 @example
 [[file:img.png]]
@@ -12173,10 +12789,9 @@ desired image file with no link description.  For 
example, to embed
 @end example
 
 @subsubheading Embedding clickable images
-You can create clickable images by providing a link whose description is a
-link to an image file.  For example, to embed a image
address@hidden which when clicked jumps to
address@hidden://Orgmode.org} website, do the following
+For clickable images, provide a link whose description is another link to an
+image file.  For example, to embed a image @file{org-mode-unicorn.png} which
+when clicked jumps to @uref{http://Orgmode.org} website, do the following
 
 @example
 [[http://orgmode.org][./org-mode-unicorn.png]]
@@ -12185,25 +12800,22 @@ link to an image file.  For example, to embed a image
 @subsubheading Sizing and scaling of embedded images
 
 @cindex #+ATTR_ODT
-You can control the size and scale of the embedded images using the
address@hidden attribute.
+Control the size and scale of the embedded images with the @code{#+ATTR_ODT}
+attribute.
 
 @cindex identify, ImageMagick
 @vindex org-odt-pixels-per-inch
-The exporter specifies the desired size of the image in the final document in
-units of centimeters.  In order to scale the embedded images, the exporter
-queries for pixel dimensions of the images using one of a) ImageMagick's
address@hidden program or b) Emacs @code{create-image} and @code{image-size}
address@hidden of @file{ImageMagick} is only desirable.  However, if you
-routinely produce documents that have large images or you export your Org
-files that has images using a Emacs batch script, then the use of
address@hidden is mandatory.}. The pixel dimensions are subsequently
-converted in to units of centimeters using
address@hidden  The default value of this variable is
-set to @code{display-pixels-per-inch}.  You can tweak this variable to
-achieve the best results.
-
-The examples below illustrate the various possibilities.
+The ODT export back-end starts with establishing the size of the image in the
+final document.  The dimensions of this size is measured in centimeters.  The
+back-end then queries the image file for its dimensions measured in pixels.
+For this measurement, the back-end relies on ImageMagick's @file{identify}
+program or Emacs @code{create-image} and @code{image-size} API.  ImageMagick
+is the preferred choice for large file sizes or frequent batch operations.
+The back-end then converts the pixel dimensions using
address@hidden into the familiar 72 dpi or 96 dpi.  The
+default value for this is in @code{display-pixels-per-inch}, which can be
+tweaked for better results based on the capabilities of the output device.
+Here are some common image scaling operations:
 
 @table @asis
 @item Explicitly size the image
@@ -12244,38 +12856,37 @@ height:width ratio, do the following
 @subsubheading Anchoring of images
 
 @cindex #+ATTR_ODT
-You can control the manner in which an image is anchored by setting the
address@hidden:anchor} property of it's @code{#+ATTR_ODT} line.  You can 
specify one
-of the following three values for the @code{:anchor} property:
address@hidden"as-char"}, @samp{"paragraph"} and @samp{"page"}.
+The ODT export back-end can anchor images to @samp{"as-char"},
address@hidden"paragraph"}, or @samp{"page"}.  Set the preferred anchor using 
the
address@hidden:anchor} property of the @code{#+ATTR_ODT} line.
 
-To create an image that is anchored to a page, do the following:
+To create an image that is anchored to a page:
 @example
 #+ATTR_ODT: :anchor "page"
 [[./img.png]]
 @end example
 
address@hidden Math formatting in ODT export, Labels and captions in ODT 
export, Images in ODT export, OpenDocument Text export
address@hidden Math formatting in ODT export
 @subsection Math formatting in ODT export
 
-The ODT exporter has special support for handling math.
+The ODT export back-end has special support built-in for handling math.
 
 @menu
-* Working with @LaTeX{} math snippets::  How to embed @LaTeX{} math fragments
-* Working with MathML or OpenDocument formula files::  How to embed equations 
in native format
+* Working with @LaTeX{} math snippets::  Embedding in @LaTeX{} format.
+* Working with MathML or OpenDocument formula files::  Embedding in native 
format.
 @end menu
 
address@hidden Working with @LaTeX{} math snippets, Working with MathML or 
OpenDocument formula files, Math formatting in ODT export, Math formatting in 
ODT export
address@hidden Working with @LaTeX{} math snippets
address@hidden Working with @LaTeX{} math snippets
address@hidden Working with @LaTeX{} math snippets
 
address@hidden math snippets (@address@hidden fragments}) can be embedded in 
the ODT
address@hidden math snippets (@address@hidden fragments}) can be embedded in an 
ODT
 document in one of the following ways:
 
 @cindex MathML
 @enumerate
 @item MathML
 
-This option is activated on a per-file basis with
+Add this line to the Org file.  This option is activated on a per-file basis.
 
 @example
 #+OPTIONS: LaTeX:t
@@ -12289,13 +12900,13 @@ the exported document.
 @vindex org-latex-to-mathml-convert-command
 @vindex org-latex-to-mathml-jar-file
 
-You can specify the @LaTeX{}-to-MathML converter by customizing the variables
+To specify the @LaTeX{}-to-MathML converter, customize the variables
 @code{org-latex-to-mathml-convert-command} and
 @code{org-latex-to-mathml-jar-file}.
 
-If you prefer to use @address@hidden
address@hidden://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}} as 
your
-converter, you can configure the above variables as shown below.
+To use address@hidden
address@hidden://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}.} as 
the
+preferred converter, configure the above variables as
 
 @lisp
 (setq org-latex-to-mathml-convert-command
@@ -12303,9 +12914,14 @@ converter, you can configure the above variables as 
shown below.
       org-latex-to-mathml-jar-file
       "/path/to/mathtoweb.jar")
 @end lisp
+To use @address@hidden @uref{http://dlmf.nist.gov/LaTeXML/}.} use
address@hidden
+(setq org-latex-to-mathml-convert-command
+      "latexmlmath \"%i\" --presentationmathml=%o")
address@hidden lisp
 
-You can use the following commands to quickly verify the reliability of
-the @LaTeX{}-to-MathML converter.
+To quickly verify the reliability of the @LaTeX{}-to-MathML converter, use
+the following commands:
 
 @table @kbd
 @item M-x org-odt-export-as-odf RET
@@ -12317,34 +12933,39 @@ and open the formula file with the system-registered 
application.
 @end table
 
 @cindex dvipng
address@hidden dvisvgm
 @cindex imagemagick
 @item PNG images
 
-This option is activated on a per-file basis with
+Add this line to the Org file.  This option is activated on a per-file basis.
 
 @example
 #+OPTIONS: tex:dvipng
 @end example
 
address@hidden
+#+OPTIONS: tex:dvisvgm
address@hidden example
+
 or:
 
 @example
 #+OPTIONS: tex:imagemagick
 @end example
 
-With this option, @LaTeX{} fragments are processed into PNG images and the
-resulting images are embedded in the exported document.  This method requires
-that the @file{dvipng} program or @file{imagemagick} suite be available on
-your system.
+Under this option, @LaTeX{} fragments are processed into PNG or SVG images
+and the resulting images are embedded in the exported document.  This method
+requires @file{dvipng} program, @file{dvisvgm} or @file{imagemagick}
+programs.
 @end enumerate
 
address@hidden Working with MathML or OpenDocument formula files,  , Working 
with @LaTeX{} math snippets, Math formatting in ODT export
address@hidden Working with MathML or OpenDocument formula files
address@hidden Working with MathML or OpenDocument formula files
address@hidden Working with MathML or OpenDocument formula files
 
-For various reasons, you may find embedding @LaTeX{} math snippets in an
-ODT document less than reliable.  In that case, you can embed a
-math equation by linking to its MathML (@file{.mml}) source or its
-OpenDocument formula (@file{.odf}) file as shown below:
+When embedding @LaTeX{} math snippets in ODT documents is not reliable, there
+is one more option to try.  Embed an equation by linking to its MathML
+(@file{.mml}) source or its OpenDocument formula (@file{.odf}) file as shown
+below:
 
 @example
 [[./equation.mml]]
@@ -12356,19 +12977,14 @@ or
 [[./equation.odf]]
 @end example
 
address@hidden Labels and captions in ODT export, Literal examples in ODT 
export, Math formatting in ODT export, OpenDocument Text export
address@hidden Labels and captions in ODT export
 @subsection Labels and captions in ODT export
 
-You can label and caption various category of objects---an inline image, a
-table, a @LaTeX{} fragment or a Math formula---using @code{#+LABEL} and
address@hidden lines.  @xref{Images and tables}.  ODT exporter enumerates
-each labeled or captioned object of a given category separately.  As a
-result, each such object is assigned a sequence number based on order of it's
-appearance in the Org file.
-
-In the exported document, a user-provided caption is augmented with the
-category and sequence number.  Consider the following inline image in an Org
-file.
+ODT format handles labeling and captioning of objects based on their
+types.  Inline images, tables, @LaTeX{} fragments, and Math formulas are
+numbered and captioned separately.  Each object also gets a unique sequence
+number based on its order of first appearance in the Org file.  Each category
+has its own sequence.  A caption is just a label applied to these objects.
 
 @example
 #+CAPTION: Bell curve
@@ -12376,94 +12992,86 @@ file.
 [[./img/a.png]]
 @end example
 
-It could be rendered as shown below in the exported document.
+When rendered, it may show as follows in the exported document:
 
 @example
 Figure 2: Bell curve
 @end example
 
 @vindex org-odt-category-map-alist
-You can modify the category component of the caption by customizing the
-option @code{org-odt-category-map-alist}.  For example, to tag all embedded
-images with the string @samp{Illustration} (instead of the default
address@hidden) use the following setting:
+To modify the category component of the caption, customize the option
address@hidden  For example, to tag embedded images with
+the string @samp{Illustration} instead of the default string @samp{Figure},
+use the following setting:
 
 @lisp
 (setq org-odt-category-map-alist
-      (("__Figure__" "Illustration" "value" "Figure" 
org-odt--enumerable-image-p)))
+      '(("__Figure__" "Illustration" "value" "Figure" 
org-odt--enumerable-image-p)))
 @end lisp
 
-With this, previous image will be captioned as below in the exported
-document.
+With the above modification, the previous example changes to:
 
 @example
 Illustration 2: Bell curve
 @end example
 
address@hidden Literal examples in ODT export, Advanced topics in ODT export, 
Labels and captions in ODT export, OpenDocument Text export
address@hidden Literal examples in ODT export
 @subsection Literal examples in ODT export
 
-Export of literal examples (@pxref{Literal examples}) with full fontification
-is supported.  Internally, the exporter relies on @file{htmlfontify.el} to
-generate all style definitions needed for a fancy address@hidden
address@hidden library must at least be at Emacs 24.1 levels for
-fontification to be turned on.}  The auto-generated styles have @samp{OrgSrc}
-as prefix and inherit their color from the faces used by Emacs
address@hidden library for the source language.
+The ODT export back-end supports literal examples (@pxref{Literal examples})
+with full fontification.  Internally, the ODT export back-end relies on
address@hidden to generate the style definitions needed for fancy
+listings.  The auto-generated styles get @samp{OrgSrc} prefix and inherit
+colors from the faces used by Emacs @code{font-lock} library for that source
+language.
 
 @vindex org-odt-fontify-srcblocks
-If you prefer to use your own custom styles for fontification, you can do
-so by customizing the option
address@hidden
+For custom fontification styles, customize the
address@hidden option.
 
 @vindex org-odt-create-custom-styles-for-srcblocks
-You can turn off fontification of literal examples by customizing the
-option @code{org-odt-fontify-srcblocks}.
+To turn off fontification of literal examples, customize the
address@hidden option.
 
address@hidden Advanced topics in ODT export,  , Literal examples in ODT 
export, OpenDocument Text export
address@hidden Advanced topics in ODT export
 @subsection Advanced topics in ODT export
 
-If you rely heavily on ODT export, you may want to exploit the full
-set of features that the exporter offers.  This section describes features
-that would be of interest to power users.
+The ODT export back-end has extensive features useful for power users and
+frequent uses of ODT formats.
 
 @menu
-* Configuring a document converter::  How to register a document converter
-* Working with OpenDocument style files::  Explore the internals
-* Creating one-off styles::     How to produce custom highlighting etc
-* Customizing tables in ODT export::  How to define and use Table templates
-* Validating OpenDocument XML::  How to debug corrupt OpenDocument files
+* Configuring a document converter::  Registering a document converter.
+* Working with OpenDocument style files::  Exploring internals.
+* Creating one-off styles::     Customizing styles, highlighting.
+* Customizing tables in ODT export::  Defining table templates.
+* Validating OpenDocument XML::  Debugging corrupted OpenDocument files.
 @end menu
 
address@hidden Configuring a document converter, Working with OpenDocument 
style files, Advanced topics in ODT export, Advanced topics in ODT export
address@hidden Configuring a document converter
address@hidden Configuring a document converter
address@hidden Configuring a document converter
 @cindex convert
 @cindex doc, docx, rtf
 @cindex converter
 
-The ODT exporter can work with popular converters with little or no
-extra configuration from your side. @xref{Extending ODT export}.
-If you are using a converter that is not supported by default or if you would
-like to tweak the default converter settings, proceed as below.
+The ODT export back-end works with popular converters with little or no extra
+configuration.  @xref{Extending ODT export}.  The following is for unsupported
+converters or tweaking existing defaults.
 
 @enumerate
 @item Register the converter
 
 @vindex org-odt-convert-processes
-Name your converter and add it to the list of known converters by
-customizing the option @code{org-odt-convert-processes}.  Also specify how
-the converter can be invoked via command-line to effect the conversion.
+Add the name of the converter to the @code{org-odt-convert-processes}
+variable.  Note that it also requires how the converter is invoked on the
+command line.  See the variable's docstring for details.
 
 @item Configure its capabilities
 
 @vindex org-odt-convert-capabilities
address@hidden Specify the set of formats the
-converter can handle by customizing the variable
address@hidden  Use the default value for this
-variable as a guide for configuring your converter.  As suggested by the
-default setting, you can specify the full set of formats supported by the
-converter and not limit yourself to specifying formats that are related to
-just the OpenDocument Text format.
address@hidden Specify which formats the converter can
+handle by customizing the variable @code{org-odt-convert-capabilities}.  Use
+the entry for the default values in this variable for configuring the new
+converter.  Also see its docstring for details.
 
 @item Choose the converter
 
@@ -12472,18 +13080,17 @@ Select the newly added converter as the preferred one 
by customizing the
 option @code{org-odt-convert-process}.
 @end enumerate
 
address@hidden Working with OpenDocument style files, Creating one-off styles, 
Configuring a document converter, Advanced topics in ODT export
address@hidden Working with OpenDocument style files
address@hidden Working with OpenDocument style files
address@hidden Working with OpenDocument style files
 @cindex styles, custom
 @cindex template, custom
 
-This section explores the internals of the ODT exporter and the
-means by which it produces styled documents.  Read this section if you are
-interested in exploring the automatic and custom OpenDocument styles used by
-the exporter.
+This section explores the internals of the ODT exporter; the means by which
+it produces styled documents; the use of automatic and custom OpenDocument
+styles.
 
 @anchor{x-factory-styles}
address@hidden Factory styles
address@hidden a) Factory styles
 
 The ODT exporter relies on two files for generating its output.
 These files are bundled with the distribution under the directory pointed to
@@ -12524,25 +13131,25 @@ the exporter.
 
 @item
 It contains 
@samp{<text:sequence-decl>address@hidden@samp{</text:sequence-decl>}
-elements that control how various entities---tables, images, equations,
-etc.---are numbered.
+elements that control numbering of tables, images, equations, and similar
+entities.
 @end enumerate
 @end itemize
 
 @anchor{x-overriding-factory-styles}
address@hidden Overriding factory styles
-The following two variables control the location from which the ODT
-exporter picks up the custom styles and content template files.  You can
-customize these variables to override the factory styles used by the
-exporter.
address@hidden b) Overriding factory styles
+The following two variables control the location from where the ODT exporter
+picks up the custom styles and content template files.  Customize these
+variables to override the factory styles used by the exporter.
 
 @itemize
 @anchor{x-org-odt-styles-file}
 @item
 @code{org-odt-styles-file}
 
-Use this variable to specify the @file{styles.xml} that will be used in the
-final output.  You can specify one of the following values:
+The ODT export back-end uses the file pointed to by this variable, such as
address@hidden, for the final output.  It can take one of the following
+values:
 
 @enumerate
 @item A @file{styles.xml} file
@@ -12576,28 +13183,26 @@ Use this variable to specify the blank 
@file{content.xml} that will be used
 in the final output.
 @end itemize
 
address@hidden Creating one-off styles, Customizing tables in ODT export, 
Working with OpenDocument style files, Advanced topics in ODT export
address@hidden Creating one-off styles
address@hidden Creating one-off styles
address@hidden Creating one-off styles
 
-There are times when you would want one-off formatting in the exported
-document.  You can achieve this by embedding raw OpenDocument XML in the Org
-file.  The use of this feature is better illustrated with couple of examples.
+The ODT export back-end can read embedded raw OpenDocument XML from the Org
+file.  Such direct formatting are useful for one-off instances.
 
 @enumerate
 @item Embedding ODT tags as part of regular text
 
-You can inline OpenDocument syntax by enclosing it within
address@hidden@@@@odt:...@@@@} markup.  For example, to highlight a region of 
text do
-the following:
+Enclose OpenDocument syntax in @samp{@@@@odt:...@@@@} for inline markup.  For
+example, to highlight a region of text do the following:
 
 @example
-@@@@odt:<text:span text:style-name="Highlight">This is a highlighted
-text</text:span>@@@@.  But this is a regular text.
+@@@@odt:<text:span text:style-name="Highlight">This is highlighted
+text</text:span>@@@@.  But this is regular text.
 @end example
 
address@hidden:} To see the above example in action, edit your
address@hidden (@pxref{x-orgodtstyles-xml,,Factory styles}) and add a
-custom @samp{Highlight} style as shown below.
address@hidden:} To see the above example in action, edit the @file{styles.xml}
+(@pxref{x-orgodtstyles-xml,,Factory styles}) and add a custom
address@hidden style as shown below:
 
 @example
 <style:style style:name="Highlight" style:family="text">
@@ -12607,8 +13212,8 @@ custom @samp{Highlight} style as shown below.
 
 @item Embedding a one-line OpenDocument XML
 
-You can add a simple OpenDocument one-liner using the @code{#+ODT:}
-directive.  For example, to force a page break do the following:
+The ODT export back-end can read one-liner options with @code{#+ODT:}
+in the Org file.  For example, to force a page break:
 
 @example
 #+ODT: <text:p text:style-name="PageBreak"/>
@@ -12627,41 +13232,40 @@ custom @samp{PageBreak} style as shown below.
 
 @item Embedding a block of OpenDocument XML
 
-You can add a large block of OpenDocument XML using the
address@hidden@address@hidden construct.
+The ODT export back-end can also read ODT export blocks for OpenDocument XML.
+Such blocks use the @code{#+BEGIN_EXPORT address@hidden@code{#+END_EXPORT}
+constructs.
 
 For example, to create a one-off paragraph that uses bold text, do the
 following:
 
 @example
-#+BEGIN_ODT
+#+BEGIN_EXPORT odt
 <text:p text:style-name="Text_20_body_20_bold">
 This paragraph is specially formatted and uses bold text.
 </text:p>
-#+END_ODT
+#+END_EXPORT
 @end example
 
 @end enumerate
 
address@hidden Customizing tables in ODT export, Validating OpenDocument XML, 
Creating one-off styles, Advanced topics in ODT export
address@hidden Customizing tables in ODT export
address@hidden Customizing tables in ODT export
address@hidden Customizing tables in ODT export
 @cindex tables, in ODT export
 
 @cindex #+ATTR_ODT
-You can override the default formatting of the table by specifying a custom
-table style with the @code{#+ATTR_ODT} line.  For a discussion on default
-formatting of tables @pxref{Tables in ODT export}.
+Override the default table format by specifying a custom table style with the
address@hidden line.  For a discussion on default formatting of tables
address@hidden in ODT export}.
 
 This feature closely mimics the way table templates are defined in the
 OpenDocument-v1.2
 
address@hidden@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html,
 OpenDocument-v1.2 Specification}}
 
address@hidden Custom table styles: an illustration
-
 @vindex org-odt-table-styles
-To have a quick preview of this feature, install the below setting and
-export the table that follows:
+For quick preview of this feature, install the settings below and export the
+table that follows:
 
 @lisp
 (setq org-odt-table-styles
@@ -12675,22 +13279,20 @@ export the table that follows:
 @end lisp
 
 @example
-#+ATTR_ODT: :style "TableWithHeaderRowAndColumn"
+#+ATTR_ODT: :style TableWithHeaderRowAndColumn
 | Name  | Phone | Age |
 | Peter |  1234 |  17 |
 | Anna  |  4321 |  25 |
 @end example
 
-In the above example, you used a template named @samp{Custom} and installed
-two table styles with the names @samp{TableWithHeaderRowAndColumn} and
address@hidden  (@strong{Important:} The OpenDocument
-styles needed for producing the above template have been pre-defined for
-you.  These styles are available under the section marked @samp{Custom
-Table Template} in @file{OrgOdtContentTemplate.xml}
-(@pxref{x-orgodtcontenttemplate-xml,,Factory styles}).  If you need
-additional templates you have to define these styles yourselves.
+The example above used @samp{Custom} template and installed two table styles
address@hidden and @samp{TableWithFirstRowandLastRow}.
address@hidden:} The OpenDocument styles needed for producing the above
+template were pre-defined.  They are available in the section marked
address@hidden Table Template} in @file{OrgOdtContentTemplate.xml}
+(@pxref{x-orgodtcontenttemplate-xml,,Factory styles}.  For adding new
+templates, define new styles here.
 
address@hidden Custom table styles: the nitty-gritty
 To use this feature proceed as follows:
 
 @enumerate
@@ -12698,8 +13300,8 @@ To use this feature proceed as follows:
 Create a table address@hidden the @code{<table:table-template>}
 element of the OpenDocument-v1.2 specification}
 
-A table template is nothing but a set of @samp{table-cell} and
address@hidden styles for each of the following table cell categories:
+A table template is set of @samp{table-cell} and @samp{paragraph} styles for
+each of the following table cell categories:
 
 @itemize @minus
 @item Body
@@ -12809,25 +13411,22 @@ the @code{ATTR_ODT} line as shown below.
 @end example
 @end enumerate
 
address@hidden Validating OpenDocument XML,  , Customizing tables in ODT 
export, Advanced topics in ODT export
address@hidden Validating OpenDocument XML
-
-Occasionally, you will discover that the document created by the
-ODT exporter cannot be opened by your favorite application.  One of
-the common reasons for this is that the @file{.odt} file is corrupt.  In such
-cases, you may want to validate the document against the OpenDocument RELAX
-NG Compact Syntax (RNC) schema.
address@hidden Validating OpenDocument XML
address@hidden Validating OpenDocument XML
 
-For de-compressing the @file{.odt} address@hidden@file{.odt} files are
-nothing but @samp{zip} archives}: @inforef{File Archives,,emacs}.  For
-general help with validation (and schema-sensitive editing) of XML files:
+Sometimes ODT format files may not open due to @file{.odt} file corruption.
+To verify if the @file{.odt} file is corrupt, validate it against the
+OpenDocument RELAX NG Compact Syntax---RNC---schema.  But first the
address@hidden files have to be decompressed using @samp{zip}.  Note that
address@hidden files are @samp{zip} archives: @inforef{File Archives,,emacs}.
+The contents of @file{.odt} files are in @file{.xml}.  For general help with
+validation---and schema-sensitive editing---of XML files:
 @inforef{Introduction,,nxml-mode}.
 
 @vindex org-odt-schema-dir
-If you have ready access to OpenDocument @file{.rnc} files and the needed
-schema-locating rules in a single folder, you can customize the variable
address@hidden to point to that directory.  The ODT exporter
-will take care of updating the @code{rng-schema-locating-files} for you.
+Customize @code{org-odt-schema-dir} to point to a directory with OpenDocument
address@hidden files and the needed schema-locating rules.  The ODT export
+back-end takes care of updating the @code{rng-schema-locating-files}.
 
 @c end opendocument
 
@@ -12836,102 +13435,146 @@ will take care of updating the 
@code{rng-schema-locating-files} for you.
 @cindex Org export
 
 @code{org} export back-end creates a normalized version of the Org document
-in current buffer.  In particular, it evaluates Babel code (@pxref{Evaluating
-code blocks}) and removes other back-ends specific contents.
+in current buffer.  The exporter evaluates Babel code (@pxref{Evaluating code
+blocks}) and removes content specific to other back-ends.
 
 @subheading Org export commands
 
 @table @kbd
 @orgcmd{C-c C-e O o,org-org-export-to-org}
-Export as an Org document.  For an Org file, @file{myfile.org}, the resulting
-file will be @file{myfile.org.org}.  The file will be overwritten without
-warning.
+Export as an Org file with a @file{.org} extension.  For @file{myfile.org},
+Org exports to @file{myfile.org.org}, overwriting without warning.
+
 @orgcmd{C-c C-e O O,org-org-export-as-org}
-Export to a temporary buffer.  Do not create a file.
+Export to a temporary buffer.  Does not create a file.
 @item C-c C-e O v
 Export to an Org file, then open it.
 @end table
 
address@hidden Texinfo export, iCalendar export, Org export, Exporting
address@hidden Texinfo export
 @section Texinfo export
 @cindex Texinfo export
 
address@hidden export back-end generates Texinfo code and can compile it into
-an Info file.
+The @samp{texinfo} export back-end generates documents with Texinfo code that
+can compile to Info format.
 
 @menu
-* Texinfo export commands::     How to invoke Texinfo export
-* Document preamble::           File header, title and copyright page
-* Headings and sectioning structure:: Building document structure
-* Indices::                     Creating indices
-* Quoting Texinfo code::        Incorporating literal Texinfo code
-* Texinfo specific attributes:: Controlling Texinfo output
-* An example::
+* Texinfo export commands::     Invoking commands.
+* Texinfo specific export settings::  Setting the environment.
+* Texinfo file header::         Generating the header.
+* Texinfo title and copyright page::  Creating preamble pages.
+* Info directory file::     Installing a manual in Info file hierarchy.
+* Headings and sectioning structure::  Building document structure.
+* Indices::                     Creating indices.
+* Quoting Texinfo code::        Incorporating literal Texinfo code.
+* Plain lists in Texinfo export::  List attributes.
+* Tables in Texinfo export::    Table attributes.
+* Images in Texinfo export::    Image attributes.
+* Special blocks in Texinfo export::  Special block attributes.
+* A Texinfo example::           Processing Org to Texinfo.
 @end menu
 
address@hidden Texinfo export commands, Document preamble, Texinfo export, 
Texinfo export
address@hidden Texinfo export commands
 @subsection Texinfo export commands
 
 @vindex org-texinfo-info-process
 @table @kbd
 @orgcmd{C-c C-e i t,org-texinfo-export-to-texinfo}
-Export as a Texinfo file.  For an Org file, @file{myfile.org}, the resulting
-file will be @file{myfile.texi}.  The file will be overwritten without
-warning.
+Export as a Texinfo file with @file{.texi} extension.  For @file{myfile.org},
+Org exports to @file{myfile.texi}, overwriting without warning.
 @orgcmd{C-c C-e i i,org-texinfo-export-to-info}
-Export to Texinfo and then process to an Info address@hidden setting
address@hidden, it is possible to generate other formats,
-including DocBook.}.
+Export to Texinfo format first and then process it to make an Info file.  To
+generate other formats, such as DocBook, customize the
address@hidden variable.
 @end table
 
address@hidden Document preamble, Headings and sectioning structure, Texinfo 
export commands, Texinfo export
address@hidden Document preamble
address@hidden Texinfo specific export settings
address@hidden Texinfo specific export settings
+The Texinfo export back-end has several additional keywords for customizing
+Texinfo output.  Setting these keywords works similar to the general options
+(@pxref{Export settings}).
+
address@hidden @samp
+
address@hidden SUBTITLE
address@hidden #+SUBTITLE (Texinfo)
+The document subtitle.
+
address@hidden SUBAUTHOR
address@hidden #+SUBAUTHOR
+The document subauthor.
+
address@hidden TEXINFO_FILENAME
address@hidden #+TEXINFO_FILENAME
+The Texinfo filename.
+
address@hidden TEXINFO_CLASS
address@hidden #+TEXINFO_CLASS
address@hidden org-texinfo-default-class
+The default document class (@code{org-texinfo-default-class}), which must be
+a member of @code{org-texinfo-classes}.
+
address@hidden TEXINFO_HEADER
address@hidden #+TEXINFO_HEADER
+Arbitrary lines inserted at the end of the header.
+
address@hidden TEXINFO_POST_HEADER
address@hidden #+TEXINFO_POST_HEADER
+Arbitrary lines inserted after the end of the header.
 
-When processing a document, @samp{texinfo} back-end generates a minimal file
-header along with a title page, a copyright page, and a menu.  You control
-the latter through the structure of the document (@pxref{Headings and
-sectioning structure}).  Various keywords allow you to tweak the other parts.
-It is also possible to give directions to install the document in the
address@hidden node.
address@hidden TEXINFO_DIR_CATEGORY
address@hidden #+TEXINFO_DIR_CATEGORY
+The directory category of the document.
+
address@hidden TEXINFO_DIR_TITLE
address@hidden #+TEXINFO_DIR_TITLE
+The directory title of the document.
+
address@hidden TEXINFO_DIR_DESC
address@hidden #+TEXINFO_DIR_DESC
+The directory description of the document.
+
address@hidden TEXINFO_PRINTED_TITLE
address@hidden #+TEXINFO_PRINTED_TITLE
+The printed title of the document.
address@hidden table
 
address@hidden File header
address@hidden Texinfo file header
address@hidden Texinfo file header
 
 @cindex #+TEXINFO_FILENAME
-Upon creating the header of a Texinfo file, the back-end guesses a name for
-the Info file to be compiled.  This may not be a sensible choice, e.g., if
-you want to produce the final document in a different directory.  Specify an
-alternate path with @code{#+TEXINFO_FILENAME} keyword to override the default
-destination.
+After creating the header for a Texinfo file, the Texinfo back-end
+automatically generates a name and destination path for the Info file.  To
+override this default with a more sensible path and name, specify the
address@hidden keyword.
 
 @vindex org-texinfo-coding-system
 @vindex org-texinfo-classes
 @cindex #+TEXINFO_HEADER
 @cindex #+TEXINFO_CLASS
-Along with the output file name, the header contains information about the
-language (@pxref{Export settings}) and current encoding address@hidden
address@hidden for more information.}.  Insert
-a @code{#+TEXINFO_HEADER} keyword for each additional command needed, e.g.,
+Along with the output's file name, the Texinfo header also contains language
+details (@pxref{Export settings}) and encoding system as set in the
address@hidden variable.  Insert @code{#+TEXINFO_HEADER}
+keywords for each additional command in the header, for example:
 @@address@hidden@@address@hidden
 
-If you happen to regularly install the same set of commands, it may be easier
-to define your own class in @code{org-texinfo-classes}, which see.  Set
address@hidden keyword accordingly in your document to activate it.
+Instead of repeatedly installing the same set of commands, define a class in
address@hidden once, and then activate it in the document by
+setting the @code{#+TEXINFO_CLASS} keyword to that class.
 
address@hidden Title and copyright page
address@hidden Texinfo title and copyright page
address@hidden Texinfo title and copyright page
 
 @cindex #+TEXINFO_PRINTED_TITLE
address@hidden #+SUBTITLE
-The default template includes a title page for hard copy output.  The title
-and author displayed on this page are extracted from, respectively,
address@hidden and @code{#+AUTHOR} keywords (@pxref{Export settings}).  It is
-also possible to print a different, more specific, title with
address@hidden keyword, and add subtitles with
address@hidden keyword.  Both expect raw Texinfo code in their value.
+The default template for hard copy output has a title page with
address@hidden and @code{#+AUTHOR} (@pxref{Export settings}).  To replace the
+regular @code{#+TITLE} with something different for the printed version, use
+the @code{#+TEXINFO_PRINTED_TITLE} and @code{#+SUBTITLE} keywords.  Both
+expect raw Texinfo code for setting their values.
 
 @cindex #+SUBAUTHOR
-Likewise, information brought by @code{#+AUTHOR} may not be enough.  You can
-include other authors with several @code{#+SUBAUTHOR} keywords.  Values are
-also expected to be written in Texinfo code.
+If one @code{#+AUTHOR} is not sufficient, add multiple @code{#+SUBAUTHOR}
+keywords.  They have to be set in raw Texinfo code.
 
 @example
 #+AUTHOR: Jane Smith
@@ -12940,10 +13583,10 @@ also expected to be written in Texinfo code.
 @end example
 
 @cindex property, COPYING
-Copying material is defined in a dedicated headline with a non-nil
address@hidden:COPYING:} property.  The contents are inserted within
-a @code{@@copying} command at the beginning of the document whereas the
-heading itself does not appear in the structure of the document.
+Copying material is defined in a dedicated headline with a address@hidden
address@hidden:COPYING:} property.  The back-end inserts the contents within a
address@hidden@@copying} command at the beginning of the document.  The heading
+itself does not appear in the structure of the document.
 
 Copyright information is printed on the back of the title page.
 
@@ -12955,20 +13598,28 @@ Copyright information is printed on the back of the 
title page.
 
   This is a short example of a complete Texinfo file, version 1.0.
 
-  Copyright \copy 2017 Free Software Foundation, Inc.
+  Copyright \copy 2016 Free Software Foundation, Inc.
 @end example
 
address@hidden The Top node
address@hidden Info directory file
address@hidden Info directory file
address@hidden @samp{dir} file, in Texinfo export
address@hidden Texinfo export, @samp{dir} file
address@hidden Info directory file, in Texinfo export
address@hidden Texinfo export, Info directory file
address@hidden @code{install-info} parameters, in Texinfo export
address@hidden Texinfo export, @code{install-info} parameters
 
 @cindex #+TEXINFO_DIR_CATEGORY
 @cindex #+TEXINFO_DIR_TITLE
 @cindex #+TEXINFO_DIR_DESC
-You may ultimately want to install your new Info file to your system.  You
-can write an appropriate entry in the top level directory specifying its
-category and title with, respectively, @code{#+TEXINFO_DIR_CATEGORY} and
address@hidden  Optionally, you can add a short description
-using @code{#+TEXINFO_DIR_DESC}.  The following example would write an entry
-similar to Org's in the @samp{Top} node.
+The end result of the Texinfo export process is the creation of an Info file.
+This Info file's metadata has variables for category, title, and description:
address@hidden, @code{#+TEXINFO_DIR_TITLE}, and
address@hidden that establish where in the Info hierarchy the file
+fits.
+
+Here is an example that writes to the Info directory file:
 
 @example
 #+TEXINFO_DIR_CATEGORY: Emacs
@@ -12976,34 +13627,38 @@ similar to Org's in the @samp{Top} node.
 #+TEXINFO_DIR_DESC: Outline-based notes management and organizer
 @end example
 
address@hidden Headings and sectioning structure, Indices, Document preamble, 
Texinfo export
address@hidden Headings and sectioning structure
 @subsection Headings and sectioning structure
 
 @vindex org-texinfo-classes
 @vindex org-texinfo-default-class
 @cindex #+TEXINFO_CLASS
address@hidden uses a pre-defined scheme, or class, to convert headlines into
-Texinfo structuring commands.  For example, a top level headline appears as
address@hidden@@chapter} if it should be numbered or as @code{@@unnumbered}
-otherwise.  If you need to use a different set of commands, e.g., to start
-with @code{@@part} instead of @code{@@chapter}, install a new class in
address@hidden, then activate it with @code{#+TEXINFO_CLASS}
-keyword.  Export process defaults to @code{org-texinfo-default-class} when
-there is no such keyword in the document.
-
-If a headline's level has no associated structuring command, or is below
-a certain threshold @pxref{Export settings}, that headline becomes a list in
-Texinfo output.
+The Texinfo export back-end uses a pre-defined scheme to convert Org
+headlines to an equivalent Texinfo structuring commands.  A scheme like this
+maps top-level headlines to numbered chapters tagged as @code{@@chapter} and
+lower-level headlines to unnumbered chapters tagged as @code{@@unnumbered}.
+To override such mappings to introduce @code{@@part} or other Texinfo
+structuring commands, define a new class in @code{org-texinfo-classes}.
+Activate the new class with the @code{#+TEXINFO_CLASS} keyword.  When no new
+class is defined and activated, the Texinfo export back-end defaults to the
address@hidden
+
+If an Org headline's level has no associated Texinfo structuring command, or
+is below a certain threshold (@pxref{Export settings}), then the Texinfo
+export back-end makes it into a list item.
 
 @cindex property, APPENDIX
-As an exception, a headline with a non-nil @code{:APPENDIX:} property becomes
-an appendix, independently on its level and the class used.
+The Texinfo export back-end makes any headline with a address@hidden
address@hidden:APPENDIX:} property into an appendix.  This happens independent 
of the
+Org headline level or the @code{#+TEXINFO_CLASS}.
 
 @cindex property, DESCRIPTION
-Each regular sectioning structure creates a menu entry, named after the
-heading.  You can provide a different, e.g., shorter, title in
address@hidden:ALT_TITLE:} property (@pxref{Table of contents}).  Optionally, 
you can
-specify a description for the item in @code{:DESCRIPTION:} property.  E.g.,
+The Texinfo export back-end creates a menu entry after the Org headline for
+each regular sectioning structure.  To override this with a shorter menu
+entry, use the @code{:ALT_TITLE:} property (@pxref{Table of contents}).
+Texinfo menu entries also have an option for a longer @code{:DESCRIPTION:}
+property.  Here's an example that uses both to override the default menu
+entry:
 
 @example
 * Controlling Screen Display
@@ -13013,30 +13668,51 @@ specify a description for the item in 
@code{:DESCRIPTION:} property.  E.g.,
   :END:
 @end example
 
address@hidden Indices, Quoting Texinfo code, Headings and sectioning 
structure, Texinfo export
address@hidden The Top node, in Texinfo export
address@hidden Texinfo export, Top node
+The text before the first headline belongs to the @samp{Top} node, i.e., the
+node in which a reader enters an Info manual.  As such, it is expected not to
+appear in printed output generated from the @file{.texi} file.  @inforef{The
+Top Node,,texinfo}, for more information.
+
address@hidden Indices
 @subsection Indices
 
 @cindex #+CINDEX
address@hidden concept index, in Texinfo export
address@hidden Texinfo export, index, concept
 @cindex #+FINDEX
address@hidden function index, in Texinfo export
address@hidden Texinfo export, index, function
 @cindex #+KINDEX
address@hidden keystroke index, in Texinfo export
address@hidden Texinfo export, keystroke index
 @cindex #+PINDEX
address@hidden program index, in Texinfo export
address@hidden Texinfo export, program index
 @cindex #+TINDEX
address@hidden data type index, in Texinfo export
address@hidden Texinfo export, data type index
 @cindex #+VINDEX
-Index entries are created using dedicated keywords.  @samp{texinfo} back-end
-provides one for each predefined type: @code{#+CINDEX}, @code{#+FINDEX},
address@hidden, @code{#+PINDEX}, @code{#+TINDEX} and @code{#+VINDEX}.  For
-custom indices, you can write raw Texinfo code (@pxref{Quoting Texinfo
-code}).
address@hidden variable index, in Texinfo export
address@hidden Texinfo export, variable index
+The Texinfo export back-end recognizes these indexing keywords if used in the
+Org file: @code{#+CINDEX}, @code{#+FINDEX}, @code{#+KINDEX}, @code{#+PINDEX},
address@hidden, and @code{#+VINDEX}.  Write their value as verbatim Texinfo
+code; in particular, @address@hidden, @address@hidden and @samp{@@} characters 
need to be
+escaped with @samp{@@} if they not belong to a Texinfo command.
 
 @example
 #+CINDEX: Defining indexing entries
 @end example
 
 @cindex property, INDEX
-To generate an index, you need to set the @code{:INDEX:} property of
-a headline to an appropriate abbreviation (e.g., @samp{cp} or @samp{vr}).
-The headline is then exported as an unnumbered chapter or section command and
-the index is inserted after its contents.
+For the back-end to generate an index entry for a headline, set the
address@hidden:INDEX:} property to @samp{cp} or @samp{vr}.  These abbreviations 
come
+from Texinfo that stand for concept index and variable index.  The Texinfo
+manual has abbreviations for all other kinds of indexes.  The back-end
+exports the headline as an unnumbered chapter or section command, and then
+inserts the index after its contents.
 
 @example
 * Concept Index
@@ -13045,78 +13721,115 @@ the index is inserted after its contents.
   :END:
 @end example
 
address@hidden Quoting Texinfo code, Texinfo specific attributes, Indices, 
Texinfo export
address@hidden Quoting Texinfo code
 @subsection Quoting Texinfo code
 
-It is possible to insert raw Texinfo code using any of the following
-constructs
+Use any of the following three methods to insert or escape raw Texinfo code:
 
 @cindex #+TEXINFO
address@hidden #+BEGIN_TEXINFO
address@hidden #+BEGIN_EXPORT texinfo
 @example
 Richard @@@@texinfo:@@address@hidden@@@@Stallman@@@@texinfo:@}@@@@ commence' 
GNU.
 
 #+TEXINFO: @@need800
 This paragraph is preceded by...
 
-#+BEGIN_TEXINFO
+#+BEGIN_EXPORT texinfo
 @@auindex Johnson, Mark
 @@auindex Lakoff, George
-#+END_TEXINFO
+#+END_EXPORT
 @end example
 
address@hidden Texinfo specific attributes, An example, Quoting Texinfo code, 
Texinfo export
address@hidden Texinfo specific attributes
-
address@hidden #+ATTR_TEXINFO
address@hidden back-end understands several attributes in plain lists and
-tables.  They must be specified using an @code{#+ATTR_TEXINFO} keyword,
-written just above the list or table.
-
address@hidden Plain lists
-
-In Texinfo output, description lists appear as two-column tables, using the
-default command @code{@@table}.  You can use @code{@@ftable} or
address@hidden@@address@hidden more information, @inforef{Two-column
-Tables,,texinfo}.} instead with @code{:table-type} attribute.
address@hidden Plain lists in Texinfo export
address@hidden Plain lists in Texinfo export
address@hidden #+ATTR_TEXINFO, in plain lists
+The Texinfo export back-end by default converts description lists in the Org
+file using the default command @code{@@table}, which results in a table with
+two columns.  To change this behavior, specify @code{:table-type} with
address@hidden@@ftable} or @code{@@vtable} attributes.  For more information,
address@hidden Tables,,texinfo}.
 
 @vindex org-texinfo-def-table-markup
-In any case, these constructs require a highlighting command for entries in
-the list.  You can provide one with @code{:indic} attribute.  If you do not,
-it defaults to the value stored in @code{org-texinfo-def-table-markup}, which
-see.
+The Texinfo export back-end by default also applies a text highlight based on
+the defaults stored in @code{org-texinfo-def-table-markup}.  To override the
+default highlight command, specify another one with the @code{:indic}
+attribute as shown in this example:
 
 @example
 #+ATTR_TEXINFO: :indic @@asis
 - foo :: This is the text for /foo/, with no highlighting.
 @end example
 
address@hidden Tables
address@hidden Tables in Texinfo export
address@hidden Tables in Texinfo export
address@hidden #+ATTR_TEXINFO, in tables
 
-When exporting a table, column widths are deduced from the longest cell in
-each column.  You can also define them explicitly as fractions of the line
-length, using @code{:columns} attribute.
+When exporting tables, the Texinfo export back-end uses the widest cell width
+in each column.  To override this and instead specify as fractions of line
+length, use the @code{:columns} attribute.  See example below.
 
 @example
 #+ATTR_TEXINFO: :columns .5 .5
 | a cell | another cell |
 @end example
 
address@hidden An example,  , Texinfo specific attributes, Texinfo export
address@hidden An example
address@hidden Images in Texinfo export
address@hidden Images in Texinfo export
address@hidden #+ATTR_TEXINFO, in images
 
-Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}.
+Insert a file link to the image in the Org file, and the Texinfo export
+back-end inserts the image.  These links must have the usual supported image
+extensions and no descriptions.  To scale the image, use @code{:width} and
address@hidden:height} attributes.  For alternate text, use @code{:alt} and 
specify
+the text using Texinfo code, as shown in the example:
 
address@hidden
-#+MACRO: version 2.0
-#+MACRO: updated last updated 4 March 2014
address@hidden
+#+ATTR_TEXINFO: :width 1in :alt Alternate @@address@hidden@}
+[[ridt.pdf]]
address@hidden example
 
-#+OPTIONS: ':t toc:t author:t email:t
address@hidden Special blocks in Texinfo export
address@hidden Special blocks
address@hidden #+ATTR_TEXINFO, in special blocks
+
+The Texinfo export back-end converts special blocks to commands with the same
+name.  It also adds any @code{:options} attributes to the end of the command,
+as shown in this example:
+
address@hidden
+#+ATTR_TEXINFO: :options org-org-export-to-org ...
+#+begin_defun
+A somewhat obsessive function.
+#+end_defun
address@hidden example
+
address@hidden
+becomes
+
address@hidden
+@@defun org-org-export-to-org ...
+A somewhat obsessive function.
+@@end defun
address@hidden example
+
address@hidden A Texinfo example
address@hidden A Texinfo example
+
+Here is a more detailed example Org file.  @inforef{GNU Sample
+Texts,,texinfo} for an equivalent example using Texinfo code.
+
address@hidden
 #+TITLE: GNU Sample @address@hidden@address@hidden@address@hidden
+#+SUBTITLE: for version @address@hidden@address@hidden@address@hidden, 
@address@hidden@address@hidden@address@hidden
 #+AUTHOR: A.U. Thor
 #+EMAIL: bug-sample@@gnu.org
+
+#+OPTIONS: ':t toc:t author:t email:t
 #+LANGUAGE: en
 
+#+MACRO: version 2.0
+#+MACRO: updated last updated 4 March 2014
+
 #+TEXINFO_FILENAME: sample.info
 #+TEXINFO_HEADER: @@syncodeindex pg cp
 
@@ -13125,7 +13838,9 @@ Here is a thorough example, taken from @inforef{GNU 
Sample Texts,,texinfo}.
 #+TEXINFO_DIR_DESC: Invoking sample
 
 #+TEXINFO_PRINTED_TITLE: GNU Sample
-#+SUBTITLE: for version 2.0, last updated 4 March 2014
+
+This manual is for GNU Sample (version 
@address@hidden@address@hidden@address@hidden,
address@hidden@address@hidden@address@hidden@}).
 
 * Copying
   :PROPERTIES:
@@ -13135,8 +13850,7 @@ Here is a thorough example, taken from @inforef{GNU 
Sample Texts,,texinfo}.
   This manual is for GNU Sample (version 
@address@hidden@address@hidden@address@hidden,
   @address@hidden@address@hidden@address@hidden), which is an example in the 
Texinfo documentation.
 
-  Copyright @@@@texinfo:@@address@hidden@}@@@@ 2013 Free Software Foundation,
-  Inc.
+  Copyright \copy 2016 Free Software Foundation, Inc.
 
   #+BEGIN_QUOTE
   Permission is granted to copy, distribute and/or modify this
@@ -13167,9 +13881,9 @@ Here is a thorough example, taken from @inforef{GNU 
Sample Texts,,texinfo}.
   :PROPERTIES:
   :INDEX:    cp
   :END:
address@hidden smallexample
address@hidden example
 
address@hidden iCalendar export, Other built-in back-ends, Texinfo export, 
Exporting
address@hidden iCalendar export
 @section iCalendar export
 @cindex iCalendar export
 
@@ -13178,49 +13892,51 @@ Here is a thorough example, taken from @inforef{GNU 
Sample Texts,,texinfo}.
 @vindex org-icalendar-use-scheduled
 @vindex org-icalendar-categories
 @vindex org-icalendar-alarm-time
-Some people use Org mode for keeping track of projects, but still prefer a
-standard calendar application for anniversaries and appointments.  In this
-case it can be useful to show deadlines and other time-stamped items in Org
-files in the calendar application.  Org mode can export calendar information
-in the standard iCalendar format.  If you also want to have TODO entries
-included in the export, configure the variable
address@hidden  Plain timestamps are exported as VEVENT,
-and TODO items as address@hidden  It will also create events from deadlines 
that are
-in non-TODO items.  Deadlines and scheduling dates in TODO items will be used
-to set the start and due dates for the TODO address@hidden the variables
address@hidden and @code{org-icalendar-use-scheduled}.}.
-As categories, it will use the tags locally defined in the heading, and the
-file/tree address@hidden add inherited tags or the TODO state,
-configure the variable @code{org-icalendar-categories}.}.  See the variable
address@hidden for a way to assign alarms to entries with a
-time.
+A large part of Org mode's inter-operability success is its ability to easily
+export to or import from external applications.  The iCalendar export
+back-end takes calendar data from Org files and exports to the standard
+iCalendar format.
+
+The iCalendar export back-end can also incorporate TODO entries based on the
+configuration of the @code{org-icalendar-include-todo} variable.  The
+back-end exports plain timestamps as VEVENT, TODO items as VTODO, and also
+create events from deadlines that are in non-TODO items.  The back-end uses
+the deadlines and scheduling dates in Org TODO items for setting the start
+and due dates for the iCalendar TODO entry.  Consult the
address@hidden and @code{org-icalendar-use-scheduled}
+variables for more details.
+
+For tags on the headline, the iCalendar export back-end makes them into
+iCalendar categories.  To tweak the inheritance of tags and TODO states,
+configure the variable @code{org-icalendar-categories}.  To assign clock
+alarms based on time, configure the @code{org-icalendar-alarm-time} variable.
 
 @vindex org-icalendar-store-UID
 @cindex property, ID
-The iCalendar standard requires each entry to have a globally unique
-identifier (UID).  Org creates these identifiers during export.  If you set
-the variable @code{org-icalendar-store-UID}, the UID will be stored in the
address@hidden:ID:} property of the entry and re-used next time you report this
-entry.  Since a single entry can give rise to multiple iCalendar entries (as
-a timestamp, a deadline, a scheduled item, and as a TODO item), Org adds
-prefixes to the UID, depending on what triggered the inclusion of the entry.
-In this way the UID remains unique, but a synchronization program can still
-figure out from which entry all the different instances originate.
+The iCalendar format standard requires globally unique identifier---UID---for
+each entry.  The iCalendar export back-end creates UIDs during export.  To
+save a copy of the UID in the Org file set the variable
address@hidden  The back-end looks for the @code{:ID:}
+property of the entry for re-using the same UID for subsequent exports.
+
+Since a single Org entry can result in multiple iCalendar entries---as
+timestamp, deadline, scheduled item, or TODO item---Org adds prefixes to the
+UID, depending on which part of the Org entry triggered the creation of the
+iCalendar entry.  Prefixing ensures UIDs remains unique, yet enable
+synchronization programs trace the connections.
 
 @table @kbd
 @orgcmd{C-c C-e c f,org-icalendar-export-to-ics}
-Create iCalendar entries for the current buffer and store them in the same
-directory, using a file extension @file{.ics}.
+Create iCalendar entries from the current Org buffer and store them in the
+same directory, using a file extension @file{.ics}.
 @orgcmd{C-c C-e c a, org-icalendar-export-agenda-files}
 @vindex org-agenda-files
-Like @kbd{C-c C-e c f}, but do this for all files in
address@hidden  For each of these files, a separate iCalendar
-file will be written.
+Create iCalendar entries from Org files in @code{org-agenda-files} and store
+in a separate iCalendar file for each Org file.
 @orgcmd{C-c C-e c c,org-icalendar-combine-agenda-files}
 @vindex org-icalendar-combined-agenda-file
-Create a single large iCalendar file from all files in
address@hidden and write it to the file given by
address@hidden
+Create a combined iCalendar file from Org files in @code{org-agenda-files}
+and write it to @code{org-icalendar-combined-agenda-file} file name.
 @end table
 
 @vindex org-use-property-inheritance
@@ -13228,72 +13944,54 @@ Create a single large iCalendar file from all files in
 @cindex property, SUMMARY
 @cindex property, DESCRIPTION
 @cindex property, LOCATION
-The export will honor SUMMARY, DESCRIPTION and address@hidden LOCATION
-property can be inherited from higher in the hierarchy if you configure
address@hidden accordingly.} properties if the selected
-entries have them.  If not, the summary will be derived from the headline,
-and the description from the body (limited to
address@hidden characters).
-
-How this calendar is best read and updated, depends on the application
-you are using.  The FAQ covers this issue.
-
address@hidden Other built-in back-ends, Export in foreign buffers, iCalendar 
export, Exporting
+The iCalendar export back-end includes SUMMARY, DESCRIPTION and LOCATION
+properties from the Org entries when exporting.  To force the back-end to
+inherit the LOCATION property, configure the
address@hidden variable.
+
+When Org entries do not have SUMMARY, DESCRIPTION and LOCATION properties,
+the iCalendar export back-end derives the summary from the headline, and
+derives the description from the body of the Org item.  The
address@hidden variable limits the maximum number of
+characters of the content are turned into its description.
+
+Exporting to iCalendar format depends in large part on the capabilities of
+the destination application.  Some are more lenient than others.  Consult the
+Org mode FAQ for advice on specific applications.
+
address@hidden Other built-in back-ends
 @section Other built-in back-ends
 @cindex export back-ends, built-in
 @vindex org-export-backends
 
-On top of the aforementioned back-ends, Org comes with other built-in ones:
+Other export back-ends included with Org are:
 
 @itemize
 @item @file{ox-man.el}: export to a man page.
 @end itemize
 
-To activate these export back-end, customize @code{org-export-backends} or
-load them directly with e.g., @code{(require 'ox-man)}.  This will add new
-keys in the export dispatcher (@pxref{The Export Dispatcher}).
-
-See the comment section of these files for more information on how to use
-them.
-
address@hidden Export in foreign buffers, Advanced configuration, Other 
built-in back-ends, Exporting
address@hidden Export in foreign buffers
-
-Most built-in back-ends come with a command to convert the selected region
-into a selected format and replace this region by the exported output.  Here
-is a list of such conversion commands:
+To activate such back-ends, either customize @code{org-export-backends} or
+load directly with @code{(require 'ox-man)}.  On successful load, the
+back-end adds new keys in the export dispatcher (@pxref{The export
+dispatcher}).
 
address@hidden @code
address@hidden org-html-convert-region-to-html
-Convert the selected region into HTML.
address@hidden org-latex-convert-region-to-latex
-Convert the selected region into @LaTeX{}.
address@hidden org-texinfo-convert-region-to-texinfo
-Convert the selected region into @code{Texinfo}.
address@hidden org-md-convert-region-to-md
-Convert the selected region into @code{MarkDown}.
address@hidden table
+Follow the comment section of such files, for example, @file{ox-man.el}, for
+usage and configuration details.
 
-This is particularly useful for converting tables and lists in foreign
-buffers.  E.g., in an HTML buffer, you can turn on @code{orgstruct-mode}, then
-use Org commands for editing a list, and finally select and convert the list
-with @code{M-x org-html-convert-region-to-html RET}.
-
address@hidden Advanced configuration,  , Export in foreign buffers, Exporting
address@hidden Advanced configuration
 @section Advanced configuration
 
 @subheading Hooks
 
 @vindex org-export-before-processing-hook
 @vindex org-export-before-parsing-hook
-Two hooks are run during the first steps of the export process.  The first
-one, @code{org-export-before-processing-hook} is called before expanding
-macros, Babel code and include keywords in the buffer.  The second one,
address@hidden, as its name suggests, happens just
-before parsing the buffer.  Their main use is for heavy duties, that is
-duties involving structural modifications of the document.  For example, one
-may want to remove every headline in the buffer during export.  The following
-code can achieve this:
+The export process executes two hooks before the actual exporting begins.
+The first hook, @code{org-export-before-processing-hook}, runs before any
+expansions of macros, Babel code, and include keywords in the buffer.  The
+second hook, @code{org-export-before-parsing-hook}, runs before the buffer is
+parsed.  Both hooks are specified as functions, see example below.  Their main
+use is for heavy duty structural modifications of the Org content.  For
+example, removing every headline in the buffer during export:
 
 @lisp
 @group
@@ -13307,86 +14005,83 @@ BACKEND is the export back-end being used, as a 
symbol."
 @end group
 @end lisp
 
-Note that functions used in these hooks require a mandatory argument,
-a symbol representing the back-end used.
+Note that the hook function must have a mandatory argument that is a symbol
+for the back-end.
 
 @subheading Filters
 
 @cindex Filters, exporting
-Filters are lists of functions applied on a specific part of the output from
-a given back-end.  More explicitly, each time a back-end transforms an Org
-object or element into another language, all functions within a given filter
-type are called in turn on the string produced.  The string returned by the
-last function will be the one used in the final output.
-
-There are filters sets for each type of element or object, for plain text,
-for the parse tree, for the export options and for the final output.  They
-are all named after the same scheme: @code{org-export-filter-TYPE-functions},
-where @code{TYPE} is the type targeted by the filter.  Valid types are:
+The Org export process relies on filters to process specific parts of
+conversion process.  Filters are just lists of functions to be applied to
+certain parts for a given back-end.  The output from the first function in
+the filter is passed on to the next function in the filter.  The final output
+is the output from the final function in the filter.
+
+The Org export process has many filter sets applicable to different types of
+objects, plain text, parse trees, export options, and final output formats.
+The filters are named after the element type or object type:
address@hidden, where @code{TYPE} is the type
+targeted by the filter.  Valid types are:
 
 @multitable @columnfractions .33 .33 .33
address@hidden bold
address@hidden body
address@hidden bold
 @tab babel-call
address@hidden center-block
address@hidden clock
address@hidden center-block
address@hidden clock
 @tab code
address@hidden comment
address@hidden comment-block
address@hidden diary-sexp
address@hidden diary-sexp
 @tab drawer
address@hidden dynamic-block
address@hidden entity
address@hidden dynamic-block
address@hidden entity
 @tab example-block
address@hidden export-block
address@hidden export-snippet
address@hidden export-block
address@hidden export-snippet
 @tab final-output
address@hidden fixed-width
address@hidden footnote-definition
address@hidden fixed-width
address@hidden footnote-definition
 @tab footnote-reference
address@hidden headline
address@hidden horizontal-rule
address@hidden headline
address@hidden horizontal-rule
 @tab inline-babel-call
address@hidden inline-src-block
address@hidden inlinetask
address@hidden inline-src-block
address@hidden inlinetask
 @tab italic
address@hidden item
address@hidden keyword
address@hidden item
address@hidden keyword
 @tab latex-environment
address@hidden latex-fragment
address@hidden line-break
address@hidden latex-fragment
address@hidden line-break
 @tab link
address@hidden node-property
address@hidden options
address@hidden node-property
address@hidden options
 @tab paragraph
address@hidden parse-tree
address@hidden plain-list
address@hidden parse-tree
address@hidden plain-list
 @tab plain-text
address@hidden planning
address@hidden property-drawer
address@hidden planning
address@hidden property-drawer
 @tab quote-block
address@hidden quote-section
 @tab radio-target
address@hidden section
address@hidden special-block
address@hidden section
address@hidden special-block
 @tab src-block
address@hidden statistics-cookie
address@hidden strike-through
address@hidden statistics-cookie
address@hidden strike-through
 @tab subscript
address@hidden superscript
address@hidden table
address@hidden superscript
address@hidden table
 @tab table-cell
address@hidden table-row
address@hidden target
address@hidden table-row
address@hidden target
 @tab timestamp
address@hidden underline
address@hidden verbatim
address@hidden underline
address@hidden verbatim
 @tab verse-block
address@hidden
 @end multitable
 
-For example, the following snippet allows me to use non-breaking spaces in
-the Org buffer and get them translated into @LaTeX{} without using the
address@hidden macro (where @code{_} stands for the non-breaking space):
+Here is an example filter that replaces non-breaking spaces @code{~} in the
+Org buffer with @code{_} for the @LaTeX{} back-end.
 
 @lisp
 @group
@@ -13400,33 +14095,49 @@ the Org buffer and get them translated into @LaTeX{} 
without using the
 @end group
 @end lisp
 
-Three arguments must be provided to a filter: the code being changed, the
-back-end used, and some information about the export process.  You can safely
-ignore the third argument for most purposes.  Note the use of
address@hidden, which ensures that the filter will only
-be applied when using @code{latex} back-end or any other back-end derived
-from it (e.g., @code{beamer}).
+A filter requires three arguments: the code to be transformed, the name of
+the back-end, and some optional information about the export process.  The
+third argument can be safely ignored.  Note the use of
address@hidden predicate that tests for @code{latex}
+back-end or any other back-end, such as @code{beamer}, derived from
address@hidden
 
address@hidden Extending an existing back-end
address@hidden Defining filters for individual files
+
+The Org export can filter not just for back-ends, but also for specific files
+through the @code{#+BIND} keyword.  Here is an example with two filters; one
+removes brackets from time stamps, and the other removes strike-through text.
+The filter functions are defined in a @samp{src} code block in the same Org
+file, which is a handy location for debugging.
+
address@hidden
+#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)
+#+BIND: org-export-filter-strike-through-functions (tmp-f-strike-through)
+#+begin_src emacs-lisp :exports results :results none
+  (defun tmp-f-timestamp (s backend info)
+    (replace-regexp-in-string "&[lg]t;\\|[][]" "" s))
+  (defun tmp-f-strike-through (s backend info) "")
+#+end_src
address@hidden example
 
-This is obviously the most powerful customization, since the changes happen
-at the parser level.  Indeed, some export back-ends are built as extensions
-of other ones (e.g., Markdown back-end an extension of HTML back-end).
address@hidden Extending an existing back-end
 
-Extending a back-end means that if an element type is not transcoded by the
-new back-end, it will be handled by the original one.  Hence you can extend
-specific parts of a back-end without too much work.
+Some parts of the conversion process can be extended for certain elements so
+as to introduce a new or revised translation.  That is how the HTML export
+back-end was extended to handle Markdown format.  The extensions work
+seamlessly so any aspect of filtering not done by the extended back-end is
+handled by the original back-end.  Of all the export customization in Org,
+extending is very powerful as it operates at the parser level.
 
-As an example, imagine we want the @code{ascii} back-end to display the
-language used in a source block, when it is available, but only when some
-attribute is address@hidden, like the following:
+For this example, make the @code{ascii} back-end display the language used in
+a source code block.  Also make it display only when some attribute is
address@hidden, like the following:
 
 @example
 #+ATTR_ASCII: :language t
 @end example
 
-Because that back-end is lacking in that area, we are going to create a new
-back-end, @code{my-ascii} that will do the job.
+Then extend @code{ascii} back-end with a custom @code{my-ascii} back-end.
 
 @lisp
 @group
@@ -13450,20 +14161,47 @@ channel."
 @end lisp
 
 The @code{my-ascii-src-block} function looks at the attribute above the
-element.  If it isn't true, it gives hand to the @code{ascii} back-end.
-Otherwise, it creates a box around the code, leaving room for the language.
-A new back-end is then created.  It only changes its behavior when
-translating @code{src-block} type element.  Now, all it takes to use the new
-back-end is calling the following from an Org buffer:
+current element.  If not true, hands over to @code{ascii} back-end.  If true,
+which it is in this example, it creates a box around the code and leaves room
+for the inserting a string for language.  The last form creates the new
+back-end that springs to action only when translating @code{src-block} type
+elements.
+
+To use the newly defined back-end, call the following from an Org buffer:
 
 @smalllisp
 (org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*")
 @end smalllisp
 
-It is obviously possible to write an interactive function for this, install
-it in the export dispatcher menu, and so on.
+Further steps to consider would be an interactive function, self-installing
+an item in the export dispatcher menu, and other user-friendly improvements.
+
address@hidden Export in foreign buffers
address@hidden Export in foreign buffers
+
+The export back-ends in Org often include commands to convert selected
+regions.  A convenient feature of this in-place conversion is that the
+exported output replaces the original source.  Here are such functions:
+
address@hidden @code
address@hidden org-html-convert-region-to-html
+Convert the selected region into HTML.
address@hidden org-latex-convert-region-to-latex
+Convert the selected region into @LaTeX{}.
address@hidden org-texinfo-convert-region-to-texinfo
+Convert the selected region into @code{Texinfo}.
address@hidden org-md-convert-region-to-md
+Convert the selected region into @code{MarkDown}.
address@hidden table
+
+In-place conversions are particularly handy for quick conversion of tables
+and lists in foreign buffers.  For example, turn on the minor mode @code{M-x
+orgstruct-mode} in an HTML buffer, then use the convenient Org keyboard
+commands to create a list, select it, and covert it to HTML with @code{M-x
+org-html-convert-region-to-html RET}.
+
 
address@hidden Publishing, Working With Source Code, Exporting, Top
address@hidden Publishing
 @chapter Publishing
 @cindex publishing
 
@@ -13485,7 +14223,7 @@ Publishing has been contributed to Org by David O'Toole.
 * Triggering publication::      Publication commands
 @end menu
 
address@hidden Configuration, Uploading files, Publishing, Publishing
address@hidden Configuration
 @section Configuration
 
 Publishing needs significant configuration to specify files, destination
@@ -13502,7 +14240,7 @@ and many other properties of a project.
 * Generating an index::         An index that reaches across pages
 @end menu
 
address@hidden Project alist, Sources and destinations, Configuration, 
Configuration
address@hidden Project alist
 @subsection The variable @code{org-publish-project-alist}
 @cindex org-publish-project-alist
 @cindex projects, for publishing
@@ -13529,7 +14267,7 @@ together files requiring different publishing options.  
When you publish such
 a ``meta-project'', all the components will also be published, in the
 sequence given.
 
address@hidden Sources and destinations, Selecting files, Project alist, 
Configuration
address@hidden Sources and destinations
 @subsection Sources and destinations for files
 @cindex directories, for publishing
 
@@ -13548,17 +14286,17 @@ use external tools to upload your website 
(@pxref{Uploading files}).
 @item @code{:preparation-function}
 @tab Function or list of functions to be called before starting the
 publishing process, for example, to run @code{make} for updating files to be
-published.  The project property list is scoped into this call as the
-variable @code{project-plist}.
+published.  Each preparation function is called with a single argument, the
+project property list.
 @item @code{:completion-function}
 @tab Function or list of functions called after finishing the publishing
-process, for example, to change permissions of the resulting files.  The
-project property list is scoped into this call as the variable
address@hidden
+process, for example, to change permissions of the resulting files.  Each
+completion function is called with a single argument, the project property
+list.
 @end multitable
 @noindent
 
address@hidden Selecting files, Publishing action, Sources and destinations, 
Configuration
address@hidden Selecting files
 @subsection Selecting files
 @cindex files, selecting for publishing
 
@@ -13584,7 +14322,7 @@ and @code{:exclude}.
 @tab address@hidden means, check base-directory recursively for files to 
publish.
 @end multitable
 
address@hidden Publishing action, Publishing options, Selecting files, 
Configuration
address@hidden Publishing action
 @subsection Publishing action
 @cindex action, for publishing
 
@@ -13623,46 +14361,26 @@ and the path to the publishing directory of the 
output file.  It should take
 the specified file, make the necessary transformation (if any) and place the
 result into the destination folder.
 
address@hidden Publishing options, Publishing links, Publishing action, 
Configuration
address@hidden Publishing options
 @subsection Options for the exporters
 @cindex options, for publishing
 
-The property list can be used to set many export options for the exporters.
-In most cases, these properties correspond to user variables in Org.  The
-first table below lists these properties along with the variable they belong
-to.  The second table list HTML specific properties.  See the documentation
-string of these options for details.
+The property list can be used to set export options during the publishing
+process.  In most cases, these properties correspond to user variables in
+Org.  While some properties are available for all export back-ends, most of
+them are back-end specific.  The following sections list properties along
+with the variable they belong to.  See the documentation string of these
+options for details.
 
address@hidden org-display-custom-times
address@hidden org-export-default-language
address@hidden org-export-exclude-tags
address@hidden org-export-headline-levels
address@hidden org-export-preserve-breaks
address@hidden org-export-publishing-directory
address@hidden org-export-select-tags
address@hidden org-export-with-archived-trees
address@hidden org-export-with-author
address@hidden org-export-with-creator
address@hidden org-export-with-drawers
address@hidden org-export-with-email
address@hidden org-export-with-emphasize
address@hidden org-export-with-fixed-width
address@hidden org-export-with-footnotes
address@hidden org-export-with-latex
address@hidden org-export-with-planning
address@hidden org-export-with-priority
address@hidden org-export-with-section-numbers
address@hidden org-export-with-special-strings
address@hidden org-export-with-sub-superscripts
address@hidden org-export-with-tables
address@hidden org-export-with-tags
address@hidden org-export-with-tasks
address@hidden org-export-with-timestamps
address@hidden org-export-with-toc
address@hidden org-export-with-todo-keywords
address@hidden user-mail-address
address@hidden org-publish-project-alist
+When a property is given a value in @code{org-publish-project-alist}, its
+setting overrides the value of the corresponding user variable (if any)
+during publishing.  Options set within a file (@pxref{Export settings}),
+however, override everything.
+
address@hidden Generic properties
 
address@hidden @columnfractions 0.32 0.68
address@hidden address@hidden:with-sub-superscript}}  address@hidden
 @item @code{:archived-trees}        @tab @code{org-export-with-archived-trees}
 @item @code{:exclude-tags}          @tab @code{org-export-exclude-tags}
 @item @code{:headline-levels}       @tab @code{org-export-headline-levels}
@@ -13671,7 +14389,10 @@ string of these options for details.
 @item @code{:section-numbers}       @tab @code{org-export-with-section-numbers}
 @item @code{:select-tags}           @tab @code{org-export-select-tags}
 @item @code{:with-author}           @tab @code{org-export-with-author}
address@hidden @code{:with-broken-links}     @tab 
@code{org-export-with-broken-links}
address@hidden @code{:with-clocks}           @tab @code{org-export-with-clocks}
 @item @code{:with-creator}          @tab @code{org-export-with-creator}
address@hidden @code{:with-date}             @tab @code{org-export-with-date}
 @item @code{:with-drawers}          @tab @code{org-export-with-drawers}
 @item @code{:with-email}            @tab @code{org-export-with-email}
 @item @code{:with-emphasize}        @tab @code{org-export-with-emphasize}
@@ -13680,83 +14401,225 @@ string of these options for details.
 @item @code{:with-latex}            @tab @code{org-export-with-latex}
 @item @code{:with-planning}         @tab @code{org-export-with-planning}
 @item @code{:with-priority}         @tab @code{org-export-with-priority}
address@hidden @code{:with-properties}       @tab 
@code{org-export-with-properties}
 @item @code{:with-special-strings}  @tab @code{org-export-with-special-strings}
 @item @code{:with-sub-superscript}  @tab 
@code{org-export-with-sub-superscripts}
 @item @code{:with-tables}           @tab @code{org-export-with-tables}
 @item @code{:with-tags}             @tab @code{org-export-with-tags}
 @item @code{:with-tasks}            @tab @code{org-export-with-tasks}
 @item @code{:with-timestamps}       @tab @code{org-export-with-timestamps}
address@hidden @code{:with-title}            @tab @code{org-export-with-title}
 @item @code{:with-toc}              @tab @code{org-export-with-toc}
 @item @code{:with-todo-keywords}    @tab @code{org-export-with-todo-keywords}
 @end multitable
 
address@hidden org-html-doctype
address@hidden org-html-container-element
address@hidden org-html-html5-fancy
address@hidden org-html-xml-declaration
address@hidden org-html-link-up
address@hidden org-html-link-home
address@hidden org-html-link-org-files-as-html
address@hidden org-html-link-use-abs-url
address@hidden org-html-head
address@hidden org-html-head-extra
address@hidden org-html-inline-images
address@hidden org-html-extension
address@hidden org-html-preamble
address@hidden org-html-postamble
address@hidden org-html-table-default-attributes
address@hidden org-html-table-row-tags
address@hidden org-html-head-include-default-style
address@hidden org-html-head-include-scripts
address@hidden @columnfractions 0.32 0.68
address@hidden @code{:html-doctype}          @tab @code{org-html-doctype}
address@hidden @code{:html-container}        @tab 
@code{org-html-container-element}
address@hidden @code{:html-html5-fancy}      @tab @code{org-html-html5-fancy}
address@hidden @code{:html-xml-declaration}  @tab 
@code{org-html-xml-declaration}
address@hidden @code{:html-link-up}          @tab @code{org-html-link-up}
address@hidden @code{:html-link-home}        @tab @code{org-html-link-home}
address@hidden @code{:html-link-org-as-html} @tab 
@code{org-html-link-org-files-as-html}
address@hidden @code{:html-link-use-abs-url} @tab 
@code{org-html-link-use-abs-url}
address@hidden @code{:html-head}             @tab @code{org-html-head}
address@hidden @code{:html-head-extra}       @tab @code{org-html-head-extra}
address@hidden @code{:html-inline-images}    @tab @code{org-html-inline-images}
address@hidden @code{:html-extension}        @tab @code{org-html-extension}
address@hidden @code{:html-preamble}         @tab @code{org-html-preamble}
address@hidden @code{:html-postamble}        @tab @code{org-html-postamble}
address@hidden @code{:html-table-attributes} @tab 
@code{org-html-table-default-attributes}
address@hidden @code{:html-table-row-tags}   @tab @code{org-html-table-row-tags}
address@hidden ASCII specific properties
+
address@hidden address@hidden:ascii-table-keep-all-vertical-lines}} 
address@hidden
address@hidden @code{:ascii-bullets}                       @tab 
@code{org-ascii-bullets}
address@hidden @code{:ascii-caption-above}                 @tab 
@code{org-ascii-caption-above}
address@hidden @code{:ascii-charset}                       @tab 
@code{org-ascii-charset}
address@hidden @code{:ascii-global-margin}                 @tab 
@code{org-ascii-global-margin}
address@hidden @code{:ascii-format-drawer-function}        @tab 
@code{org-ascii-format-drawer-function}
address@hidden @code{:ascii-format-inlinetask-function}    @tab 
@code{org-ascii-format-inlinetask-function}
address@hidden @code{:ascii-headline-spacing}              @tab 
@code{org-ascii-headline-spacing}
address@hidden @code{:ascii-indented-line-width}           @tab 
@code{org-ascii-indented-line-width}
address@hidden @code{:ascii-inlinetask-width}              @tab 
@code{org-ascii-inlinetask-width}
address@hidden @code{:ascii-inner-margin}                  @tab 
@code{org-ascii-inner-margin}
address@hidden @code{:ascii-links-to-notes}                @tab 
@code{org-ascii-links-to-notes}
address@hidden @code{:ascii-list-margin}                   @tab 
@code{org-ascii-list-margin}
address@hidden @code{:ascii-paragraph-spacing}             @tab 
@code{org-ascii-paragraph-spacing}
address@hidden @code{:ascii-quote-margin}                  @tab 
@code{org-ascii-quote-margin}
address@hidden @code{:ascii-table-keep-all-vertical-lines} @tab 
@code{org-ascii-table-keep-all-vertical-lines}
address@hidden @code{:ascii-table-use-ascii-art}           @tab 
@code{org-ascii-table-use-ascii-art}
address@hidden @code{:ascii-table-widen-columns}           @tab 
@code{org-ascii-table-widen-columns}
address@hidden @code{:ascii-text-width}                    @tab 
@code{org-ascii-text-width}
address@hidden @code{:ascii-underline}                     @tab 
@code{org-ascii-underline}
address@hidden @code{:ascii-verbatim-format}               @tab 
@code{org-ascii-verbatim-format}
address@hidden multitable
+
address@hidden Beamer specific properties
+
address@hidden address@hidden:beamer-frame-default-options}} address@hidden
address@hidden @code{:beamer-theme}                 @tab @code{org-beamer-theme}
address@hidden @code{:beamer-column-view-format}    @tab 
@code{org-beamer-column-view-format}
address@hidden @code{:beamer-environments-extra}    @tab 
@code{org-beamer-environments-extra}
address@hidden @code{:beamer-frame-default-options} @tab 
@code{org-beamer-frame-default-options}
address@hidden @code{:beamer-outline-frame-options} @tab 
@code{org-beamer-outline-frame-options}
address@hidden @code{:beamer-outline-frame-title}   @tab 
@code{org-beamer-outline-frame-title}
address@hidden @code{:beamer-subtitle-format}       @tab 
@code{org-beamer-subtitle-format}
address@hidden multitable
+
address@hidden HTML specific properties
+
address@hidden address@hidden:html-table-use-header-tags-for-first-column}} 
address@hidden
address@hidden @code{:html-allow-name-attribute-in-anchors} @tab 
@code{org-html-allow-name-attribute-in-anchors}
address@hidden @code{:html-checkbox-type}              @tab 
@code{org-html-checkbox-type}
address@hidden @code{:html-container}                  @tab 
@code{org-html-container-element}
address@hidden @code{:html-divs}                       @tab @code{org-html-divs}
address@hidden @code{:html-doctype}                    @tab 
@code{org-html-doctype}
address@hidden @code{:html-extension}                  @tab 
@code{org-html-extension}
address@hidden @code{:html-footnote-format}            @tab 
@code{org-html-footnote-format}
address@hidden @code{:html-footnote-separator}         @tab 
@code{org-html-footnote-separator}
address@hidden @code{:html-footnotes-section}          @tab 
@code{org-html-footnotes-section}
address@hidden @code{:html-format-drawer-function}     @tab 
@code{org-html-format-drawer-function}
address@hidden @code{:html-format-headline-function}   @tab 
@code{org-html-format-headline-function}
address@hidden @code{:html-format-inlinetask-function} @tab 
@code{org-html-format-inlinetask-function}
address@hidden @code{:html-head-extra}                 @tab 
@code{org-html-head-extra}
 @item @code{:html-head-include-default-style} @tab 
@code{org-html-head-include-default-style}
address@hidden @code{:html-head-include-scripts} @tab 
@code{org-html-head-include-scripts}
address@hidden @code{:html-head-include-scripts}       @tab 
@code{org-html-head-include-scripts}
address@hidden @code{:html-head}                       @tab @code{org-html-head}
address@hidden @code{:html-home/up-format}             @tab 
@code{org-html-home/up-format}
address@hidden @code{:html-html5-fancy}                @tab 
@code{org-html-html5-fancy}
address@hidden @code{:html-indent}                     @tab 
@code{org-html-indent}
address@hidden @code{:html-infojs-options}             @tab 
@code{org-html-infojs-options}
address@hidden @code{:html-infojs-template}            @tab 
@code{org-html-infojs-template}
address@hidden @code{:html-inline-image-rules}         @tab 
@code{org-html-inline-image-rules}
address@hidden @code{:html-inline-images}              @tab 
@code{org-html-inline-images}
address@hidden @code{:html-link-home}                  @tab 
@code{org-html-link-home}
address@hidden @code{:html-link-org-files-as-html}     @tab 
@code{org-html-link-org-files-as-html}
address@hidden @code{:html-link-up}                    @tab 
@code{org-html-link-up}
address@hidden @code{:html-link-use-abs-url}           @tab 
@code{org-html-link-use-abs-url}
address@hidden @code{:html-mathjax-options}            @tab 
@code{org-html-mathjax-options}
address@hidden @code{:html-mathjax-template}           @tab 
@code{org-html-mathjax-template}
address@hidden @code{:html-metadata-timestamp-format}  @tab 
@code{org-html-metadata-timestamp-format}
address@hidden @code{:html-postamble-format}           @tab 
@code{org-html-postamble-format}
address@hidden @code{:html-postamble}                  @tab 
@code{org-html-postamble}
address@hidden @code{:html-preamble-format}            @tab 
@code{org-html-preamble-format}
address@hidden @code{:html-preamble}                   @tab 
@code{org-html-preamble}
address@hidden @code{:html-table-align-individual-fields} @tab 
@code{org-html-table-align-individual-fields}
address@hidden @code{:html-table-attributes}           @tab 
@code{org-html-table-default-attributes}
address@hidden @code{:html-table-caption-above}        @tab 
@code{org-html-table-caption-above}
address@hidden @code{:html-table-data-tags}            @tab 
@code{org-html-table-data-tags}
address@hidden @code{:html-table-header-tags}          @tab 
@code{org-html-table-header-tags}
address@hidden @code{:html-table-row-tags}             @tab 
@code{org-html-table-row-tags}
address@hidden @code{:html-table-use-header-tags-for-first-column} @tab 
@code{org-html-table-use-header-tags-for-first-column}
address@hidden @code{:html-tag-class-prefix}           @tab 
@code{org-html-tag-class-prefix}
address@hidden @code{:html-text-markup-alist}          @tab 
@code{org-html-text-markup-alist}
address@hidden @code{:html-todo-kwd-class-prefix}      @tab 
@code{org-html-todo-kwd-class-prefix}
address@hidden @code{:html-toplevel-hlevel}            @tab 
@code{org-html-toplevel-hlevel}
address@hidden @code{:html-use-infojs}                 @tab 
@code{org-html-use-infojs}
address@hidden @code{:html-validation-link}            @tab 
@code{org-html-validation-link}
address@hidden @code{:html-viewport}                   @tab 
@code{org-html-viewport}
address@hidden @code{:html-xml-declaration}            @tab 
@code{org-html-xml-declaration}
 @end multitable
 
-Most of the @code{org-export-with-*} variables have the same effect in each
-exporter.
address@hidden @LaTeX{} specific properties
+
address@hidden address@hidden:latex-link-with-unknown-path-format}} 
address@hidden
address@hidden @code{:latex-active-timestamp-format}    @tab 
@code{org-latex-active-timestamp-format}
address@hidden @code{:latex-caption-above}              @tab 
@code{org-latex-caption-above}
address@hidden @code{:latex-classes}                    @tab 
@code{org-latex-classes}
address@hidden @code{:latex-class}                      @tab 
@code{org-latex-default-class}
address@hidden @code{:latex-compiler}                   @tab 
@code{org-latex-compiler}
address@hidden @code{:latex-default-figure-position}    @tab 
@code{org-latex-default-figure-position}
address@hidden @code{:latex-default-table-environment}  @tab 
@code{org-latex-default-table-environment}
address@hidden @code{:latex-default-table-mode}         @tab 
@code{org-latex-default-table-mode}
address@hidden @code{:latex-diary-timestamp-format}     @tab 
@code{org-latex-diary-timestamp-format}
address@hidden @code{:latex-footnote-defined-format}    @tab 
@code{org-latex-footnote-defined-format}
address@hidden @code{:latex-footnote-separator}         @tab 
@code{org-latex-footnote-separator}
address@hidden @code{:latex-format-drawer-function}     @tab 
@code{org-latex-format-drawer-function}
address@hidden @code{:latex-format-headline-function}   @tab 
@code{org-latex-format-headline-function}
address@hidden @code{:latex-format-inlinetask-function} @tab 
@code{org-latex-format-inlinetask-function}
address@hidden @code{:latex-hyperref-template}          @tab 
@code{org-latex-hyperref-template}
address@hidden @code{:latex-image-default-height}       @tab 
@code{org-latex-image-default-height}
address@hidden @code{:latex-image-default-option}       @tab 
@code{org-latex-image-default-option}
address@hidden @code{:latex-image-default-width}        @tab 
@code{org-latex-image-default-width}
address@hidden @code{:latex-images-centered}            @tab 
@code{org-latex-images-centered}
address@hidden @code{:latex-inactive-timestamp-format}  @tab 
@code{org-latex-inactive-timestamp-format}
address@hidden @code{:latex-inline-image-rules}         @tab 
@code{org-latex-inline-image-rules}
address@hidden @code{:latex-link-with-unknown-path-format} @tab 
@code{org-latex-link-with-unknown-path-format}
address@hidden @code{:latex-listings-langs}             @tab 
@code{org-latex-listings-langs}
address@hidden @code{:latex-listings-options}           @tab 
@code{org-latex-listings-options}
address@hidden @code{:latex-listings}                   @tab 
@code{org-latex-listings}
address@hidden @code{:latex-minted-langs}               @tab 
@code{org-latex-minted-langs}
address@hidden @code{:latex-minted-options}             @tab 
@code{org-latex-minted-options}
address@hidden @code{:latex-prefer-user-labels}         @tab 
@code{org-latex-prefer-user-labels}
address@hidden @code{:latex-subtitle-format}            @tab 
@code{org-latex-subtitle-format}
address@hidden @code{:latex-subtitle-separate}          @tab 
@code{org-latex-subtitle-separate}
address@hidden @code{:latex-table-scientific-notation}  @tab 
@code{org-latex-table-scientific-notation}
address@hidden @code{:latex-tables-booktabs}            @tab 
@code{org-latex-tables-booktabs}
address@hidden @code{:latex-tables-centered}            @tab 
@code{org-latex-tables-centered}
address@hidden @code{:latex-text-markup-alist}          @tab 
@code{org-latex-text-markup-alist}
address@hidden @code{:latex-title-command}              @tab 
@code{org-latex-title-command}
address@hidden @code{:latex-toc-command}                @tab 
@code{org-latex-toc-command}
address@hidden multitable
 
address@hidden org-publish-project-alist
-When a property is given a value in @code{org-publish-project-alist}, its
-setting overrides the value of the corresponding user variable (if any)
-during publishing.  Options set within a file (@pxref{Export settings}),
-however, override everything.
address@hidden Markdown specific properties
+
address@hidden address@hidden:md-footnotes-section}} address@hidden
address@hidden @code{:md-footnote-format} @tab @code{org-md-footnote-format}
address@hidden @code{:md-footnotes-section} @tab @code{org-md-footnotes-section}
address@hidden @code{:md-headline-style} @tab @code{org-md-headline-style}
address@hidden multitable
+
address@hidden ODT specific properties
+
address@hidden address@hidden:odt-format-inlinetask-function}} address@hidden
address@hidden @code{:odt-content-template-file}      @tab 
@code{org-odt-content-template-file}
address@hidden @code{:odt-display-outline-level}      @tab 
@code{org-odt-display-outline-level}
address@hidden @code{:odt-fontify-srcblocks}          @tab 
@code{org-odt-fontify-srcblocks}
address@hidden @code{:odt-format-drawer-function}     @tab 
@code{org-odt-format-drawer-function}
address@hidden @code{:odt-format-headline-function}   @tab 
@code{org-odt-format-headline-function}
address@hidden @code{:odt-format-inlinetask-function} @tab 
@code{org-odt-format-inlinetask-function}
address@hidden @code{:odt-inline-formula-rules}       @tab 
@code{org-odt-inline-formula-rules}
address@hidden @code{:odt-inline-image-rules}         @tab 
@code{org-odt-inline-image-rules}
address@hidden @code{:odt-pixels-per-inch}            @tab 
@code{org-odt-pixels-per-inch}
address@hidden @code{:odt-styles-file}                @tab 
@code{org-odt-styles-file}
address@hidden @code{:odt-table-styles}               @tab 
@code{org-odt-table-styles}
address@hidden @code{:odt-use-date-fields}            @tab 
@code{org-odt-use-date-fields}
address@hidden multitable
+
address@hidden Texinfo specific properties
+
address@hidden address@hidden:texinfo-link-with-unknown-path-format}} 
address@hidden
address@hidden @code{:texinfo-active-timestamp-format}    @tab 
@code{org-texinfo-active-timestamp-format}
address@hidden @code{:texinfo-classes}                    @tab 
@code{org-texinfo-classes}
address@hidden @code{:texinfo-class}                      @tab 
@code{org-texinfo-default-class}
address@hidden @code{:texinfo-def-table-markup}           @tab 
@code{org-texinfo-def-table-markup}
address@hidden @code{:texinfo-diary-timestamp-format}     @tab 
@code{org-texinfo-diary-timestamp-format}
address@hidden @code{:texinfo-filename}                   @tab 
@code{org-texinfo-filename}
address@hidden @code{:texinfo-format-drawer-function}     @tab 
@code{org-texinfo-format-drawer-function}
address@hidden @code{:texinfo-format-headline-function}   @tab 
@code{org-texinfo-format-headline-function}
address@hidden @code{:texinfo-format-inlinetask-function} @tab 
@code{org-texinfo-format-inlinetask-function}
address@hidden @code{:texinfo-inactive-timestamp-format}  @tab 
@code{org-texinfo-inactive-timestamp-format}
address@hidden @code{:texinfo-link-with-unknown-path-format} @tab 
@code{org-texinfo-link-with-unknown-path-format}
address@hidden @code{:texinfo-node-description-column}    @tab 
@code{org-texinfo-node-description-column}
address@hidden @code{:texinfo-table-scientific-notation}  @tab 
@code{org-texinfo-table-scientific-notation}
address@hidden @code{:texinfo-tables-verbatim}            @tab 
@code{org-texinfo-tables-verbatim}
address@hidden @code{:texinfo-text-markup-alist}          @tab 
@code{org-texinfo-text-markup-alist}
address@hidden multitable
 
address@hidden Publishing links, Sitemap, Publishing options, Configuration
address@hidden Publishing links
 @subsection Links between published files
 @cindex links, publishing
 
 To create a link from one Org file to another, you would use something like
address@hidden:foo.org][The foo]]} or simply @samp{file:foo.org.}
-(@pxref{Hyperlinks}).  When published, this link becomes a link to
address@hidden  You can thus interlink the pages of your "org web" project
-and the links will work as expected when you publish them to address@hidden  
If you
-also publish the Org source file and want to link to it, use an @code{http:}
-link instead of a @code{file:} link, because @code{file:} links are converted
-to link to the corresponding @file{html} file.
address@hidden:foo.org][The foo]]} or simply @samp{file:foo.org}
+(@pxref{External links}).  When published, this link becomes a link to
address@hidden  You can thus interlink the pages of your ``org web''
+project and the links will work as expected when you publish them to HTML.
+If you also publish the Org source file and want to link to it, use an
address@hidden:} link instead of a @code{file:} link, because @code{file:} links
+are converted to link to the corresponding @file{html} file.
 
 You may also link to related files, such as images.  Provided you are careful
 with relative file names, and provided you have also configured Org to upload
 the related files, these links will work too.  See @ref{Complex example}, for
 an example of this usage.
 
address@hidden Sitemap, Generating an index, Publishing links, Configuration
+Eventually, links between published documents can contain some search options
+(@pxref{Search options}), which will be resolved to the appropriate location
+in the linked file.  For example, once published to HTML, the following links
+all point to a dedicated anchor in @file{foo.html}.
+
address@hidden
+[[file:foo.org::*heading]]
+[[file:foo.org::#custom-id]]
+[[file:foo.org::target]]
address@hidden example
+
address@hidden Sitemap
 @subsection Generating a sitemap
 @cindex sitemap, of published pages
 
@@ -13816,7 +14679,7 @@ Defaults to @code{nil}.
 
 @end multitable
 
address@hidden Generating an index,  , Sitemap, Configuration
address@hidden Generating an index
 @subsection Generating an index
 @cindex index, in a publishing project
 
@@ -13833,7 +14696,17 @@ The file will be created when first publishing a 
project with the
 "theindex.inc"}.  You can then build around this include statement by adding
 a title, style information, etc.
 
address@hidden Uploading files, Sample configuration, Configuration, Publishing
address@hidden #+INDEX
+Index entries are specified with @code{#+INDEX} keyword.  An entry that
+contains an exclamation mark will create a sub item.
+
address@hidden
+* Curriculum Vitae
+#+INDEX: CV
+#+INDEX: Application!CV
address@hidden example
+
address@hidden Uploading files
 @section Uploading files
 @cindex rsync
 @cindex unison
@@ -13866,7 +14739,7 @@ benefit of re-including any changed external files such 
as source example
 files you might include with @code{#+INCLUDE:}.  The timestamp mechanism in
 Org is not smart enough to detect if included files have been modified.
 
address@hidden Sample configuration, Triggering publication, Uploading files, 
Publishing
address@hidden Sample configuration
 @section Sample configuration
 
 Below we provide two example configurations.  The first one is a simple
@@ -13878,7 +14751,7 @@ more complex, with a multi-component project.
 * Complex example::             A multi-component publishing example
 @end menu
 
address@hidden Simple example, Complex example, Sample configuration, Sample 
configuration
address@hidden Simple example
 @subsection Example: simple publishing configuration
 
 This example publishes a set of Org files to the @file{public_html}
@@ -13896,7 +14769,7 @@ directory on the local machine.
                     type=\"text/css\"/>")))
 @end lisp
 
address@hidden Complex example,  , Simple example, Sample configuration
address@hidden Complex example
 @subsection Example: complex publishing configuration
 
 This more complicated example publishes an entire website, including
@@ -13946,7 +14819,7 @@ right place on the web server, and publishing images to 
it.
          ("website" :components ("orgfiles" "images" "other"))))
 @end lisp
 
address@hidden Triggering publication,  , Sample configuration, Publishing
address@hidden Triggering publication
 @section Triggering publication
 
 Once properly configured, Org can publish with the following commands:
@@ -13970,17 +14843,20 @@ above, or by customizing the variable 
@code{org-publish-use-timestamps-flag}.
 This may be necessary in particular if files include other files via
 @code{#+SETUPFILE:} or @code{#+INCLUDE:}.
 
address@hidden  node-name,  next,  previous,  up
address@hidden Working With Source Code, Miscellaneous, Publishing, Top
 
address@hidden Working With Source Code, Miscellaneous, Publishing, Top
address@hidden Working with source code
 @chapter Working with source code
 @cindex Schulte, Eric
 @cindex Davison, Dan
 @cindex source code, working with
 
-Source code can be included in Org mode documents using a @samp{src} block,
-e.g.:
+Source code here refers to any code typed in Org mode documents.  Org can
+manage source code in any Org file once such code is tagged with begin and
+end markers.  Working with source code begins with tagging source code
+blocks.  Tagged @samp{src} code blocks are not restricted to the preamble or
+the end of an Org document; they can go anywhere---with a few exceptions,
+such as not inside comments and fixed width areas.  Here's a sample
address@hidden code block in emacs-lisp:
 
 @example
 #+BEGIN_SRC emacs-lisp
@@ -13990,14 +14866,57 @@ e.g.:
 #+END_SRC
 @end example
 
-Org mode provides a number of features for working with live source code,
-including editing of code blocks in their native major-mode, evaluation of
-code blocks, converting code blocks into source files (known as @dfn{tangling}
-in literate programming), and exporting code blocks and their
-results in several formats.  This functionality was contributed by Eric
-Schulte and Dan Davison, and was originally named Org-babel.
-
-The following sections describe Org mode's code block handling facilities.
+Org can take the code in the block between the @samp{#+BEGIN_SRC} and
address@hidden tags, and format, compile, execute, and show the results.
+Org can simplify many housekeeping tasks essential to modern code
+maintenance.  That's why these blocks in Org mode literature are sometimes
+referred to as @samp{live code} blocks (as compared to the static text and
+documentation around it).  Users can control how @samp{live} they want each
+block by tweaking the headers for compiling, execution, extraction.
+
+Org's @samp{src} code block type is one of many block types, such as quote,
+export, verse, latex, example, and verbatim.  This section pertains to
address@hidden code blocks between @samp{#+BEGIN_SRC} and @samp{#+END_SRC}
+
+For editing @samp{src} code blocks, Org provides native Emacs major-modes.
+That leverages the latest Emacs features for that source code language mode.
+
+For exporting, Org can then extract @samp{src} code blocks into compilable
+source files (in a conversion process known as @dfn{tangling} in literate
+programming terminology).
+
+For publishing, Org's back-ends can handle the @samp{src} code blocks and the
+text for output to a variety of formats with native syntax highlighting.
+
+For executing the source code in the @samp{src} code blocks, Org provides
+facilities that glue the tasks of compiling, collecting the results of the
+execution, and inserting them back to the Org file.  Besides text output,
+results may include links to other data types that Emacs can handle: audio,
+video, and graphics.
+
+An important feature of Org's execution of the @samp{src} code blocks is
+passing variables, functions, and results between @samp{src} blocks.  Such
+interoperability uses a common syntax even if these @samp{src} blocks are in
+different source code languages.  The integration extends to linking the
+debugger's error messages to the line in the @samp{src} code block in the Org
+file.  That should partly explain why this functionality by the original
+contributors, Eric Schulte and Dan Davison, was called @samp{Org Babel}.
+
+In literate programming, the main appeal is code and documentation
+co-existing in one file.  Org mode takes this several steps further.  First
+by enabling execution, and then by inserting results of that execution back
+into the Org file.  Along the way, Org provides extensive formatting
+features, including handling tables.  Org handles multiple source code
+languages in one file, and provides a common syntax for passing variables,
+functions, and results between @samp{src} code blocks.
+
+Org mode fulfills the promise of easy verification and maintenance of
+publishing reproducible research by keeping all these in the same file: text,
+data, code, configuration settings of the execution environment, the results
+of the execution, and associated narratives, claims, references, and internal
+and external links.
+
+Details of Org's facilities for working with source code are shown next.
 
 @menu
 * Structure of code blocks::    Code block syntax described
@@ -14014,19 +14933,18 @@ The following sections describe Org mode's code block 
handling facilities.
 * Batch execution::             Call functions from the command line
 @end menu
 
address@hidden  node-name,  next,  previous,  up
address@hidden  Structure of code blocks, Editing source code, Working With 
Source Code, Working With Source Code
 
address@hidden Structure of code blocks, Editing source code, Working With 
Source Code, Working With Source Code
address@hidden Structure of code blocks
 @section Structure of code blocks
 @cindex code block, structure
 @cindex source code, block structure
 @cindex #+NAME
 @cindex #+BEGIN_SRC
 
-Live code blocks can be specified with a @samp{src} block or
address@hidden that @samp{src} blocks may be inserted using Org mode's
address@hidden Templates} system}  The structure of a @samp{src} block is
+Org offers two ways to structure source code in Org documents: in a
address@hidden block, and directly inline.  Both specifications are shown below.
+
+A @samp{src} block conforms to this structure:
 
 @example
 #+NAME: <name>
@@ -14035,12 +14953,15 @@ address@hidden that @samp{src} blocks may be inserted 
using Org mode's
 #+END_SRC
 @end example
 
-The @code{#+NAME:} line is optional, and can be used to name the code
-block.  Live code blocks require that a language be specified on the
address@hidden line.  Switches and header arguments are optional.
address@hidden source code, inline
+Org mode's templates system (@pxref{Easy templates}) speeds up creating
address@hidden code blocks with just three keystrokes.  Do not be put-off by
+having to remember the source block syntax.  Org also works with other
+completion systems in Emacs, some of which predate Org and have custom
+domain-specific languages for defining templates.  Regular use of templates
+reduces errors, increases accuracy, and maintains consistency.
 
-Live code blocks can also be specified inline using
address@hidden source code, inline
+An inline code block conforms to this structure:
 
 @example
 src_<language>@{<body>@}
@@ -14053,36 +14974,39 @@ src_<language>[<header 
arguments>address@hidden<body>@}
 @end example
 
 @table @code
address@hidden <#+NAME: name>
-This line associates a name with the code block.  This is similar to the
address@hidden: Name} lines that can be used to name tables in Org mode
-files.  Referencing the name of a code block makes it possible to evaluate
-the block from other places in the file, from other files, or from Org mode
-table formulas (see @ref{The spreadsheet}).  Names are assumed to be unique
-and the behavior of Org mode when two or more blocks share the same name is
-undefined.
address@hidden #+NAME: <name>
+Optional.  Names the @samp{src} block so it can be called, like a function,
+from other @samp{src} blocks or inline blocks to evaluate or to capture the
+results.  Code from other blocks, other files, and from table formulas
+(@pxref{The spreadsheet}) can use the name to reference a @samp{src} block.
+This naming serves the same purpose as naming Org tables.  Org mode requires
+unique names.  For duplicate names, Org mode's behavior is undefined.
 @cindex #+NAME
address@hidden #+BEGIN_SRC
address@hidden #+END_SRC
+Mandatory.  They mark the start and end of a block that Org requires.  The
address@hidden line takes additional arguments, as described next.
address@hidden begin block, end block
 @item <language>
-The language of the code in the block (see @ref{Languages}).
+Mandatory for live code blocks.  It is the identifier of the source code
+language in the block.  @xref{Languages}, for identifiers of supported
+languages.
 @cindex source code, language
 @item <switches>
-Optional switches control code block export (see the discussion of switches in
address@hidden examples})
+Optional.  Switches provide finer control of the code execution, export, and
+format (see the discussion of switches in @ref{Literal examples})
 @cindex source code, switches
 @item <header arguments>
-Optional header arguments control many aspects of evaluation, export and
-tangling of code blocks (see @ref{Header arguments}).
-Header arguments can also be set on a per-buffer or per-subtree
-basis using properties.
+Optional.  Heading arguments control many aspects of evaluation, export and
+tangling of code blocks (@pxref{Header arguments}).  Using Org's properties
+feature, header arguments can be selectively applied to the entire buffer or
+specific sub-trees of the Org document.
 @item source code, header arguments
 @item <body>
-Source code in the specified language.
+Source code in the dialect of the specified language identifier.
 @end table
 
address@hidden  node-name,  next,  previous,  up
address@hidden  Editing source code, Exporting code blocks, Structure of code 
blocks, Working With Source Code
-
address@hidden Editing source code, Exporting code blocks, Structure of code 
blocks, Working With Source Code
address@hidden Editing source code
 @section Editing source code
 @cindex code block, editing
 @cindex source code, editing
@@ -14090,116 +15014,150 @@ Source code in the specified language.
 @vindex org-edit-src-auto-save-idle-delay
 @vindex org-edit-src-turn-on-auto-save
 @kindex C-c '
-Use @kbd{C-c '} to edit the current code block.  This brings up a language
-major-mode edit buffer containing the body of the code block.  Manually
-saving this buffer with @key{C-x C-s} will write the contents back to the Org
-buffer.  You can also set @code{org-edit-src-auto-save-idle-delay} to save the
-base buffer after some idle delay, or @code{org-edit-src-turn-on-auto-save}
-to auto-save this buffer into a separate file using @code{auto-save-mode}.
-Use @kbd{C-c '} again to exit.
-
-The @code{org-src-mode} minor mode will be active in the edit buffer.  The
-following variables can be used to configure the behavior of the edit
-buffer.  See also the customization group @code{org-edit-structure} for
-further configuration options.
address@hidden '} for editing the current code block.  It opens a new major-mode
+edit buffer containing the body of the @samp{src} code block, ready for any
+edits.  @kbd{C-c '} again to close the buffer and return to the Org buffer.
+
address@hidden C-s} saves the buffer and updates the contents of the Org buffer.
+
+Set @code{org-edit-src-auto-save-idle-delay} to save the base buffer after
+a certain idle delay time.
+
+Set @code{org-edit-src-turn-on-auto-save} to auto-save this buffer into a
+separate file using @code{auto-save-mode}.
+
address@hidden '} to close the major-mode buffer and return back to the Org 
buffer.
+
+While editing the source code in the major-mode, the @code{org-src-mode}
+minor mode remains active.  It provides these customization variables as
+described below.  For even more variables, look in the customization
+group @code{org-edit-structure}.
 
 @table @code
 @item org-src-lang-modes
-If an Emacs major-mode named @code{<lang>-mode} exists, where
address@hidden<lang>} is the language named in the header line of the code 
block,
-then the edit buffer will be placed in that major-mode.  This variable
-can be used to map arbitrary language names to existing major modes.
+If an Emacs major-mode named @code{<lang>-mode} exists, where @code{<lang>}
+is the language identifier from code block's header line, then the edit
+buffer uses that major-mode.  Use this variable to arbitrarily map language
+identifiers to major modes.
 @item org-src-window-setup
-Controls the way Emacs windows are rearranged when the edit buffer is created.
+For specifying Emacs window arrangement when the new edit buffer is created.
 @item org-src-preserve-indentation
-By default, the value is @code{nil}, which means that when code blocks are
-evaluated during export or tangled, they are re-inserted into the code block,
-which may replace sequences of spaces with tab characters.  When non-nil,
-whitespace in code blocks will be preserved during export or tangling,
-exactly as it appears.  This variable is especially useful for tangling
-languages such as Python, in which whitespace indentation in the output is
-critical.
address@hidden indentation, in source blocks
+Default is @code{nil}.  Source code is indented.  This indentation applies
+during export or tangling, and depending on the context, may alter leading
+spaces and tabs.  When address@hidden, source code is aligned with the
+leftmost column.  No lines are modified during export or tangling, which is
+very useful for white-space sensitive languages, such as Python.
 @item org-src-ask-before-returning-to-edit-buffer
-By default, Org will ask before returning to an open edit buffer.  Set this
-variable to @code{nil} to switch without asking.
+When @code{nil}, Org returns to the edit buffer without further prompts.  The
+default prompts for a confirmation.
 @end table
 
-To turn on native code fontification in the @emph{Org} buffer, configure the
-variable @code{org-src-fontify-natively}.
+Set @code{org-src-fontify-natively} to address@hidden to turn on native code
+fontification in the @emph{Org} buffer.  Fontification of @samp{src} code
+blocks can give visual separation of text and code on the display page.  To
+further customize the appearance of @code{org-block} for specific languages,
+customize @code{org-src-block-faces}.  The following example shades the
+background of regular blocks, and colors source blocks only for Python and
+Emacs-Lisp languages.
address@hidden
+(require 'color)
+(set-face-attribute 'org-block nil :background
+                    (color-darken-name
+                     (face-attribute 'default :background) 3))
 
address@hidden  node-name,  next,  previous,  up
address@hidden  Exporting code blocks, Extracting source code, Editing source 
code, Working With Source Code
+(setq org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF"))
+                            ("python" (:background "#E5FFB8"))))
address@hidden lisp
 
address@hidden Exporting code blocks, Extracting source code, Editing source 
code, Working With Source Code
address@hidden Exporting code blocks
 @section Exporting code blocks
 @cindex code block, exporting
 @cindex source code, exporting
 
-It is possible to export the @emph{code} of code blocks, the @emph{results}
-of code block evaluation, @emph{both} the code and the results of code block
-evaluation, or @emph{none}.  For most languages, the default exports code.
-However, for some languages (e.g., @code{ditaa}) the default exports the
-results of code block evaluation.  For information on exporting code block
-bodies, see @ref{Literal examples}.
+Org can flexibly export just the @emph{code} from the code blocks, just the
address@hidden of evaluation of the code block, @emph{both} the code and the
+results of the code block evaluation, or @emph{none}.  Org defaults to
+exporting @emph{code} for most languages.  For some languages, such as
address@hidden, Org defaults to @emph{results}.  To export just the body of
+code blocks, @pxref{Literal examples}.  To selectively export sub-trees of
+an Org document, @pxref{Exporting}.
 
-The @code{:exports} header argument can be used to specify export
-behavior:
+The @code{:exports} header arguments control exporting code blocks only and
+not inline code:
 
 @subsubheading Header arguments:
 
 @table @code
address@hidden @code{:exports}, src header argument
 @item :exports code
-The default in most languages.  The body of the code block is exported, as
-described in @ref{Literal examples}.
+This is the default for most languages where the body of the code block is
+exported.  See @ref{Literal examples} for more.
 @item :exports results
-The code block will be evaluated and the results will be placed in the
-Org mode buffer for export, either updating previous results of the code
-block located anywhere in the buffer or, if no previous results exist,
-placing the results immediately after the code block.  The body of the code
-block will not be exported.
+On export, Org includes only the results and not the code block.  After each
+evaluation, Org inserts the results after the end of code block in the Org
+buffer.  By default, Org replaces any previous results.  Org can also append
+results.
 @item :exports both
-Both the code block and its results will be exported.
+Org exports both the code block and the results.
 @item :exports none
-Neither the code block nor its results will be exported.
+Org does not export the code block nor the results.
 @end table
 
-It is possible to inhibit the evaluation of code blocks during export.
-Setting the @code{org-export-babel-evaluate} variable to @code{nil} will
-ensure that no code blocks are evaluated as part of the export process.  This
-can be useful in situations where potentially untrusted Org mode files are
-exported in an automated fashion, for example when Org mode is used as the
-markup language for a wiki.  It is also possible to set this variable to
address@hidden'inline-only}.  In that case, only inline code blocks will be
-evaluated, in order to insert their results.  Non-inline code blocks are
-assumed to have their results already inserted in the buffer by manual
-evaluation.  This setting is useful to avoid expensive recalculations during
-export, not to provide security.
-
address@hidden  node-name,  next,  previous,  up
address@hidden  Extracting source code, Evaluating code blocks, Exporting code 
blocks, Working With Source Code
address@hidden Extracting source code, Evaluating code blocks, Exporting code 
blocks, Working With Source Code
address@hidden org-export-babel-evaluate
+To stop Org from evaluating code blocks during export, set
address@hidden variable to @code{nil}.
+
+Turning off evaluation comes in handy when batch processing.  For example,
+markup languages for wikis, which have a high risk of untrusted code.
+Stopping code block evaluation also stops evaluation of all header arguments
+of the code block.  This may not be desirable in some circumstances.  So
+during export, to allow evaluation of just the header arguments but not any
+code evaluation in the source block, set @code{:eval never-export}
+(@pxref{eval}).
+
+To evaluate just the inline code blocks, set @code{org-export-babel-evaluate}
+to @code{inline-only}.  Isolating the option to allow inline evaluations
+separate from @samp{src} code block evaluations during exports is not for
+security but for avoiding any delays due to recalculations, such as calls to
+a remote database.
+
+Org never evaluates code blocks in commented sub-trees when exporting
+(@pxref{Comment lines}).  On the other hand, Org does evaluate code blocks in
+sub-trees excluded from export (@pxref{Export settings}).
+
address@hidden Extracting source code
 @section Extracting source code
 @cindex tangling
 @cindex source code, extracting
 @cindex code block, extracting source code
 
-Creating pure source code files by extracting code from source blocks is
-referred to as ``tangling''---a term adopted from the literate programming
-community.  During ``tangling'' of code blocks their bodies are expanded
-using @code{org-babel-expand-src-block} which can expand both variable and
-``noweb'' style references  (see @ref{Noweb reference syntax}).
+Extracting source code from code blocks is a basic task in literate
+programming.  Org has features to make this easy.  In literate programming
+parlance, documents on creation are @emph{woven} with code and documentation,
+and on export, the code is @emph{tangled} for execution by a computer.  Org
+facilitates weaving and tangling for producing, maintaining, sharing, and
+exporting literate programming documents.  Org provides extensive
+customization options for extracting source code.
+
+When Org tangles @samp{src} code blocks, it expands, merges, and transforms
+them.  Then Org recomposes them into one or more separate files, as
+configured through the options.  During this @emph{tangling} process, Org
+expands variables in the source code, and resolves any ``noweb'' style
+references (@pxref{Noweb reference syntax}).
 
 @subsubheading Header arguments
 
 @table @code
address@hidden @code{:tangle}, src header argument
 @item :tangle no
-The default.  The code block is not included in the tangled output.
+By default, Org does not tangle the @samp{src} code block on export.
 @item :tangle yes
-Include the code block in the tangled output.  The output file name is the
-name of the org file with the extension @samp{.org} replaced by the extension
-for the block language.
+Org extracts the contents of the code block for the tangled output.  By
+default, the output file name is the same as the Org file but with a file
+extension derived from the language identifier of the @samp{src} code block.
 @item :tangle filename
-Include the code block in the tangled output to file @samp{filename}.
+Override the default file name with this one for the tangled output.
 @end table
 
 @kindex  C-c C-v t
@@ -14209,7 +15167,7 @@ Include the code block in the tangled output to file 
@samp{filename}.
 @item org-babel-tangle
 Tangle the current file.  Bound to @kbd{C-c C-v t}.
 
-With prefix argument only tangle the current code block.
+With prefix argument only tangle the current @samp{src} code block.
 @item org-babel-tangle-file
 Choose a file to tangle.  Bound to @kbd{C-c C-v f}.
 @end table
@@ -14218,72 +15176,67 @@ Choose a file to tangle.  Bound to @kbd{C-c C-v f}.
 
 @table @code
 @item org-babel-post-tangle-hook
-This hook is run from within code files tangled by @code{org-babel-tangle}.
-Example applications could include post-processing, compilation or evaluation
-of tangled code files.
+This hook runs from within code tangled by @code{org-babel-tangle}, making it
+suitable for post-processing, compilation, and evaluation of code in the
+tangled files.
 @end table
 
 @subsubheading Jumping between code and Org
 
-When tangling code from an Org-mode buffer to a source code file, you'll
-frequently find yourself viewing the file of tangled source code (e.g., many
-debuggers point to lines of the source code file).  It is useful to be able
-to navigate from the tangled source to the Org-mode buffer from which the
-code originated.
+Debuggers normally link errors and messages back to the source code.  But for
+tangled files, we want to link back to the Org file, not to the tangled
+source file.  To make this extra jump, Org uses
address@hidden function with two additional source code
+block header arguments: One, set @code{padline} (@pxref{padline}) to true
+(the default setting).  Two, set @code{comments} (@pxref{comments}) to
address@hidden, which makes Org insert links to the Org file.
 
-The @code{org-babel-tangle-jump-to-org} function provides this jumping from
-code to Org-mode functionality.  Two header arguments are required for
-jumping to work, first the @code{padline} (@ref{padline}) option must be set
-to true (the default setting), second the @code{comments} (@ref{comments})
-header argument must be set to @code{links}, which will insert comments into
-the source code buffer which point back to the original Org-mode file.
-
address@hidden Evaluating code blocks, Library of Babel, Extracting source 
code, Working With Source Code
address@hidden Evaluating code blocks
 @section Evaluating code blocks
 @cindex code block, evaluating
 @cindex source code, evaluating
 @cindex #+RESULTS
 
-Code blocks can be address@hidden code is evaluated there is a
-potential for that code to do harm.  Org mode provides safeguards to ensure
-that code is only evaluated after explicit confirmation from the user.  For
-information on these safeguards (and on how to disable them) see @ref{Code
-evaluation security}.} and the results of evaluation optionally placed in the
-Org mode buffer.  The results of evaluation are placed following a line that
-begins by default with @code{#+RESULTS} and optionally a cache identifier
-and/or the name of the evaluated code block.  The default value of
address@hidden can be changed with the customizable variable
address@hidden
-
-By default, the evaluation facility is only enabled for Lisp code blocks
-specified as @code{emacs-lisp}.  However, source code blocks in many languages
-can be evaluated within Org mode (see @ref{Languages} for a list of supported
-languages and @ref{Structure of code blocks} for information on the syntax
-used to define a code block).
+A note about security: With code evaluation comes the risk of harm.  Org
+safeguards by prompting for user's permission before executing any code in
+the source block.  To customize this safeguard (or disable it) see @ref{Code
+evaluation security}.
+
+Org captures the results of the @samp{src} code block evaluation and inserts
+them in the Org file, right after the @samp{src} code block.  The insertion
+point is after a newline and the @code{#+RESULTS} label.  Org creates the
address@hidden label if one is not already there.
+
+By default, Org enables only @code{emacs-lisp} @samp{src} code blocks for
+execution.  See @ref{Languages} for identifiers to enable other languages.
 
 @kindex C-c C-c
-There are a number of ways to evaluate code blocks.  The simplest is to press
address@hidden C-c} or @kbd{C-c C-v e} with the point on a code address@hidden
-option @code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used to remove code
-evaluation from the @kbd{C-c C-c} key binding.}.  This will call the
address@hidden function to evaluate the block and insert
-its results into the Org mode buffer.
address@hidden #+CALL
+Org provides many ways to execute @samp{src} code blocks.  @kbd{C-c C-c} or
address@hidden C-v e} with the point on a @samp{src} code address@hidden option
address@hidden can be used to remove code
+evaluation from the @kbd{C-c C-c} key binding.} calls the
address@hidden function, which executes the code in the
+block, collects the results, and inserts them in the buffer.
 
-It is also possible to evaluate named code blocks from anywhere in an Org
-mode buffer or an Org mode table.  Live code blocks located in the current
-Org mode buffer or in the ``Library of Babel'' (see @ref{Library of Babel})
-can be executed.  Named code blocks can be executed with a separate
address@hidden:} line or inline within a block of text.
address@hidden #+CALL
+By calling a named code address@hidden, the constructs call_<name>()
+and src_<lang>@address@hidden are not evaluated when they appear in a keyword 
line
+(i.e. lines starting with @code{#+KEYWORD:}, @pxref{In-buffer settings}).}
+from an Org mode buffer or a table.  Org can call the named @samp{src} code
+blocks from the current Org mode buffer or from the ``Library of Babel''
+(@pxref{Library of Babel}).  Whether inline syntax or the @code{#+CALL:}
+syntax is used, the result is wrapped based on the variable
address@hidden, which by default is set to @code{"=%s="}
+to produce verbatim text suitable for markup.
 
-The syntax of the @code{#+CALL:} line is
+The syntax for @code{#+CALL:} is
 
 @example
 #+CALL: <name>(<arguments>)
 #+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments>
 @end example
 
-The syntax for inline evaluation of named code blocks is
+The syntax for inline named code block is
 
 @example
 ... call_<name>(<arguments>) ...
@@ -14292,98 +15245,88 @@ The syntax for inline evaluation of named code blocks 
is
 
 @table @code
 @item <name>
-The name of the code block to be evaluated (see @ref{Structure of code 
blocks}).
+This is the name of the code block to be evaluated (@pxref{Structure of
+code blocks}).
 @item <arguments>
-Arguments specified in this section will be passed to the code block.  These
-arguments use standard function call syntax, rather than
-header argument syntax.  For example, a @code{#+CALL:} line that passes the
-number four to a code block named @code{double}, which declares the header
-argument @code{:var n=2}, would be written as @code{#+CALL: double(n=4)}.
+Org passes arguments to the code block using standard function call syntax.
+For example, a @code{#+CALL:} line that passes @samp{4} to a code block named
address@hidden, which declares the header argument @code{:var n=2}, would be
+written as @code{#+CALL: double(n=4)}.  Note how this function call syntax is
+different from the header argument syntax.
 @item <inside header arguments>
-Inside header arguments are passed through and applied to the named code
-block.  These arguments use header argument syntax rather than standard
-function call syntax.  Inside header arguments affect how the code block is
-evaluated.  For example, @code{[:results output]} will collect the results of
-everything printed to @code{STDOUT} during execution of the code block.
+Org passes inside header arguments to the named @samp{src} code block using
+the header argument syntax.  Inside header arguments apply to code block
+evaluation.  For example, @code{[:results output]} collects results printed
+to @code{STDOUT} during code execution of that block.  Note how this header
+argument syntax is different from the function call syntax.
 @item <end header arguments>
-End header arguments are applied to the calling instance and do not affect
-evaluation of the named code block.  They affect how the results are
-incorporated into the Org mode buffer and how the call line is exported.  For
-example, @code{:results html} will insert the results of the call line
-evaluation in the Org buffer, wrapped in a @code{BEGIN_HTML:} block.
-
-For more examples of passing header arguments to @code{#+CALL:} lines see
address@hidden arguments in function calls}.
+End header arguments affect the results returned by the code block.  For
+example, @code{:results html} wraps the results in a @code{BEGIN_EXPORT html}
+block before inserting the results in the Org buffer.
+
+For more examples of header arguments for @code{#+CALL:} lines,
address@hidden in function calls}.
 @end table
 
address@hidden Library of Babel, Languages, Evaluating code blocks, Working 
With Source Code
address@hidden Library of Babel
 @section Library of Babel
 @cindex babel, library of
 @cindex source code, library
 @cindex code block, library
 
-The ``Library of Babel'' consists of code blocks that can be called from any
-Org mode file.  Code blocks defined in the ``Library of Babel'' can be called
-remotely as if they were in the current Org mode buffer (see @ref{Evaluating
-code blocks} for information on the syntax of remote code block evaluation).
-
-
-The central repository of code blocks in the ``Library of Babel'' is housed
-in an Org mode file located in the @samp{contrib} directory of Org mode.
-
-Users can add code blocks they believe to be generally useful to their
-``Library of Babel.''  The code blocks can be stored in any Org mode file and
-then loaded into the library with @code{org-babel-lob-ingest}.
-
+The ``Library of Babel'' is a collection of code blocks.  Like a function
+library, these code blocks can be called from other Org files.  This
+collection is in a repository file in Org mode format in the @samp{doc}
+directory of Org mode installation.  For remote code block evaluation syntax,
address@hidden code blocks}.
 
 @kindex C-c C-v i
-Code blocks located in any Org mode file can be loaded into the ``Library of
-Babel'' with the @code{org-babel-lob-ingest} function, bound to @kbd{C-c C-v
-i}.
+For any user to add code to the library, first save the code in regular
address@hidden code blocks of an Org file, and then load the Org file with
address@hidden, which is bound to @kbd{C-c C-v i}.
 
address@hidden Languages, Header arguments, Library of Babel, Working With 
Source Code
address@hidden Languages
 @section Languages
 @cindex babel, languages
 @cindex source code, languages
 @cindex code block, languages
 
-Code blocks in the following languages are supported.
+Org supports the following languages for the @samp{src} code blocks:
 
address@hidden @columnfractions 0.28 0.3 0.22 0.2
address@hidden @b{Language} @tab @b{Identifier} @tab @b{Language} @tab 
@b{Identifier}
address@hidden @columnfractions 0.25 0.25 0.25 0.25
address@hidden @b{Language} @tab @b{Identifier} @tab @b{Language} @tab 
@b{Identifier}
 @item Asymptote @tab asymptote @tab Awk @tab awk
address@hidden Emacs Calc @tab calc @tab C @tab C
address@hidden C++ @tab C++ @tab Clojure @tab clojure
address@hidden CSS @tab css @tab ditaa @tab ditaa
address@hidden Graphviz @tab dot @tab Emacs Lisp @tab emacs-lisp
address@hidden C @tab C @tab C++ @tab C++
address@hidden Clojure @tab clojure @tab CSS @tab css
address@hidden D @tab d @tab ditaa @tab ditaa
address@hidden Graphviz @tab dot @tab Emacs Calc @tab calc
address@hidden Emacs Lisp @tab emacs-lisp @tab Fortran @tab fortran
 @item gnuplot @tab gnuplot @tab Haskell @tab haskell
address@hidden Java @tab java @tab @tab
address@hidden Javascript @tab js @tab LaTeX @tab latex
address@hidden Ledger @tab ledger @tab Lisp @tab lisp
address@hidden Lilypond @tab lilypond @tab MATLAB @tab matlab
address@hidden Java @tab java @tab Javascript @tab js
address@hidden LaTeX @tab latex @tab Ledger @tab ledger
address@hidden Lisp @tab lisp @tab Lilypond @tab lilypond
address@hidden Lua @tab lua @tab MATLAB @tab matlab
 @item Mscgen @tab mscgen @tab Objective Caml @tab ocaml
 @item Octave @tab octave @tab Org mode @tab org
 @item Oz @tab oz @tab Perl @tab perl
address@hidden Plantuml @tab plantuml @tab Python @tab python
address@hidden R @tab R @tab Ruby @tab ruby
address@hidden Sass @tab sass @tab Scheme @tab scheme
address@hidden GNU Screen @tab screen @tab shell @tab sh
address@hidden Plantuml @tab plantuml @tab Processing.js @tab processing
address@hidden Python @tab python @tab R @tab R
address@hidden Ruby @tab ruby @tab Sass @tab sass
address@hidden Scheme @tab scheme @tab GNU Screen @tab screen
address@hidden Sed @tab sed @tab shell @tab sh
 @item SQL @tab sql @tab SQLite @tab sqlite
 @end multitable
 
-Language-specific documentation is available for some languages.  If
-available, it can be found at
+Additional documentation for some languages are at
 @uref{http://orgmode.org/worg/org-contrib/babel/languages.html}.
 
-The option @code{org-babel-load-languages} controls which languages are
-enabled for evaluation (by default only @code{emacs-lisp} is enabled).  This
-variable can be set using the customization interface or by adding code like
-the following to your emacs configuration.
+By default, only @code{emacs-lisp} is enabled for evaluation.  To enable or
+disable other languages, customize the @code{org-babel-load-languages}
+variable either through the Emacs customization interface, or by adding code
+to the init file as shown next:
 
address@hidden
-The following disables @code{emacs-lisp} evaluation and enables evaluation of
address@hidden code blocks.
address@hidden quotation
+In this example, evaluation is disabled for @code{emacs-lisp}, and enabled
+for @code{R}.
 
 @lisp
 (org-babel-do-load-languages
@@ -14392,55 +15335,54 @@ The following disables @code{emacs-lisp} evaluation 
and enables evaluation of
    (R . t)))
 @end lisp
 
-It is also possible to enable support for a language by loading the related
-elisp file with @code{require}.
-
address@hidden
-The following adds support for evaluating @code{clojure} code blocks.
address@hidden quotation
+Note that this is not the only way to enable a language.  Org also enables
+languages when loaded with @code{require} statement.  For example, the
+following enables execution of @code{clojure} code blocks:
 
 @lisp
 (require 'ob-clojure)
 @end lisp
 
address@hidden Header arguments, Results of evaluation, Languages, Working With 
Source Code
address@hidden Header arguments
 @section Header arguments
 @cindex code block, header arguments
 @cindex source code, block header arguments
 
-Code block functionality can be configured with header arguments.  This
-section provides an overview of the use of header arguments, and then
-describes each header argument in detail.
+Details of configuring header arguments are shown here.
 
 @menu
 * Using header arguments::      Different ways to set header arguments
 * Specific header arguments::   List of header arguments
 @end menu
 
address@hidden Using header arguments, Specific header arguments, Header 
arguments, Header arguments
address@hidden Using header arguments
 @subsection Using header arguments
 
-The values of header arguments can be set in several way.  When the header
-arguments in each layer have been determined, they are combined in order from
-the first, least specific (having the lowest priority) up to the last, most
-specific (having the highest priority).  A header argument with a higher
-priority replaces the same header argument specified at lower priority.
+Since header arguments can be set in several ways, Org prioritizes them in
+case of overlaps or conflicts by giving local settings a higher priority.
+Header values in function calls, for example, override header values from
+global defaults.
 @menu
-* System-wide header arguments::  Set global default values
-* Language-specific header arguments::  Set default values by language
-* Header arguments in Org mode properties::  Set default values for a buffer 
or heading
-* Language-specific header arguments in Org mode properties::  Set 
language-specific default values for a buffer or heading
-* Code block specific header arguments::  The most common way to set values
-* Header arguments in function calls::  The most specific level
+* System-wide header arguments::  Set globally, language-specific
+* Language-specific header arguments::  Set in the Org file's headers
+* Header arguments in Org mode properties::  Set in the Org file
+* Language-specific mode properties::
+* Code block specific header arguments::  The most commonly used method
+* Arguments in function calls::  The most specific level, takes highest 
priority
 @end menu
 
 
address@hidden System-wide header arguments, Language-specific header 
arguments, Using header arguments, Using header arguments
address@hidden System-wide header arguments
 @subsubheading System-wide header arguments
 @vindex org-babel-default-header-args
 System-wide values of header arguments can be specified by adapting the
 @code{org-babel-default-header-args} variable:
 
address@hidden @code{:session}, src header argument
address@hidden @code{:results}, src header argument
address@hidden @code{:exports}, src header argument
address@hidden @code{:cache}, src header argument
address@hidden @code{:noweb}, src header argument
 @example
 :session    => "none"
 :results    => "replace"
@@ -14449,10 +15391,8 @@ System-wide values of header arguments can be 
specified by adapting the
 :noweb      => "no"
 @end example
 
-For example, the following example could be used to set the default value of
address@hidden:noweb} header arguments to @code{yes}.  This would have the 
effect of
-expanding @code{:noweb} references by default when evaluating source code
-blocks.
+This example sets @code{:noweb} header arguments to @code{yes}, which makes
+Org expand @code{:noweb} references by default.
 
 @lisp
 (setq org-babel-default-header-args
@@ -14460,48 +15400,40 @@ blocks.
             (assq-delete-all :noweb org-babel-default-header-args)))
 @end lisp
 
address@hidden Language-specific header arguments, Header arguments in Org mode 
properties, System-wide header arguments, Using header arguments
address@hidden Language-specific header arguments
 @subsubheading Language-specific header arguments
-Each language can define its own set of default header arguments in variable
address@hidden:<lang>}, where @code{<lang>} is the name
-of the language.  See the language-specific documentation available online at
address@hidden://orgmode.org/worg/org-contrib/babel}.
+Each language can have separate default header arguments by customizing the
+variable @code{org-babel-default-header-args:<lang>}, where @code{<lang>} is
+the name of the language.  For details, see the language-specific online
+documentation at @uref{http://orgmode.org/worg/org-contrib/babel}.
 
address@hidden Header arguments in Org mode properties, Language-specific 
header arguments in Org mode properties, Language-specific header arguments, 
Using header arguments
address@hidden Header arguments in Org mode properties
 @subsubheading Header arguments in Org mode properties
 
-Buffer-wide header arguments may be specified as properties through the use
-of @code{#+PROPERTY:} lines placed anywhere in an Org mode file (see
address@hidden syntax}).
+For header arguments applicable to the buffer, use @code{#+PROPERTY:} lines
+anywhere in the Org mode file (@pxref{Property syntax}).
 
-For example the following would set @code{session} to @code{*R*} (only for R
-code blocks), and @code{results} to @code{silent} for every code block in the
-buffer, ensuring that all execution took place in the same session, and no
-results would be inserted into the buffer.
+The following example sets only for @samp{R} code blocks to @code{session},
+making all the @samp{R} code blocks execute in the same session.  Setting
address@hidden to @code{silent} ignores the results of executions for all
+blocks, not just @samp{R} code blocks; no results inserted for any block.
 
 @example
 #+PROPERTY: header-args:R  :session *R*
 #+PROPERTY: header-args    :results silent
 @end example
 
-Header arguments read from Org mode properties can also be set on a
-per-subtree basis using property drawers (see @ref{Property syntax}).
 @vindex org-use-property-inheritance
-When properties are used to set default header arguments, they are always
-looked up with inheritance, regardless of the value of
address@hidden  Properties are evaluated as seen by the
-outermost call or source address@hidden deprecated syntax for default
-header argument properties, using the name of the header argument as a
-property name directly, evaluates the property as seen by the corresponding
-source block definition.  This behavior has been kept for backwards
-compatibility.}
+Header arguments set through Org's property drawers (@pxref{Property syntax})
+apply at the sub-tree level on down.  Since these property drawers can appear
+anywhere in the file hierarchy, Org uses outermost call or source block to
+resolve the values.  Org ignores @code{org-use-property-inheritance} setting.
 
-In the following example the value of
-the @code{:cache} header argument will default to @code{yes} in all code
-blocks in the subtree rooted at the following heading:
+In this example, @code{:cache} defaults to @code{yes} for all code blocks in
+the sub-tree starting with @samp{sample header}.
 
 @example
-* outline header
+* sample header
   :PROPERTIES:
   :header-args:    :cache yes
   :END:
@@ -14509,17 +15441,16 @@ blocks in the subtree rooted at the following heading:
 
 @kindex C-c C-x p
 @vindex org-babel-default-header-args
-Properties defined in this way override the properties set in
address@hidden and are applied for all activated
-languages.  It is convenient to use the @code{org-set-property} function
-bound to @kbd{C-c C-x p} to set properties in Org mode documents.
+Properties defined through @code{org-set-property} function, bound to
address@hidden C-x p}, apply to all active languages.  They override properties 
set
+in @code{org-babel-default-header-args}.
 
address@hidden Language-specific header arguments in Org mode properties, Code 
block specific header arguments, Header arguments in Org mode properties, Using 
header arguments
address@hidden Language-specific header arguments in Org mode properties
address@hidden Language-specific mode properties
address@hidden Language-specific mode properties
 
 Language-specific header arguments are also read from properties
address@hidden:<lang>} where @code{<lang>} is the name of the language
-targeted.  As an example
address@hidden:<lang>} where @code{<lang>} is the language identifier.
+For example,
 
 @example
 * Heading
@@ -14533,24 +15464,21 @@ targeted.  As an example
   :END:
 @end example
 
-would independently set a default session header argument for R and clojure
-for calls and source blocks under subtree ``Heading'' and change to a
-different clojure setting for evaluations under subtree ``Subheading'', while
-the R session is inherited from ``Heading'' and therefore unchanged.
+would force separate sessions for clojure blocks in Heading and Subheading,
+but use the same session for all @samp{R} blocks.  Blocks in Subheading
+inherit settings from Heading.
 
address@hidden Code block specific header arguments, Header arguments in 
function calls, Language-specific header arguments in Org mode properties, 
Using header arguments
address@hidden Code block specific header arguments
 @subsubheading Code block specific header arguments
 
-The most common way to assign values to header arguments is at the
-code block level.  This can be done by listing a sequence of header
-arguments and their values as part of the @code{#+BEGIN_SRC} line.
-Properties set in this way override both the values of
address@hidden and header arguments specified as
-properties.  In the following example, the @code{:results} header argument
-is set to @code{silent}, meaning the results of execution will not be
-inserted in the buffer, and the @code{:exports} header argument is set to
address@hidden, meaning only the body of the code block will be
-preserved on export to HTML or @LaTeX{}.
+Header arguments are most commonly set at the @samp{src} code block level, on
+the @code{#+BEGIN_SRC} line.  Arguments set at this level take precedence
+over those set in the @code{org-babel-default-header-args} variable, and also
+those set as header properties.
+
+In the following example, setting @code{results} to @code{silent} makes it
+ignore results of the code execution.  Setting @code{:exports} to @code{code}
+exports only the body of the @samp{src} code block to HTML or @LaTeX{}.:
 
 @example
 #+NAME: factorial
@@ -14559,93 +15487,93 @@ fac 0 = 1
 fac n = n * fac (n-1)
 #+END_SRC
 @end example
-Similarly, it is possible to set header arguments for inline code blocks
+
+The same header arguments in an inline @samp{src} code block:
 
 @example
 src_haskell[:exports address@hidden address@hidden
 @end example
 
-Code block header arguments can span multiple lines using @code{#+HEADER:} or
address@hidden:} lines preceding a code block or nested between the
address@hidden:} line and the @code{#+BEGIN_SRC} line of a named code block.
+Code block header arguments can span multiple lines using @code{#+HEADER:} on
+each line.  Note that Org currently accepts the plural spelling of
address@hidden:} only as a convenience for backward-compatibility.  It may be
+removed at some point.
+
 @cindex #+HEADER:
address@hidden #+HEADERS:
 
-Multi-line header arguments on an un-named code block:
+Multi-line header arguments on an unnamed @samp{src} code block:
 
 @example
- #+HEADERS: :var data1=1
- #+BEGIN_SRC emacs-lisp :var data2=2
+#+HEADER: :var data1=1
+#+BEGIN_SRC emacs-lisp :var data2=2
    (message "data1:%S, data2:%S" data1 data2)
- #+END_SRC
+#+END_SRC
 
- #+RESULTS:
- : data1:1, data2:2
+#+RESULTS:
+: data1:1, data2:2
 @end example
 
-Multi-line header arguments on a named code block:
+Multi-line header arguments on a named @samp{src} code block:
 
 @example
-   #+NAME: named-block
-   #+HEADER: :var data=2
-   #+BEGIN_SRC emacs-lisp
-     (message "data:%S" data)
-   #+END_SRC
+#+NAME: named-block
+#+HEADER: :var data=2
+#+BEGIN_SRC emacs-lisp
+  (message "data:%S" data)
+#+END_SRC
 
-   #+RESULTS: named-block
-   : data:2
+#+RESULTS: named-block
+  : data:2
 @end example
 
address@hidden Header arguments in function calls,  , Code block specific 
header arguments, Using header arguments
address@hidden  node-name,  next,  previous,  up
address@hidden Header arguments in function calls
address@hidden Arguments in function calls
address@hidden Arguments in function calls
 
-At the most specific level, header arguments for ``Library of Babel'' or
address@hidden:} lines can be set as shown in the two examples below.  For more
-information on the structure of @code{#+CALL:} lines see @ref{Evaluating code
-blocks}.
+Header arguments in function calls are the most specific and override all
+other settings in case of an overlap.  They get the highest priority.  Two
address@hidden:} examples are shown below.  For the complete syntax of
address@hidden:} lines, see @ref{Evaluating code blocks}.
 
-The following will apply the @code{:exports results} header argument to the
+In this example, @code{:exports results} header argument is applied to the
 evaluation of the @code{#+CALL:} line.
 
 @example
 #+CALL: factorial(n=5) :exports results
 @end example
 
-The following will apply the @code{:session special} header argument to the
-evaluation of the @code{factorial} code block.
+In this example, @code{:session special} header argument is applied to the
+evaluation of @code{factorial} code block.
 
 @example
 #+CALL: factorial[:session special](n=5)
 @end example
 
address@hidden Specific header arguments,  , Using header arguments, Header 
arguments
address@hidden Specific header arguments
 @subsection Specific header arguments
-Header arguments consist of an initial colon followed by the name of the
-argument in lowercase letters.  The following header arguments are defined:
+Org comes with many header arguments common to all languages.  New header
+arguments are added for specific languages as they become available for use
+in @samp{src} code blocks.  A header argument is specified with an initial
+colon followed by the argument's name in lowercase.  Common header arguments
+are:
 
 @menu
-* var::                         Pass arguments to code blocks
-* results::                     Specify the type of results and how they will
-                                be collected and handled
-* file::                        Specify a path for file output
+* var::                         Pass arguments to @samp{src} code blocks
+* results::                     Specify results type; how to collect
+* file::                        Specify a path for output file
 * file-desc::                   Specify a description for file results
-* dir::                         Specify the default (possibly remote)
-                                directory for code block execution
-* exports::                     Export code and/or results
-* tangle::                      Toggle tangling and specify file name
-* mkdirp::                      Toggle creation of parent directories of target
-                                files during tangling
-* comments::                    Toggle insertion of comments in tangled
-                                code files
-* padline::                     Control insertion of padding lines in tangled
-                                code files
-* no-expand::                   Turn off variable assignment and noweb
-                                expansion during tangling
+* file-ext::                    Specify an extension for file output
+* output-dir::                  Specify a directory for output file
+* dir::                         Specify the default directory for code block 
execution
+* exports::                     Specify exporting code, results, both, none
+* tangle::                      Toggle tangling; or specify file name
+* mkdirp::                      Toggle for parent directory creation for 
target files during tangling
+* comments::                    Toggle insertion of comments in tangled code 
files
+* padline::                     Control insertion of padding lines in tangled 
code files
+* no-expand::                   Turn off variable assignment and noweb 
expansion during tangling
 * session::                     Preserve the state of code evaluation
 * noweb::                       Toggle expansion of noweb references
 * noweb-ref::                   Specify block's noweb reference resolution 
target
-* noweb-sep::                   String used to separate noweb references
+* noweb-sep::                   String to separate noweb references
 * cache::                       Avoid re-evaluating unchanged code blocks
 * sep::                         Delimiter for writing tabular results outside 
Org
 * hlines::                      Handle horizontal lines in tables
@@ -14655,45 +15583,46 @@ argument in lowercase letters.  The following header 
arguments are defined:
 * tangle-mode::                 Set permission of tangled files
 * eval::                        Limit evaluation of specific code blocks
 * wrap::                        Mark source block evaluation results
-* post::                        Post processing of code block results
-* prologue::                    Text to prepend to code block body
-* epilogue::                    Text to append to code block body
+* post::                        Post processing of results of code block 
evaluation
+* prologue::                    Text to prepend to body of code block
+* epilogue::                    Text to append to body of code block
 @end menu
 
-Additional header arguments are defined on a language-specific basis, see
address@hidden
+For language-specific header arguments, see @ref{Languages}.
 
address@hidden var, results, Specific header arguments, Specific header 
arguments
address@hidden var
 @subsubsection @code{:var}
-The @code{:var} header argument is used to pass arguments to code blocks.
-The specifics of how arguments are included in a code block vary by language;
-these are addressed in the language-specific documentation.  However, the
-syntax used to specify arguments is the same across all languages.  In every
-case, variables require a default value when they are declared.
address@hidden @code{:var}, src header argument
+Use @code{:var} for passing arguments to @samp{src} code blocks.  The
+specifics of variables in @samp{src} code blocks vary by the source language
+and are covered in the language-specific documentation.  The syntax for
address@hidden:var}, however, is the same for all languages.  This includes 
declaring
+a variable, and assigning a default value.
 
-The values passed to arguments can either be literal values, references, or
-Emacs Lisp code (see @ref{var, Emacs Lisp evaluation of variables}).
-References include anything in the Org mode file that takes a @code{#+NAME:}
-or @code{#+RESULTS:} line: tables, lists, @code{#+BEGIN_EXAMPLE} blocks,
-other code blocks and the results of other code blocks.
+Arguments can take values as literals, or as references, or even as Emacs
+Lisp code (@pxref{var, Emacs Lisp evaluation of variables}).  References are
+names from the Org file from the lines @code{#+NAME:} or @code{#+RESULTS:}.
+References can also refer to tables, lists, @code{#+BEGIN_EXAMPLE} blocks,
+other types of @samp{src} code blocks, or the results of execution of
address@hidden code blocks.
 
-Note: When a reference is made to another code block, the referenced block
-will be evaluated unless it has current cached results (see @ref{cache}).
+For better performance, Org can cache results of evaluations.  But caching
+comes with severe limitations (@pxref{cache}).
 
-Argument values can be indexed in a manner similar to arrays (see @ref{var,
-Indexable variable values}).
+Argument values are indexed like arrays (@pxref{var, Indexable variable
+values}).
 
-The following syntax is used to pass arguments to code blocks using the
address@hidden:var} header argument.
+The following syntax is used to pass arguments to @samp{src} code blocks
+using the @code{:var} header argument.
 
 @example
 :var name=assign
 @end example
 
-The argument, @code{assign}, can either be a literal value, such as a string
address@hidden"string"} or a number @samp{9}, or a reference to a table, a 
list, a
-literal example, another code block (with or without arguments), or the
-results of evaluating another code block.
+The @code{assign} is a literal value, such as a string @samp{"string"}, a
+number @samp{9}, a reference to a table, a list, a literal example, another
+code block (with or without arguments), or the results from evaluating a code
+block.
 
 Here are examples of passing values by reference:
 
@@ -14719,8 +15648,8 @@ an Org mode table named with either a @code{#+NAME:} 
line
 @end example
 
 @item list
-a simple list named with a @code{#+NAME:} line (note that nesting is not
-carried through to the source code block)
+a simple list named with a @code{#+NAME:} line.  Note that only the top level
+list items are passed along.  Nested list items are ignored.
 
 @example
 #+NAME: example-list
@@ -14751,9 +15680,9 @@ optionally followed by parentheses
 @end example
 
 @item code block with arguments
-a code block name, as assigned by @code{#+NAME:}, followed by parentheses and
-optional arguments passed within the parentheses following the
-code block name using standard function call syntax
+a @samp{src} code block name, as assigned by @code{#+NAME:}, followed by
+parentheses and optional arguments passed within the parentheses following
+the @samp{src} code block name using standard function call syntax
 
 @example
 #+NAME: double
@@ -14765,7 +15694,7 @@ code block name using standard function call syntax
 : 16
 
 #+NAME: squared
-#+BEGIN_SRC emacs-lisp :var input=double(input=1)
+#+BEGIN_SRC emacs-lisp :var input=double(input=2)
 (* input input)
 #+END_SRC
 
@@ -14797,14 +15726,14 @@ on two lines
 @end table
 
 @subsubheading Indexable variable values
-It is possible to reference portions of variable values by ``indexing'' into
-the variables.  Indexes are 0 based with negative values counting back from
-the end.  If an index is separated by @code{,}s then each subsequent section
-will index into the next deepest nesting or dimension of the value.  Note
-that this indexing occurs @emph{before} other table related header arguments
-like @code{:hlines}, @code{:colnames} and @code{:rownames} are applied.  The
-following example assigns the last cell of the first row the table
address@hidden to the variable @code{data}:
+Indexing variable values enables referencing portions of a variable.  Indexes
+are 0 based with negative values counting backwards from the end.  If an
+index is separated by @code{,}s then each subsequent section will index as
+the next dimension.  Note that this indexing occurs @emph{before} other
+table-related header arguments are applied, such as @code{:hlines},
address@hidden:colnames} and @code{:rownames}.  The following example assigns 
the
+last cell of the first row the table @code{example-table} to the variable
address@hidden:
 
 @example
 #+NAME: example-table
@@ -14844,10 +15773,9 @@ to @code{data}.
 | 4 | d |
 @end example
 
-Additionally, an empty index, or the single character @code{*}, are both
-interpreted to mean the entire range and as such are equivalent to
address@hidden:-1}, as shown in the following example in which the entire first
-column is referenced.
+To pick the entire range, use an empty index, or the single character
address@hidden  @code{0:-1} does the same thing.  Example below shows how to
+reference the first column only.
 
 @example
 #+NAME: example-table
@@ -14864,9 +15792,9 @@ column is referenced.
 | 1 | 2 | 3 | 4 |
 @end example
 
-It is possible to index into the results of code blocks as well as tables.
-Any number of dimensions can be indexed.  Dimensions are separated from one
-another by commas, as shown in the following example.
+Index referencing can be used for tables and code blocks.  Index referencing
+can handle any number of dimensions.  Commas delimit multiple dimensions, as
+shown below.
 
 @example
 #+NAME: 3D
@@ -14886,14 +15814,13 @@ another by commas, as shown in the following example.
 
 @subsubheading Emacs Lisp evaluation of variables
 
-Emacs lisp code can be used to initialize variable values.  When a variable
-value starts with @code{(}, @code{[}, @code{'} or @code{`} it will be
-evaluated as Emacs Lisp and the result of the evaluation will be assigned as
-the variable value.  The following example demonstrates use of this
-evaluation to reliably pass the file-name of the Org mode buffer to a code
-block---note that evaluation of header arguments is guaranteed to take place
-in the original Org mode file, while there is no such guarantee for
-evaluation of the code block body.
+Emacs lisp code can set the values for variables.  To differentiate a value
+from lisp code, Org interprets any value starting with @code{(}, @code{[},
address@hidden'} or @code{`} as Emacs Lisp code.  The result of evaluating that 
code
+is then assigned to the value of that variable.  The following example shows
+how to reliably query and pass file name of the Org mode buffer to a code
+block using headers.  We need reliability here because the file's name could
+change once the code in the block starts executing.
 
 @example
 #+BEGIN_SRC sh :var filename=(buffer-file-name) :exports both
@@ -14901,14 +15828,14 @@ evaluation of the code block body.
 #+END_SRC
 @end example
 
-Note that values read from tables and lists will not be evaluated as
-Emacs Lisp, as shown in the following example.
+Note that values read from tables and lists will not be mistakenly evaluated
+as Emacs Lisp code, as illustrated in the following example.
 
 @example
 #+NAME: table
 | (a b c) |
 
-#+HEADERS: :var data=table[0,0]
+#+HEADER: :var data=table[0,0]
 #+BEGIN_SRC perl
   $data
 #+END_SRC
@@ -14917,167 +15844,171 @@ Emacs Lisp, as shown in the following example.
 : (a b c)
 @end example
 
address@hidden results, file, var, Specific header arguments
address@hidden results
 @subsubsection @code{:results}
address@hidden @code{:results}, src header argument
 
-There are four classes of @code{:results} header argument.  Only one option
-per class may be supplied per code block.
+There are four classes of @code{:results} header arguments.  Each @samp{src}
+code block can take only one option per class.
 
 @itemize @bullet
 @item
address@hidden header arguments specify how the results should be collected
-from the code block
address@hidden for how the results should be collected from the @samp{src}
+code block
 @item
address@hidden header arguments specify what type of result the code block will
-return---which has implications for how they will be processed before
-insertion into the Org mode buffer
address@hidden for which type of result the code block will return; affects how 
Org
+processes and inserts results in the Org buffer
 @item
address@hidden header arguments specify what type of result the code block will
-return---which has implications for how they will be inserted into the
-Org mode buffer
address@hidden for the result; affects how Org processes and inserts results in
+the Org buffer
 @item
address@hidden header arguments specify how the results of evaluating the code
-block should be handled.
address@hidden for processing results after evaluation of the @samp{src} code
+block
 @end itemize
 
 @subsubheading Collection
-The following options are mutually exclusive, and specify how the results
-should be collected from the code block.
+Collection options specify the results.  Choose one of the options; they are
+mutually exclusive.
 
 @itemize @bullet
 @item @code{value}
-This is the default.  The result is the value of the last statement in the
-code block.  This header argument places the evaluation in functional
-mode.  Note that in some languages, e.g., Python, use of this result type
-requires that a @code{return} statement be included in the body of the source
-code block.  E.g., @code{:results value}.
+Default.  Functional mode.  Result is the value returned by the last
+statement in the @samp{src} code block.  Languages like Python may require an
+explicit @code{return} statement in the @samp{src} code block.  Usage
+example: @code{:results value}.
 @item @code{output}
-The result is the collection of everything printed to STDOUT during the
-execution of the code block.  This header argument places the
-evaluation in scripting mode.  E.g., @code{:results output}.
+Scripting mode.  Result is collected from STDOUT during execution of the code
+in the @samp{src} code block.  Usage example: @code{:results output}.
 @end itemize
 
 @subsubheading Type
-
-The following options are mutually exclusive and specify what type of results
-the code block will return.  By default, results are inserted as either a
-table or scalar depending on their value.
+Type tells what result types to expect from the execution of the code
+block.  Choose one of the options; they are mutually exclusive.  The default
+behavior is to automatically determine the result type.
 
 @itemize @bullet
 @item @code{table}, @code{vector}
-The results should be interpreted as an Org mode table.  If a single value is
-returned, it will be converted into a table with one row and one column.
-E.g., @code{:results value table}.
+Interpret the results as an Org table.  If the result is a single value,
+create a table with one row and one column.  Usage example: @code{:results
+value table}.
 @item @code{list}
-The results should be interpreted as an Org mode list.  If a single scalar
-value is returned it will be converted into a list with only one element.
+Interpret the results as an Org list.  If the result is a single value,
+create a list of one element.
 @item @code{scalar}, @code{verbatim}
-The results should be interpreted literally---they will not be
-converted into a table.  The results will be inserted into the Org mode
-buffer as quoted text.  E.g., @code{:results value verbatim}.
+Interpret literally and insert as quoted text.  Do not create a table.  Usage
+example: @code{:results value verbatim}.
 @item @code{file}
-The results will be interpreted as the path to a file, and will be inserted
-into the Org mode buffer as a file link.  E.g., @code{:results value file}.
+Interpret as path to a file.  Inserts a link to the file.  Usage example:
address@hidden:results value file}.
 @end itemize
 
 @subsubheading Format
-
-The following options are mutually exclusive and specify what type of results
-the code block will return.  By default, results are inserted according to the
-type as specified above.
+Format pertains to the type of the result returned by the @samp{src} code
+block.  Choose one of the options; they are mutually exclusive.  The default
+follows from the type specified above.
 
 @itemize @bullet
 @item @code{raw}
-The results are interpreted as raw Org mode code and are inserted directly
-into the buffer.  If the results look like a table they will be aligned as
-such by Org mode.  E.g., @code{:results value raw}.
+Interpreted as raw Org mode.  Inserted directly into the buffer.  Aligned if
+it is a table.  Usage example: @code{:results value raw}.
 @item @code{org}
-The results are will be enclosed in a @code{BEGIN_SRC org} block.
-They are not comma-escaped by default but they will be if you hit @kbd{TAB}
-in the block and/or if you export the file.  E.g., @code{:results value org}.
+Results enclosed in a @code{BEGIN_SRC org} block.  For comma-escape, either
address@hidden in the block, or export the file.  Usage example: @code{:results
+value org}.
 @item @code{html}
-Results are assumed to be HTML and will be enclosed in a @code{BEGIN_HTML}
-block.  E.g., @code{:results value html}.
+Results enclosed in a @code{BEGIN_EXPORT html} block.  Usage example:
address@hidden:results value html}.
 @item @code{latex}
-Results assumed to be @LaTeX{} and are enclosed in a @code{BEGIN_LaTeX} block.
-E.g., @code{:results value latex}.
+Results enclosed in a @code{BEGIN_EXPORT latex} block.  Usage example:
address@hidden:results value latex}.
 @item @code{code}
-Result are assumed to be parsable code and are enclosed in a code block.
-E.g., @code{:results value code}.
+Result enclosed in a @samp{src} code block.  Useful for parsing.  Usage
+example: @code{:results value code}.
 @item @code{pp}
-The result is converted to pretty-printed code and is enclosed in a code
-block.  This option currently supports Emacs Lisp, Python, and Ruby.  E.g.,
+Result converted to pretty-print source code.  Enclosed in a @samp{src} code
+block.  Languages supported: Emacs Lisp, Python, and Ruby.  Usage example:
 @code{:results value pp}.
 @item @code{drawer}
-The result is wrapped in a RESULTS drawer.  This can be useful for
-inserting @code{raw} or @code{org} syntax results in such a way that their
-extent is known and they can be automatically removed or replaced.
+Result wrapped in a RESULTS drawer.  Useful for containing @code{raw} or
address@hidden results for later scripting and automated processing.  Usage
+example: @code{:results value drawer}.
 @end itemize
 
 @subsubheading Handling
-The following results options indicate what happens with the
-results once they are collected.
+Handling options after collecting the results.
 
 @itemize @bullet
 @item @code{silent}
-The results will be echoed in the minibuffer but will not be inserted into
-the Org mode buffer.  E.g., @code{:results output silent}.
+Do not insert results in the Org mode buffer, but echo them in the
+minibuffer.  Usage example: @code{:results output silent}.
 @item @code{replace}
-The default value.  Any existing results will be removed, and the new results
-will be inserted into the Org mode buffer in their place.  E.g.,
address@hidden:results output replace}.
+Default.  Insert results in the Org buffer.  Remove previous results.  Usage
+example: @code{:results output replace}.
 @item @code{append}
-If there are pre-existing results of the code block then the new results will
-be appended to the existing results.  Otherwise the new results will be
-inserted as with @code{replace}.
+Append results to the Org buffer.  Latest results are at the bottom.  Does
+not remove previous results.  Usage example: @code{:results output append}.
 @item @code{prepend}
-If there are pre-existing results of the code block then the new results will
-be prepended to the existing results.  Otherwise the new results will be
-inserted as with @code{replace}.
+Prepend results to the Org buffer.  Latest results are at the top.  Does not
+remove previous results.  Usage example: @code{:results output prepend}.
 @end itemize
 
address@hidden file, file-desc, results, Specific header arguments
address@hidden file
 @subsubsection @code{:file}
address@hidden @code{:file}, src header argument
+
+An external @code{:file} that saves the results of execution of the code
+block.  The @code{:file} is either a file name or two strings, where the
+first is the file name and the second is the description.  A link to the file
+is inserted.  It uses an Org mode style @code{[[file:]]} link (@pxref{Link
+format}).  Some languages, such as @samp{R}, @samp{dot}, @samp{ditaa}, and
address@hidden, automatically wrap the source code in additional boilerplate
+code.  Such code wrapping helps recreate the output, especially graphics
+output, by executing just the @code{:file} contents.
+
address@hidden file-desc
address@hidden @code{:file-desc}
 
-The header argument @code{:file} is used to specify an external file in which
-to save code block results.  After code block evaluation an Org mode style
address@hidden:]]} link (see @ref{Link format}) to the file will be inserted
-into the Org mode buffer.  Some languages including R, gnuplot, dot, and
-ditaa provide special handling of the @code{:file} header argument
-automatically wrapping the code block body in the boilerplate code required
-to save output to the specified file.  This is often useful for saving
-graphical output of a code block to the specified file.
+A description of the results file.  Org uses this description for the link
+(see @ref{Link format}) it inserts in the Org file.  If the @code{:file-desc}
+has no value, Org will use file name for both the ``link'' and the
+``description'' portion of the Org mode link.
 
-The argument to @code{:file} should be either a string specifying the path to
-a file, or a list of two strings in which case the first element of the list
-should be the path to a file and the second a description for the link.
address@hidden file-ext
address@hidden @code{:file-ext}
address@hidden @code{:file-ext}, src header argument
 
address@hidden file-desc, dir, file, Specific header arguments
address@hidden @code{:file-desc}
+File name extension for the output file.  Org generates the file's complete
+name, and extension by combining @code{:file-ext}, @code{#+NAME:} of the
+source block, and the @ref{output-dir} header argument.  To override this
+auto generated file name, use the @code{:file} header argument.
 
-The value of the @code{:file-desc} header argument is used to provide a
-description for file code block results which are inserted as Org mode links
-(see @ref{Link format}).  If the @code{:file-desc} header argument is given
-with no value the link path will be placed in both the ``link'' and the
-``description'' portion of the Org mode link.
address@hidden output-dir
address@hidden @code{:output-dir}
address@hidden @code{:output-dir}, src header argument
 
address@hidden dir, exports, file-desc, Specific header arguments
+Specifies the @code{:output-dir} for the results file.  Org accepts an
+absolute path (beginning with @code{/}) or a relative directory (without
address@hidden/}).  The value can be combined with @code{#+NAME:} of the source 
block
+and @ref{file} or @ref{file-ext} header arguments.
+
address@hidden dir
 @subsubsection @code{:dir} and remote execution
address@hidden @code{:dir}, src header argument
 
 While the @code{:file} header argument can be used to specify the path to the
-output file, @code{:dir} specifies the default directory during code block
-execution.  If it is absent, then the directory associated with the current
-buffer is used.  In other words, supplying @code{:dir path} temporarily has
-the same effect as changing the current directory with @kbd{M-x cd path RET}, 
and
-then not supplying @code{:dir}.  Under the surface, @code{:dir} simply sets
-the value of the Emacs variable @code{default-directory}.
+output file, @code{:dir} specifies the default directory during @samp{src}
+code block execution.  If it is absent, then the directory associated with
+the current buffer is used.  In other words, supplying @code{:dir path}
+temporarily has the same effect as changing the current directory with
address@hidden cd path RET}, and then not supplying @code{:dir}.  Under the
+surface, @code{:dir} simply sets the value of the Emacs variable
address@hidden
 
-When using @code{:dir}, you should supply a relative path for file output
-(e.g., @code{:file myfile.jpg} or @code{:file results/myfile.jpg}) in which
-case that path will be interpreted relative to the default directory.
+When using @code{:dir}, relative paths (for example, @code{:file myfile.jpg}
+or @code{:file results/myfile.jpg}) become relative to the default directory.
 
-In other words, if you want your plot to go into a folder called @file{Work}
-in your home directory, you could use
+For example, to save the plot file in the @samp{Work} folder of the home
+directory (notice tilde is expanded):
 
 @example
 #+BEGIN_SRC R :file myplot.png :dir ~/Work
@@ -15086,8 +16017,8 @@ matplot(matrix(rnorm(100), 10), type="l")
 @end example
 
 @subsubheading Remote execution
-A directory on a remote machine can be specified using tramp file syntax, in
-which case the code will be evaluated on the remote machine.  An example is
+To evaluate the @samp{src} code block on a remote machine, supply a remote s
+directory name using @samp{Tramp} syntax.  For example:
 
 @example
 #+BEGIN_SRC R :file plot.png :dir /scp:dand@@yakuba.princeton.edu:
@@ -15095,189 +16026,196 @@ plot(1:10, main=system("hostname", intern=TRUE))
 #+END_SRC
 @end example
 
-Text results will be returned to the local Org mode buffer as usual, and file
-output will be created on the remote machine with relative paths interpreted
-relative to the remote directory.  An Org mode link to the remote file will be
-created.
-
-So, in the above example a plot will be created on the remote machine,
-and a link of the following form will be inserted in the org buffer:
+Org first captures the text results as usual for insertion in the Org file.
+Then Org also inserts a link to the remote file, thanks to Emacs
address@hidden  Org constructs the remote path to the file name from
address@hidden:dir} and @code{default-directory}, as illustrated here:
 
 @example
 [[file:/scp:dand@@yakuba.princeton.edu:/home/dand/plot.png][plot.png]]
 @end example
 
-Most of this functionality follows immediately from the fact that @code{:dir}
-sets the value of the Emacs variable @code{default-directory}, thanks to
-tramp.  Those using XEmacs, or GNU Emacs prior to version 23 may need to
-install tramp separately in order for these features to work correctly.
 
address@hidden Further points
address@hidden Some more warnings
 
 @itemize @bullet
 @item
-If @code{:dir} is used in conjunction with @code{:session}, although it will
-determine the starting directory for a new session as expected, no attempt is
-currently made to alter the directory associated with an existing session.
+When @code{:dir} is used with @code{:session}, Org sets the starting
+directory for a new session.  But Org will not alter the directory of an
+already existing session.
 @item
address@hidden:dir} should typically not be used to create files during export 
with
address@hidden:exports results} or @code{:exports both}.  The reason is that, 
in order
-to retain portability of exported material between machines, during export
-links inserted into the buffer will @emph{not} be expanded against 
@code{default
-directory}.  Therefore, if @code{default-directory} is altered using
address@hidden:dir}, it is probable that the file will be created in a location 
to
-which the link does not point.
+Do not use @code{:dir} with @code{:exports results} or with @code{:exports
+both} to avoid Org inserting incorrect links to remote files.  That is because
+Org does not expand @code{default directory} to avoid some underlying
+portability issues.
 @end itemize
 
address@hidden exports, tangle, dir, Specific header arguments
address@hidden exports
 @subsubsection @code{:exports}
address@hidden @code{:exports}, src header argument
 
-The @code{:exports} header argument specifies what should be included in HTML
-or @LaTeX{} exports of the Org mode file.
+The @code{:exports} header argument is to specify if that part of the Org
+file is exported to, say, HTML or @LaTeX{} formats.  Note that
address@hidden:exports} affects only @samp{src} code blocks and not inline code.
 
 @itemize @bullet
 @item @code{code}
-The default.  The body of code is included into the exported file.  E.g.,
+The default.  The body of code is included into the exported file.  Example:
 @code{:exports code}.
 @item @code{results}
-The result of evaluating the code is included in the exported file.  E.g.,
address@hidden:exports results}.
+The results of evaluation of the code is included in the exported file.
+Example: @code{:exports results}.
 @item @code{both}
-Both the code and results are included in the exported file.  E.g.,
address@hidden:exports both}.
+Both the code and results of evaluation are included in the exported file.
+Example: @code{:exports both}.
 @item @code{none}
-Nothing is included in the exported file.  E.g., @code{:exports none}.
+Neither the code nor the results of evaluation is included in the exported
+file.  Whether the code is evaluated at all depends on other
+options.  Example: @code{:exports none}.
 @end itemize
 
address@hidden tangle, mkdirp, exports, Specific header arguments
address@hidden tangle
 @subsubsection @code{:tangle}
address@hidden @code{:tangle}, src header argument
 
-The @code{:tangle} header argument specifies whether or not the code
-block should be included in tangled extraction of source code files.
+The @code{:tangle} header argument specifies if the @samp{src} code block is
+exported to source file(s).
 
 @itemize @bullet
 @item @code{tangle}
-The code block is exported to a source code file named after the full path
-(including the directory) and file name (w/o extension) of the Org mode file.
-E.g., @code{:tangle yes}.
+Export the @samp{src} code block to source file.  The file name for the
+source file is derived from the name of the Org file, and the file extension
+is derived from the source code language identifier.  Example: @code{:tangle
+yes}.
 @item @code{no}
-The default.  The code block is not exported to a source code file.
-E.g., @code{:tangle no}.
+The default.  Do not extract the code a source code file.  Example:
address@hidden:tangle no}.
 @item other
-Any other string passed to the @code{:tangle} header argument is interpreted
-as a path (directory and file name relative to the directory of the Org mode
-file) to which the block will be exported.  E.g., @code{:tangle path}.
+Export the @samp{src} code block to source file whose file name is derived
+from any string passed to the @code{:tangle} header argument.  Org derives
+the file name as being relative to the directory of the Org file's location.
+Example: @code{:tangle path}.
 @end itemize
 
address@hidden mkdirp, comments, tangle, Specific header arguments
address@hidden mkdirp
 @subsubsection @code{:mkdirp}
address@hidden @code{:mkdirp}, src header argument
 
-The @code{:mkdirp} header argument can be used to create parent directories
-of tangled files when missing.  This can be set to @code{yes} to enable
-directory creation or to @code{no} to inhibit directory creation.
+The @code{:mkdirp} header argument creates parent directories for tangled
+files if the directory does not exist.  @code{yes} enables directory creation
+and @code{no} inhibits directory creation.
 
address@hidden comments, padline, mkdirp, Specific header arguments
address@hidden comments
 @subsubsection @code{:comments}
-By default code blocks are tangled to source-code files without any insertion
-of comments beyond those which may already exist in the body of the code
-block.  The @code{:comments} header argument can be set as follows to control
-the insertion of extra comments into the tangled code file.
address@hidden @code{:comments}, src header argument
+Controls inserting comments into tangled files.  These are above and beyond
+whatever comments may already exist in the @samp{src} code block.
 
 @itemize @bullet
 @item @code{no}
-The default.  No extra comments are inserted during tangling.
+The default.  Do not insert any extra comments during tangling.
 @item @code{link}
-The code block is wrapped in comments which contain pointers back to the
-original Org file from which the code was tangled.
+Wrap the @samp{src} code block in comments.  Include links pointing back to
+the place in the Org file from where the code was tangled.
 @item @code{yes}
-A synonym for ``link'' to maintain backwards compatibility.
+Kept for backward compatibility; same as ``link''.
 @item @code{org}
-Include text from the Org mode file as a comment.
-The text is picked from the leading context of the tangled code and is
-limited by the nearest headline or source block as the case may be.
+Nearest headline text from Org file is inserted as comment.  The exact text
+that is inserted is picked from the leading context of the source block.
 @item @code{both}
-Turns on both the ``link'' and ``org'' comment options.
+Includes both ``link'' and ``org'' comment options.
 @item @code{noweb}
-Turns on the ``link'' comment option, and additionally wraps expanded noweb
-references in the code block body in link comments.
+Includes ``link'' comment option, expands noweb references, and wraps them in
+link comments inside the body of the @samp{src} code block.
 @end itemize
 
address@hidden padline, no-expand, comments, Specific header arguments
address@hidden padline
 @subsubsection @code{:padline}
-Control in insertion of padding lines around code block bodies in tangled
-code files.  The default value is @code{yes} which results in insertion of
-newlines before and after each tangled code block.  The following arguments
-are accepted.
-
address@hidden @code{:padline}, src header argument
+Control insertion of newlines to pad @samp{src} code blocks in the tangled
+file.
 @itemize @bullet
 @item @code{yes}
-Insert newlines before and after each code block body in tangled code files.
+Default.  Insert a newline before and after each @samp{src} code block in the
+tangled file.
 @item @code{no}
-Do not insert any newline padding in tangled output.
+Do not insert newlines to pad the tangled @samp{src} code blocks.
 @end itemize
 
address@hidden no-expand, session, padline, Specific header arguments
address@hidden no-expand
 @subsubsection @code{:no-expand}
-
-By default, code blocks are expanded with @code{org-babel-expand-src-block}
-during tangling.  This has the effect of assigning values to variables
-specified with @code{:var} (see @ref{var}), and of replacing ``noweb''
-references (see @ref{Noweb reference syntax}) with their targets.  The
address@hidden:no-expand} header argument can be used to turn off this behavior.
-
address@hidden session, noweb, no-expand, Specific header arguments
address@hidden @code{:no-expand}, src header argument
+
+By default Org expands @samp{src} code blocks during tangling.  The
address@hidden:no-expand} header argument turns off such expansions.  Note that 
one
+side-effect of expansion by @code{org-babel-expand-src-block} also assigns
+values to @code{:var} (@pxref{var}) variables.  Expansions also replace
+``noweb'' references with their targets (@pxref{Noweb reference syntax}).
+Some of these expansions may cause premature assignment, hence this option.
+This option makes a difference only for tangling.  It has no effect when
+exporting since @samp{src} code blocks for execution have to be expanded
+anyway.
+
address@hidden session
 @subsubsection @code{:session}
address@hidden @code{:session}, src header argument
 
-The @code{:session} header argument starts a session for an interpreted
-language where state is preserved.
+The @code{:session} header argument is for running multiple source code
+blocks under one session.  Org runs @samp{src} code blocks with the same
+session name in the same interpreter process.
 
-By default, a session is not started.
-
-A string passed to the @code{:session} header argument will give the session
-a name.  This makes it possible to run concurrent sessions for each
-interpreted language.
address@hidden @bullet
address@hidden @code{none}
+Default.  Each @samp{src} code block gets a new interpreter process to
+execute.  The process terminates once the block is evaluated.
address@hidden @code{other}
+Any string besides @code{none} turns that string into the name of that
+session.  For example, @code{:session mysession} names it @samp{mysession}.
+If @code{:session} has no argument, then the session name is derived from the
+source language identifier.  Subsequent blocks with the same source code
+language use the same session.  Depending on the language, state variables,
+code from other blocks, and the overall interpreted environment may be
+shared.  Some interpreted languages support concurrent sessions when
+subsequent source code language blocks change session names.
address@hidden itemize
 
address@hidden noweb, noweb-ref, session, Specific header arguments
address@hidden noweb
 @subsubsection @code{:noweb}
address@hidden @code{:noweb}, src header argument
 
 The @code{:noweb} header argument controls expansion of ``noweb'' syntax
-references (see @ref{Noweb reference syntax}) when the code block is
-evaluated, tangled, or exported.  The @code{:noweb} header argument can have
-one of the five values: @code{no}, @code{yes}, @code{tangle}, or
address@hidden @code{strip-export}.
+references (@pxref{Noweb reference syntax}).  Expansions occur when source
+code blocks are evaluated, tangled, or exported.
 
 @itemize @bullet
 @item @code{no}
-The default.  ``Noweb'' syntax references in the body of the code block will
-not be expanded before the code block is evaluated, tangled or exported.
+Default.  No expansion of ``Noweb'' syntax references in the body of the code
+when evaluating, tangling, or exporting.
 @item @code{yes}
-``Noweb'' syntax references in the body of the code block will be
-expanded before the code block is evaluated, tangled or exported.
+Expansion of ``Noweb'' syntax references in the body of the @samp{src} code
+block when evaluating, tangling, or exporting.
 @item @code{tangle}
-``Noweb'' syntax references in the body of the code block will be expanded
-before the code block is tangled.  However, ``noweb'' syntax references will
-not be expanded when the code block is evaluated or exported.
+Expansion of ``Noweb'' syntax references in the body of the @samp{src} code
+block when tangling.  No expansion when evaluating or exporting.
 @item @code{no-export}
-``Noweb'' syntax references in the body of the code block will be expanded
-before the block is evaluated or tangled.  However, ``noweb'' syntax
-references will not be expanded when the code block is exported.
+Expansion of ``Noweb'' syntax references in the body of the @samp{src} code
+block when evaluating or tangling.  No expansion when exporting.
 @item @code{strip-export}
-``Noweb'' syntax references in the body of the code block will be expanded
-before the block is evaluated or tangled.  However, ``noweb'' syntax
-references will be removed when the code block is exported.
+Expansion of ``Noweb'' syntax references in the body of the @samp{src} code
+block when expanding prior to evaluating or tangling.  Removes ``noweb''
+syntax references when exporting.
 @item @code{eval}
-``Noweb'' syntax references in the body of the code block will only be
-expanded before the block is evaluated.
+Expansion of ``Noweb'' syntax references in the body of the @samp{src} code
+block only before evaluating.
 @end itemize
 
 @subsubheading Noweb prefix lines
-Noweb insertions are now placed behind the line prefix of the
address@hidden<<reference>>}.
-This behavior is illustrated in the following example.  Because the
address@hidden<<example>>} noweb reference appears behind the SQL comment 
syntax,
-each line of the expanded noweb reference will be commented.
+Noweb insertions now honor prefix characters that appear before
address@hidden<<reference>>}.  This behavior is illustrated in the following 
example.
+Because the @code{<<example>>} noweb reference appears behind the SQL comment
+syntax, each line of the expanded noweb reference will be commented.
 
-This code block:
+This @samp{src} code block:
 
 @example
 -- <<example>>
@@ -15290,23 +16228,20 @@ expands to:
 -- multi-line body of example
 @end example
 
-Note that noweb replacement text that does not contain any newlines will not
-be affected by this change, so it is still possible to use inline noweb
-references.
+Since this change will not affect noweb replacement text without newlines in
+them, inline noweb references are acceptable.
 
address@hidden noweb-ref, noweb-sep, noweb, Specific header arguments
address@hidden noweb-ref
 @subsubsection @code{:noweb-ref}
-When expanding ``noweb'' style references the bodies of all code block with
address@hidden a block name matching the reference name @emph{or} a
address@hidden:noweb-ref} header argument matching the reference name will be
-concatenated together to form the replacement text.
address@hidden @code{:noweb-ref}, src header argument
 
-By setting this header argument at the sub-tree or file level, simple code
-block concatenation may be achieved.  For example, when tangling the
-following Org mode file, the bodies of code blocks will be concatenated into
-the resulting pure code address@hidden(The example needs property inheritance
-to be turned on for the @code{noweb-ref} property, see @ref{Property
-inheritance}).}.
+When expanding ``noweb'' style references, Org concatenates @samp{src} code
+blocks by matching the reference name to either the block name or the
address@hidden:noweb-ref} header argument.
+
+For simple concatenation, set this @code{:noweb-ref} header argument at the
+sub-tree or file level.  In the example Org file shown next, the body of the
+source code in each block is extracted for concatenation to a pure code file.
 
 @example
  #+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh
@@ -15314,7 +16249,7 @@ inheritance}).}.
  #+END_SRC
  * the mount point of the fullest disk
    :PROPERTIES:
-   :noweb-ref: fullest-disk
+   :header-args: :noweb-ref fullest-disk
    :END:
 
  ** query all mounted disks
@@ -15333,45 +16268,60 @@ inheritance}).}.
  #+END_SRC
 @end example
 
-The @code{:noweb-sep} (see @ref{noweb-sep}) header argument holds the string
-used to separate accumulate noweb references like those above.  By default a
-newline is used.
-
address@hidden noweb-sep, cache, noweb-ref, Specific header arguments
address@hidden noweb-sep
 @subsubsection @code{:noweb-sep}
address@hidden @code{:noweb-sep}, src header argument
 
-The @code{:noweb-sep} header argument holds the string used to separate
-accumulate noweb references (see @ref{noweb-ref}).  By default a newline is
-used.
+By default a newline separates each noweb reference concatenation.  To change
+this newline separator, edit the @code{:noweb-sep} (@pxref{noweb-sep}) header
+argument.
 
address@hidden cache, sep, noweb-sep, Specific header arguments
address@hidden cache
 @subsubsection @code{:cache}
-
-The @code{:cache} header argument controls the use of in-buffer caching of
-the results of evaluating code blocks.  It can be used to avoid re-evaluating
-unchanged code blocks.  Note that the @code{:cache} header argument will not
-attempt to cache results when the @code{:session} header argument is used,
-because the results of the code block execution may be stored in the session
-outside of the Org mode buffer.  The @code{:cache} header argument can have
-one of two values: @code{yes} or @code{no}.
address@hidden @code{:cache}, src header argument
+
+The @code{:cache} header argument is for caching results of evaluating code
+blocks.  Caching results can avoid re-evaluating @samp{src} code blocks that
+have not changed since the previous run.  To benefit from the cache and avoid
+redundant evaluations, the source block must have a result already present in
+the buffer, and neither the header arguments (including the value of
address@hidden:var} references) nor the text of the block itself has changed 
since
+the result was last computed.  This feature greatly helps avoid long-running
+calculations.  For some edge cases, however, the cached results may not be
+reliable.
+
+The caching feature is best for when @samp{src} blocks are pure functions,
+that is functions that return the same value for the same input arguments
+(@pxref{var}), and that do not have side effects, and do not rely on external
+variables other than the input arguments.  Functions that depend on a timer,
+file system objects, and random number generators are clearly unsuitable for
+caching.
+
+A note of warning: when @code{:cache} is used for a @code{:session}, caching
+may cause unexpected results.
+
+When the caching mechanism tests for any source code changes, it will not
+expand ``noweb'' style references (@pxref{Noweb reference syntax}).  For
+reasons why, see @uref{http://thread.gmane.org/gmane.emacs.orgmode/79046}.
+
+The @code{:cache} header argument can have one of two values: @code{yes} or
address@hidden
 
 @itemize @bullet
 @item @code{no}
-The default.  No caching takes place, and the code block will be evaluated
-every time it is called.
+Default.  No caching of results; @samp{src} code block evaluated every time.
 @item @code{yes}
-Every time the code block is run a SHA1 hash of the code and arguments
-passed to the block will be generated.  This hash is packed into the
address@hidden:} line and will be checked on subsequent
-executions of the code block.  If the code block has not
-changed since the last time it was evaluated, it will not be re-evaluated.
+Whether to run the code or return the cached results is determined by
+comparing the SHA1 hash value of the combined @samp{src} code block and
+arguments passed to it.  This hash value is packed on the @code{#+RESULTS:}
+line from previous evaluation.  When hash values match, Org does not evaluate
+the @samp{src} code block.  When hash values mismatch, Org evaluates the
address@hidden code block, inserts the results, recalculates the hash value, and
+updates @code{#+RESULTS:} line.
 @end itemize
 
-Code block caches notice if the value of a variable argument
-to the code block has changed.  If this is the case, the cache is
-invalidated and the code block is re-run.  In the following example,
address@hidden will not be re-run unless the results of @code{random} have
-changed since it was last run.
+In this example, both functions are cached.  But @code{caller} runs only if
+the result from @code{random} has changed since the last run.
 
 @example
  #+NAME: random
@@ -15391,32 +16341,31 @@ changed since it was last run.
  0.254227238707244
 @end example
 
address@hidden sep, hlines, cache, Specific header arguments
address@hidden sep
 @subsubsection @code{:sep}
address@hidden @code{:sep}, src header argument
 
-The @code{:sep} header argument can be used to control the delimiter used
-when writing tabular results out to files external to Org mode.  This is used
-either when opening tabular results of a code block by calling the
address@hidden function bound to @kbd{C-c C-o} on the code block,
-or when writing code block results to an external file (see @ref{file})
-header argument.
+The @code{:sep} header argument is the delimiter for saving results as tables
+to files (@pxref{file}) external to Org mode.  Org defaults to tab delimited
+output.  The function, @code{org-open-at-point}, which is bound to @kbd{C-c
+C-o}, also uses @code{:sep} for opening tabular results.
 
-By default, when @code{:sep} is not specified output tables are tab
-delimited.
-
address@hidden hlines, colnames, sep, Specific header arguments
address@hidden hlines
 @subsubsection @code{:hlines}
address@hidden @code{:hlines}, src header argument
 
-Tables are frequently represented with one or more horizontal lines, or
-hlines.  The @code{:hlines} argument to a code block accepts the
-values @code{yes} or @code{no}, with a default value of @code{no}.
+In-between each table row or below the table headings, sometimes results have
+horizontal lines, which are also known as hlines.  The @code{:hlines}
+argument with the value @code{yes} accepts such lines.  The default is
address@hidden
 
 @itemize @bullet
 @item @code{no}
-Strips horizontal lines from the input table.  In most languages this is the
-desired effect because an @code{hline} symbol is interpreted as an unbound
-variable and raises an error.  Setting @code{:hlines no} or relying on the
-default value yields the following results.
+Strips horizontal lines from the input table.  For most code, this is
+desirable, or else those @code{hline} symbols raise unbound variable errors.
+
+The default is @code{:hlines no}.  The example shows hlines removed from the
+input table.
 
 @example
 #+NAME: many-cols
@@ -15438,7 +16387,7 @@ default value yields the following results.
 @end example
 
 @item @code{yes}
-Leaves hlines in the table.  Setting @code{:hlines yes} has this effect.
+For @code{:hlines yes}, the example shows hlines unchanged.
 
 @example
 #+NAME: many-cols
@@ -15462,20 +16411,20 @@ Leaves hlines in the table.  Setting @code{:hlines 
yes} has this effect.
 @end example
 @end itemize
 
address@hidden colnames, rownames, hlines, Specific header arguments
address@hidden colnames
 @subsubsection @code{:colnames}
address@hidden @code{:colnames}, src header argument
 
-The @code{:colnames} header argument accepts the values @code{yes},
address@hidden, or @code{nil} for unassigned.  The default value is @code{nil}.
-Note that the behavior of the @code{:colnames} header argument may differ
-across languages.
+The @code{:colnames} header argument accepts @code{yes}, @code{no}, or
address@hidden values.  The default value is @code{nil}, which is unassigned.
+But this header argument behaves differently depending on the source code
+language.
 
 @itemize @bullet
 @item @code{nil}
-If an input table looks like it has column names
-(because its second row is an hline), then the column
-names will be removed from the table before
-processing, then reapplied to the results.
+If an input table has column names (because the second row is an hline), then
+Org removes the column names, processes the table, puts back the column
+names, and then writes the table to the results block.
 
 @example
 #+NAME: less-cols
@@ -15496,33 +16445,36 @@ processing, then reapplied to the results.
 | c* |
 @end example
 
-Please note that column names are not removed before the table is indexed
-using variable indexing @xref{var, Indexable variable values}.
+Note that column names have to accounted for when using variable indexing
+(@pxref{var, Indexable variable values}) because column names are not removed
+for indexing.
 
 @item @code{no}
-No column name pre-processing takes place
+Do not pre-process column names.
 
 @item @code{yes}
-Column names are removed and reapplied as with @code{nil} even if the table
-does not ``look like'' it has column names (i.e., the second row is not an
-hline)
+For an input table that has no hlines, process it like the @code{nil}
+value.  That is, Org removes the column names, processes the table, puts back
+the column names, and then writes the table to the results block.
 @end itemize
 
address@hidden rownames, shebang, colnames, Specific header arguments
address@hidden rownames
 @subsubsection @code{:rownames}
address@hidden @code{:rownames}, src header argument
 
-The @code{:rownames} header argument can take on the values @code{yes} or
address@hidden, with a default value of @code{no}.  Note that Emacs Lisp code
-blocks ignore the @code{:rownames} header argument entirely given the ease
-with which tables with row names may be handled directly in Emacs Lisp.
+The @code{:rownames} header argument can take on values @code{yes} or
address@hidden values.  The default is @code{no}.  Note that @code{emacs-lisp}
+code blocks ignore @code{:rownames} header argument because of the ease of
+table-handling in Emacs.
 
 @itemize @bullet
 @item @code{no}
-No row name pre-processing will take place.
+Org will not pre-process row names.
 
 @item @code{yes}
-The first column of the table is removed from the table before processing,
-and is then reapplied to the results.
+If an input table has row names, then Org removes the row names, processes
+the table, puts back the row names, and then writes the table to the results
+block.
 
 @example
 #+NAME: with-rownames
@@ -15539,82 +16491,88 @@ and is then reapplied to the results.
 | two | 16 | 17 | 18 | 19 | 20 |
 @end example
 
-Please note that row names are not removed before the table is indexed using
-variable indexing @xref{var, Indexable variable values}.
+Note that row names have to accounted for when using variable indexing
+(@pxref{var, Indexable variable values}) because row names are not removed
+for indexing.
 
 @end itemize
 
address@hidden shebang, tangle-mode, rownames, Specific header arguments
address@hidden shebang
 @subsubsection @code{:shebang}
address@hidden @code{:shebang}, src header argument
 
-Setting the @code{:shebang} header argument to a string value
-(e.g., @code{:shebang "#!/bin/bash"}) causes the string to be inserted as the
-first line of any tangled file holding the code block, and the file
-permissions of the tangled file are set to make it executable.
+This header argument can turn results into executable script files.  By
+setting the @code{:shebang} header argument to a string value (for example,
address@hidden:shebang "#!/bin/bash"}), Org inserts that string as the first 
line of
+the tangled file that the @samp{src} code block is extracted to.  Org then
+turns on the tangled file's executable permission.
 
-
address@hidden tangle-mode, eval, shebang, Specific header arguments
address@hidden tangle-mode
 @subsubsection @code{:tangle-mode}
address@hidden @code{:tangle-mode}, src header argument
+
+The @code{tangle-mode} header argument specifies what permissions to set for
+tangled files by @code{set-file-modes}.  For example, to make read-only
+tangled file, use @code{:tangle-mode (identity #o444)}.  To make it
+executable, use @code{:tangle-mode (identity #o755)}.
+
+On @samp{src} code blocks with @code{shebang} (@pxref{shebang}) header
+argument, Org will automatically set the tangled file to executable
+permissions.  But this can be overridden with custom permissions using
address@hidden header argument.
+
+When multiple @samp{src} code blocks tangle to a single file with different
+and conflicting @code{tangle-mode} header arguments, Org's behavior is
+undefined.
 
-The @code{tangle-mode} header argument controls the permission set on tangled
-files.  The value of this header argument will be passed to
address@hidden  For example, to set a tangled file as read only use
address@hidden:tangle-mode (identity #o444)}, or to set a tangled file as 
executable
-use @code{:tangle-mode (identity #o755)}.  Blocks with @code{shebang}
-(@ref{shebang}) header arguments will automatically be made executable unless
-the @code{tangle-mode} header argument is also used.  The behavior is
-undefined if multiple code blocks with different values for the
address@hidden header argument are tangled to the same file.
-
address@hidden eval, wrap, tangle-mode, Specific header arguments
address@hidden eval
 @subsubsection @code{:eval}
-The @code{:eval} header argument can be used to limit the evaluation of
-specific code blocks.  The @code{:eval} header argument can be useful for
-protecting against the evaluation of dangerous code blocks or to ensure that
-evaluation will require a query regardless of the value of the
address@hidden variable.  The possible values of
address@hidden:eval} and their effects are shown below.
address@hidden @code{:eval}, src header argument
+The @code{:eval} header argument can limit evaluation of specific code
+blocks.  It is useful for protection against evaluating untrusted @samp{src}
+code blocks by prompting for a confirmation.  This protection is independent
+of the @code{org-confirm-babel-evaluate} setting.
 
 @table @code
 @item never or no
-The code block will not be evaluated under any circumstances.
+Org will never evaluate this @samp{src} code block.
 @item query
-Evaluation of the code block will require a query.
+Org prompts the user for permission to evaluate this @samp{src} code block.
 @item never-export or no-export
-The code block will not be evaluated during export but may still be called
-interactively.
+Org will not evaluate this @samp{src} code block when exporting, yet the user
+can evaluate this source block interactively.
 @item query-export
-Evaluation of the code block during export will require a query.
+Org prompts the user for permission to export this @samp{src} code block.
 @end table
 
-If this header argument is not set then evaluation is determined by the value
-of the @code{org-confirm-babel-evaluate} variable see @ref{Code evaluation
-security}.
+If @code{:eval} header argument is not set for a source block, then Org
+determines whether to evaluate from the @code{org-confirm-babel-evaluate}
+variable (@pxref{Code evaluation security}).
 
address@hidden wrap, post, eval, Specific header arguments
address@hidden wrap
 @subsubsection @code{:wrap}
-The @code{:wrap} header argument is used to mark the results of source block
-evaluation.  The header argument can be passed a string that will be appended
-to @code{#+BEGIN_} and @code{#+END_}, which will then be used to wrap the
-results.  If not string is specified then the results will be wrapped in a
address@hidden/END_RESULTS} block.
address@hidden @code{:wrap}, src header argument
+The @code{:wrap} header argument marks the results block by appending strings
+to @code{#+BEGIN_} and @code{#+END_}.  If no string is specified, Org wraps
+the results in a @code{#+BEGIN/END_RESULTS} block.
 
address@hidden post, prologue, wrap, Specific header arguments
address@hidden post
 @subsubsection @code{:post}
-The @code{:post} header argument is used to post-process the results of a
-code block execution.  When a post argument is given, the results of the code
-block will temporarily be bound to the @code{*this*} variable.  This variable
-may then be included in header argument forms such as those used in @ref{var}
-header argument specifications allowing passing of results to other code
-blocks, or direct execution via Emacs Lisp.
-
-The following example illustrates the usage of the @code{:post} header
-argument.
address@hidden @code{:post}, src header argument
+The @code{:post} header argument is for post-processing results from
address@hidden block evaluation.  When @code{:post} has any value, Org binds the
+results to @code{*this*} variable for easy passing to @ref{var} header
+argument specifications.  That makes results available to other @samp{src}
+code blocks, or for even direct Emacs Lisp code execution.
+
+The following two examples illustrate @code{:post} header argument in action.
+The first one shows how to attach @code{#+ATTR_LATEX:} line using
address@hidden:post}.
 
 @example
 #+name: attr_wrap
 #+begin_src sh :var data="" :var width="\\textwidth" :results output
-  echo "#+ATTR_LATEX :width $width"
+  echo "#+ATTR_LATEX: :width $width"
   echo "$data"
 #+end_src
 
@@ -15634,33 +16592,65 @@ argument.
 :END:
 @end example
 
address@hidden prologue, epilogue, post, Specific header arguments
+The second example shows use of @code{:colnames} in @code{:post} to pass
+data between @samp{src} code blocks.
+
address@hidden
+#+name: round-tbl
+#+begin_src emacs-lisp :var tbl="" fmt="%.3f"
+  (mapcar (lambda (row)
+            (mapcar (lambda (cell)
+                      (if (numberp cell)
+                          (format fmt cell)
+                        cell))
+                    row))
+          tbl)
+#+end_src
+
+#+begin_src R :colnames yes :post round-tbl[:colnames yes](*this*)
+set.seed(42)
+data.frame(foo=rnorm(1))
+#+end_src
+
+#+RESULTS:
+|   foo |
+|-------|
+| 1.371 |
address@hidden example
+
address@hidden prologue
 @subsubsection @code{:prologue}
-The value of the @code{prologue} header argument will be prepended to the
-code block body before execution.  For example, @code{:prologue "reset"} may
-be used to reset a gnuplot session before execution of a particular code
-block, or the following configuration may be used to do this for all gnuplot
-code blocks.  Also see @ref{epilogue}.
address@hidden @code{:prologue}, src header argument
+The @code{prologue} header argument is for appending to the top of the code
+block for execution.  For example, a clear or reset code at the start of new
+execution of a @samp{src} code block.  A @code{reset} for @samp{gnuplot}:
address@hidden:prologue "reset"}.  See also @ref{epilogue}.
 
 @lisp
 (add-to-list 'org-babel-default-header-args:gnuplot
              '((:prologue . "reset")))
 @end lisp
 
address@hidden epilogue, , prologue, Specific header arguments
address@hidden epilogue
 @subsubsection @code{:epilogue}
-The value of the @code{epilogue} header argument will be appended to the code
-block body before execution.  Also see @ref{prologue}.
address@hidden @code{:epilogue}, src header argument
+The value of the @code{epilogue} header argument is for appending to the end
+of the code block for execution.  See also @ref{prologue}.
 
address@hidden Results of evaluation, Noweb reference syntax, Header arguments, 
Working With Source Code
address@hidden Results of evaluation
 @section Results of evaluation
 @cindex code block, results of evaluation
 @cindex source code, results of evaluation
 
-The way in which results are handled depends on whether a session is invoked,
-as well as on whether @code{:results value} or @code{:results output} is
-used.  The following table shows the table possibilities.  For a full listing
-of the possible results header arguments see @ref{results}.
+How Org handles results of a code block execution depends on many header
+arguments working together.  Here is only a summary of these.  For an
+enumeration of all the header arguments that affect results, see
address@hidden
+
+The primary determinant is the execution context.  Is it in a @code{:session}
+or not?  Orthogonal to that is if the expected result is a @code{:results
+value} or @code{:results output}, which is a concatenation of output from
+start to finish of the @samp{src} code block's evaluation.
 
 @multitable @columnfractions 0.26 0.33 0.41
 @item @tab @b{Non-session} @tab @b{Session}
@@ -15668,51 +16658,54 @@ of the possible results header arguments see 
@ref{results}.
 @item @code{:results output} @tab contents of STDOUT @tab concatenation of 
interpreter output
 @end multitable
 
-Note: With @code{:results value}, the result in both @code{:session} and
-non-session is returned to Org mode as a table (a one- or two-dimensional
-vector of strings or numbers) when appropriate.
+For @code{:session} and non-session, the @code{:results value} turns the
+results into an Org mode table format.  Single values are wrapped in a one
+dimensional vector.  Rows and columns of a table are wrapped in a
+two-dimensional vector.
 
 @subsection Non-session
 @subsubsection @code{:results value}
-This is the default.  Internally, the value is obtained by wrapping the code
-in a function definition in the external language, and evaluating that
-function.  Therefore, code should be written as if it were the body of such a
-function.  In particular, note that Python does not automatically return a
-value from a function unless a @code{return} statement is present, and so a
address@hidden statement will usually be required in Python.
address@hidden @code{:results}, src header argument
+Default.  Org gets the value by wrapping the code in a function definition in
+the language of the @samp{src} block.  That is why when using @code{:results
+value}, code should execute like a function and return a value.  For
+languages like Python, an explicit @code{return} statement is mandatory when
+using @code{:results value}.
 
-This is the only one of the four evaluation contexts in which the code is
-automatically wrapped in a function definition.
+This is one of four evaluation contexts where Org automatically wraps the
+code in a function definition.
 
 @subsubsection @code{:results output}
-The code is passed to the interpreter as an external process, and the
-contents of the standard output stream are returned as text.  (In certain
-languages this also contains the error output stream; this is an area for
-future work.)
address@hidden @code{:results}, src header argument
+For @code{:results output}, the code is passed to an external process running
+the interpreter.  Org returns the contents of the standard output stream as
+as text results.
 
 @subsection Session
 @subsubsection @code{:results value}
-The code is passed to an interpreter running as an interactive Emacs inferior
-process.  Only languages which provide tools for interactive evaluation of
-code have session support, so some language (e.g., C and ditaa) do not
-support the @code{:session} header argument, and in other languages (e.g.,
-Python and Haskell) which have limitations on the code which may be entered
-into interactive sessions, those limitations apply to the code in code blocks
-using the @code{:session} header argument as well.
-
-Unless the @code{:results output} option is supplied (see below) the result
-returned is the result of the last evaluation performed by the
-interpreter.  (This is obtained in a language-specific manner: the value of
-the variable @code{_} in Python and Ruby, and the value of @code{.Last.value}
-in R).
address@hidden @code{:results}, src header argument
+For @code{:results value} from a @code{:session}, Org passes the code to an
+interpreter running as an interactive Emacs inferior process.  So only
+languages that provide interactive evaluation can have session support.  Not
+all languages provide this support, such as @samp{C} and @samp{ditaa}.  Even
+those that do support, such as @samp{Python} and @samp{Haskell}, they impose
+limitations on allowable language constructs that can run interactively.  Org
+inherits those limitations for those @samp{src} code blocks running in a
address@hidden:session}.
+
+Org gets the value from the source code interpreter's last statement
+output.  Org has to use language-specific methods to obtain the value.  For
+example, from the variable @code{_} in @samp{Python} and @samp{Ruby}, and the
+value of @code{.Last.value} in @samp{R}).
 
 @subsubsection @code{:results output}
-The code is passed to the interpreter running as an interactive Emacs
-inferior process.  The result returned is the concatenation of the sequence of
-(text) output from the interactive interpreter.  Notice that this is not
-necessarily the same as what would be sent to @code{STDOUT} if the same code
-were passed to a non-interactive interpreter running as an external
-process.  For example, compare the following two blocks:
address@hidden @code{:results}, src header argument
+For @code{:results output}, Org passes the code to the interpreter running as
+an interactive Emacs inferior process.  Org concatenates whatever text output
+emitted by the interpreter to return the collection as a result.  Note that
+this collection is not the same as collected from @code{STDOUT} of a
+non-interactive interpreter running as an external process.  Compare for
+example these two blocks:
 
 @example
 #+BEGIN_SRC python :results output
@@ -15726,7 +16719,8 @@ process.  For example, compare the following two blocks:
 : bye
 @end example
 
-In non-session mode, the ``2'' is not printed and does not appear.
+In the above non-session mode, the ``2'' is not printed; so does not appear
+in results.
 
 @example
 #+BEGIN_SRC python :results output :session
@@ -15741,60 +16735,61 @@ In non-session mode, the ``2'' is not printed and 
does not appear.
 : bye
 @end example
 
-But in @code{:session} mode, the interactive interpreter receives input ``2''
-and prints out its value, ``2''.  (Indeed, the other print statements are
-unnecessary here).
+In the above @code{:session} mode, the interactive interpreter receives and
+prints ``2''.  Results show that.
 
address@hidden Noweb reference syntax, Key bindings and useful functions, 
Results of evaluation, Working With Source Code
address@hidden Noweb reference syntax
 @section Noweb reference syntax
 @cindex code block, noweb reference
 @cindex syntax, noweb
 @cindex source code, noweb reference
 
-The ``noweb'' (see @uref{http://www.cs.tufts.edu/~nr/noweb/}) Literate
-Programming system allows named blocks of code to be referenced by using the
-familiar Noweb syntax:
+Org supports named blocks in ``noweb'' style syntax.  For ``noweb'' literate
+programming details, see @uref{http://www.cs.tufts.edu/~nr/noweb/}).
 
 @example
 <<code-block-name>>
 @end example
 
-When a code block is tangled or evaluated, whether or not ``noweb''
-references are expanded depends upon the value of the @code{:noweb} header
-argument.  If @code{:noweb yes}, then a Noweb reference is expanded before
-evaluation.  If @code{:noweb no}, the default, then the reference is not
-expanded before evaluation.  See the @ref{noweb-ref} header argument for
-a more flexible way to resolve noweb references.
+For the header argument @code{:noweb yes}, Org expands ``noweb'' style
+references in the @samp{src} code block before evaluation.
+
+For the header argument @code{:noweb no}, Org does not expand ``noweb'' style
+references in the @samp{src} code block before evaluation.
+
+The default is @code{:noweb no}.
+
+Org offers a more flexible way to resolve ``noweb'' style references
+(@pxref{noweb-ref}).
 
-It is possible to include the @emph{results} of a code block rather than the
-body.  This is done by appending parenthesis to the code block name which may
-optionally contain arguments to the code block as shown below.
+Org can handle naming of @emph{results} block, rather than the body of the
address@hidden code block, using ``noweb'' style references.
+
+For ``noweb'' style reference, append parenthesis to the code block name for
+arguments, as shown in this example:
 
 @example
 <<code-block-name(optional arguments)>>
 @end example
 
-Note: the default value, @code{:noweb no}, was chosen to ensure that
-correct code is not broken in a language, such as Ruby, where
address@hidden<<arg>>} is a syntactically valid construct.  If @code{<<arg>>} 
is not
-syntactically valid in languages that you use, then please consider setting
-the default value.
+Note: Org defaults to @code{:noweb no} so as not to cause errors in languages
+such as @samp{Ruby} where ``noweb'' syntax is equally valid characters.  For
+example, @code{<<arg>>}.  Change Org's default to @code{:noweb yes} for
+languages where there is no risk of confusion.
 
-Note: if noweb tangling is slow in large Org mode files consider setting the
+For faster tangling of large Org mode files, set
 @code{org-babel-use-quick-and-dirty-noweb-expansion} variable to @code{t}.
-This will result in faster noweb reference resolution at the expense of not
-correctly resolving inherited values of the @code{:noweb-ref} header
-argument.
+The speedup comes at the expense of not correctly resolving inherited values
+of the @code{:noweb-ref} header argument.
 
address@hidden Key bindings and useful functions, Batch execution, Noweb 
reference syntax, Working With Source Code
+
address@hidden Key bindings and useful functions
 @section Key bindings and useful functions
 @cindex code block, key bindings
 
-Many common Org mode key sequences are re-bound depending on
-the context.
+Many common Org mode key sequences are re-bound depending on the context.
 
-Within a code block, the following key bindings
-are active:
+Active key bindings in code blocks:
 
 @multitable @columnfractions 0.25 0.75
 @kindex C-c C-c
@@ -15807,9 +16802,9 @@ are active:
 @item @address@hidden  @tab @code{org-babel-switch-to-session}
 @end multitable
 
-In an Org mode buffer, the following key bindings are active:
+Active key bindings in Org mode buffer:
 
address@hidden @columnfractions 0.45 0.55
address@hidden @columnfractions 0.5 0.5
 @kindex C-c C-v p
 @kindex C-c C-v C-p
 @item @kbd{C-c C-v p} @ @ @r{or} @ @ @kbd{C-c C-v C-p} @tab 
@code{org-babel-previous-src-block}
@@ -15878,8 +16873,7 @@ In an Org mode buffer, the following key bindings are 
active:
 @item @kbd{C-c C-v x} @ @ @r{or} @ @ @kbd{C-c C-v C-x} @tab 
@code{org-babel-do-key-sequence-in-edit-buffer}
 @end multitable
 
address@hidden When possible these keybindings were extended to work when the 
control key is
address@hidden kept pressed, resulting in the following additional keybindings.
address@hidden Extended key bindings when control key is kept pressed:
 
 @c @multitable @columnfractions 0.25 0.75
 @c @item @kbd{C-c C-v C-a} @tab @code{org-babel-sha1-hash}
@@ -15892,15 +16886,18 @@ In an Org mode buffer, the following key bindings are 
active:
 @c @item @kbd{C-c C-v C-z} @tab @code{org-babel-switch-to-session}
 @c @end multitable
 
address@hidden Batch execution,  , Key bindings and useful functions, Working 
With Source Code
address@hidden Batch execution
 @section Batch execution
 @cindex code block, batch execution
 @cindex source code, batch execution
 
-It is possible to call functions from the command line.  This shell
-script calls @code{org-babel-tangle} on every one of its arguments.
+Org mode features, including working with source code facilities can be
+invoked from the command line.  This enables building shell scripts for batch
+processing, running automated system tasks, and expanding Org mode's
+usefulness.
 
-Be sure to adjust the paths to fit your system.
+The sample script shows batch processing of multiple files using
address@hidden
 
 @example
 #!/bin/sh
@@ -15917,35 +16914,33 @@ for i in $@@; do
 done
 
 emacs -Q --batch \
---eval "(progn
-(add-to-list 'load-path (expand-file-name \"~/src/org/lisp/\"))
-(add-to-list 'load-path (expand-file-name \"~/src/org/contrib/lisp/\" t))
-(require 'org)(require 'org-exp)(require 'ob)(require 'ob-tangle)
-(mapc (lambda (file)
-       (find-file (expand-file-name file \"$DIR\"))
-       (org-babel-tangle)
-       (kill-buffer)) '($FILES)))" 2>&1 |grep tangled
+     --eval "(progn
+     (require 'org)(require 'ob)(require 'ob-tangle)
+     (mapc (lambda (file)
+            (find-file (expand-file-name file \"$DIR\"))
+            (org-babel-tangle)
+            (kill-buffer)) '($FILES)))" 2>&1 |grep -i tangled
 @end example
 
address@hidden Miscellaneous, Hacking, Working With Source Code, Top
address@hidden Miscellaneous
 @chapter Miscellaneous
 
 @menu
-* Completion::                  M-TAB knows what you need
-* Easy Templates::              Quick insertion of structural elements
+* Completion::                  M-TAB guesses completions
+* Easy templates::              Quick insertion of structural elements
 * Speed keys::                  Electric commands at the beginning of a 
headline
 * Code evaluation security::    Org mode files evaluate inline code
-* Customization::               Adapting Org to your taste
+* Customization::               Adapting Org to changing tastes
 * In-buffer settings::          Overview of the #+KEYWORDS
 * The very busy C-c C-c key::   When in doubt, press C-c C-c
 * Clean view::                  Getting rid of leading stars in the outline
 * TTY keys::                    Using Org on a tty
-* Interaction::                 Other Emacs packages
+* Interaction::                 With other Emacs packages
 * org-crypt::                   Encrypting Org files
 @end menu
 
 
address@hidden Completion, Easy Templates, Miscellaneous, Miscellaneous
address@hidden Completion
 @section Completion
 @cindex completion, of @TeX{} symbols
 @cindex completion, of TODO keywords
@@ -15961,15 +16956,13 @@ emacs -Q --batch \
 @cindex tag completion
 @cindex link abbreviations, completion of
 
-Emacs would not be Emacs without completion, and Org mode uses it whenever it
-makes sense.  If you prefer an @i{iswitchb}- or @i{ido}-like interface for
-some of the completion prompts, you can specify your preference by setting at
-most one of the variables @code{org-completion-use-iswitchb}
address@hidden
-
-Org supports in-buffer completion.  This type of completion does
-not make use of the minibuffer.  You simply type a few letters into
-the buffer and use the key to complete text right there.
+Org has in-buffer completions.  Unlike minibuffer completions, which are
+useful for quick command interactions, Org's in-buffer completions are more
+suitable for content creation in Org documents.  Type one or more letters and
+invoke the hot key to complete the text in-place.  Depending on the context
+and the keys, Org will offer different types of completions.  No minibuffer
+is involved.  Such mode-specific hot keys have become an integral part of
+Emacs and Org provides several shortcuts.
 
 @table @kbd
 @kindex address@hidden
@@ -15996,112 +16989,123 @@ buffer.
 After @samp{[}, complete link abbreviations (@pxref{Link abbreviations}).
 @item
 After @samp{#+}, complete the special keywords like @samp{TYP_TODO} or
address@hidden which set file-specific options for Org mode.  When the
-option keyword is already complete, pressing @address@hidden again
-will insert example settings for this keyword.
+file-specific @samp{OPTIONS}.  After option keyword is complete, pressing
address@hidden@key{TAB}} again will insert example settings for that option.
 @item
-In the line after @samp{#+STARTUP: }, complete startup keywords,
-i.e., valid keys for this line.
+After @samp{#+STARTUP: }, complete startup keywords.
 @item
-Elsewhere, complete dictionary words using Ispell.
+When the point is anywhere else, complete dictionary words using Ispell.
 @end itemize
address@hidden C-M-i
+If your desktop intercepts the combo @address@hidden to switch windows, use
address@hidden or @address@hidden @key{TAB}} as an alternative or customize your
+environment.
 @end table
 
address@hidden Easy Templates, Speed keys, Completion, Miscellaneous
address@hidden Easy Templates
address@hidden Easy templates
address@hidden Easy templates
 @cindex template insertion
 @cindex insertion, of templates
 
-Org mode supports insertion of empty structural elements (like
address@hidden and @code{#+END_SRC} pairs) with just a few key
-strokes.  This is achieved through a native template expansion mechanism.
-Note that Emacs has several other template mechanisms which could be used in
-a similar way, for example @file{yasnippet}.
+With just a few keystrokes, Org's easy templates inserts empty pairs of
+structural elements, such as @code{#+BEGIN_SRC} and @code{#+END_SRC}.  Easy
+templates use an expansion mechanism, which is native to Org, in a process
+similar to @file{yasnippet} and other Emacs template expansion packages.
+
address@hidden@key{<}} @address@hidden @address@hidden completes the @samp{src} 
code
+block.
+
address@hidden<} @kbd{l} @address@hidden
+
+expands to:
+
+#+BEGIN_EXPORT latex
 
-To insert a structural element, type a @samp{<}, followed by a template
-selector and @address@hidden  Completion takes effect only when the above
-keystrokes are typed on a line by itself.
+#+END_EXPORT
 
-The following template selectors are currently supported.
+Org comes with these pre-defined easy templates:
 
 @multitable @columnfractions 0.1 0.9
address@hidden @kbd{s} @tab @code{#+BEGIN_SRC     ... #+END_SRC}
address@hidden @kbd{s} @tab @code{#+BEGIN_SRC ... #+END_SRC}
 @item @kbd{e} @tab @code{#+BEGIN_EXAMPLE ... #+END_EXAMPLE}
address@hidden @kbd{q} @tab @code{#+BEGIN_QUOTE   ... #+END_QUOTE}
address@hidden @kbd{v} @tab @code{#+BEGIN_VERSE   ... #+END_VERSE}
address@hidden @kbd{c} @tab @code{#+BEGIN_CENTER  ... #+END_CENTER}
address@hidden @kbd{l} @tab @code{#+BEGIN_LaTeX   ... #+END_LaTeX}
address@hidden @kbd{L} @tab @code{#+LaTeX:}
address@hidden @kbd{h} @tab @code{#+BEGIN_HTML    ... #+END_HTML}
address@hidden @kbd{q} @tab @code{#+BEGIN_QUOTE ... #+END_QUOTE}
address@hidden @kbd{v} @tab @code{#+BEGIN_VERSE ... #+END_VERSE}
address@hidden @kbd{c} @tab @code{#+BEGIN_CENTER ... #+END_CENTER}
address@hidden @kbd{l} @tab @code{#+BEGIN_EXPORT latex ... #+END_EXPORT}
address@hidden @kbd{L} @tab @code{#+LATEX:}
address@hidden @kbd{h} @tab @code{#+BEGIN_EXPORT html ... #+END_EXPORT}
 @item @kbd{H} @tab @code{#+HTML:}
address@hidden @kbd{a} @tab @code{#+BEGIN_ASCII   ... #+END_ASCII}
address@hidden @kbd{a} @tab @code{#+BEGIN_EXPORT ascii ... #+END_EXPORT}
 @item @kbd{A} @tab @code{#+ASCII:}
 @item @kbd{i} @tab @code{#+INDEX:} line
 @item @kbd{I} @tab @code{#+INCLUDE:} line
 @end multitable
 
-For example, on an empty line, typing "<e" and then pressing TAB, will expand
-into a complete EXAMPLE template.
+More templates can added by customizing the variable
address@hidden, whose docstring has additional details.
 
-You can install additional templates by customizing the variable
address@hidden  See the docstring of the variable for
-additional details.
-
address@hidden Speed keys, Code evaluation security, Easy Templates, 
Miscellaneous
address@hidden Speed keys
 @section Speed keys
 @cindex speed keys
+
+Single keystrokes can execute custom commands in an Org file when the cursor
+is on a headline.  Without the extra burden of a meta or modifier key, Speed
+Keys can speed navigation or execute custom commands.  Besides faster
+navigation, Speed Keys may come in handy on small mobile devices that do not
+have full keyboards.  Speed Keys may also work on TTY devices known for their
+problems when entering Emacs keychords.
+
 @vindex org-use-speed-commands
address@hidden org-speed-commands-user
+By default, Org has Speed Keys disabled.  To activate Speed Keys, set the
+variable @code{org-use-speed-commands} to a address@hidden value.  To trigger
+a Speed Key, the cursor must be at the beginning of an Org headline, before
+any of the stars.
 
-Single keys can be made to execute commands when the cursor is at the
-beginning of a headline, i.e., before the first star.  Configure the variable
address@hidden to activate this feature.  There is a
-pre-defined list of commands, and you can add more such commands using the
-variable @code{org-speed-commands-user}.  Speed keys do not only speed up
-navigation and other commands, but they also provide an alternative way to
-execute commands bound to keys that are not or not easily available on a TTY,
-or on a small mobile device with a limited keyboard.
address@hidden org-speed-commands-user
address@hidden org-speed-command-help
+Org comes with a pre-defined list of Speed Keys.  To add or modify Speed
+Keys, customize the variable, @code{org-speed-commands-user}.  For more
+details, see the variable's docstring.  With Speed Keys activated, @kbd{M-x
+org-speed-command-help}, or @kbd{?} when cursor is at the beginning of an Org
+headline, shows currently active Speed Keys, including the user-defined ones.
 
-To see which commands are available, activate the feature and press @kbd{?}
-with the cursor at the beginning of a headline.
 
address@hidden Code evaluation security, Customization, Speed keys, 
Miscellaneous
address@hidden Code evaluation security
 @section Code evaluation and security issues
 
-Org provides tools to work with the code snippets, including evaluating them.
-
-Running code on your machine always comes with a security risk.  Badly
-written or malicious code can be executed on purpose or by accident.  Org has
-default settings which will only evaluate such code if you give explicit
-permission to do so, and as a casual user of these features you should leave
-these precautions intact.
+Unlike plain text, running code comes with risk.  Each @samp{src} code block,
+in terms of risk, is equivalent to an executable file.  Org therefore puts a
+few confirmation prompts by default.  This is to alert the casual user from
+accidentally running untrusted code.
 
-For people who regularly work with such code, the confirmation prompts can
-become annoying, and you might want to turn them off.  This can be done, but
-you must be aware of the risks that are involved.
+For users who do not run code blocks or write code regularly, Org's default
+settings should suffice.  However, some users may want to tweak the prompts
+for fewer interruptions.  To weigh the risks of automatic execution of code
+blocks, here are some details about code evaluation.
 
-Code evaluation can happen under the following circumstances:
+Org evaluates code in the following circumstances:
 
 @table @i
 @item Source code blocks
-Source code blocks can be evaluated during export, or when pressing @kbd{C-c
-C-c} in the block.  The most important thing to realize here is that Org mode
-files which contain code snippets are, in a certain sense, like executable
-files.  So you should accept them and load them into Emacs only from trusted
-sources---just like you would do with a program you install on your computer.
-
-Make sure you know what you are doing before customizing the variables
-which take off the default security brakes.
+Org evaluates @samp{src} code blocks in an Org file during export.  Org also
+evaluates a @samp{src} code block with the @kbd{C-c C-c} key chord.  Users
+exporting or running code blocks must load files only from trusted sources.
+Be weary of customizing variables that remove or alter default security
+measures.
 
 @defopt org-confirm-babel-evaluate
-When t (the default), the user is asked before every code block evaluation.
-When @code{nil}, the user is not asked.  When set to a function, it is called 
with
-two arguments (language and body of the code block) and should return t to
-ask and @code{nil} not to ask.
+When @code{t}, Org prompts the user for confirmation before executing each
+code block.  When @code{nil}, Org executes code blocks without prompting the
+user for confirmation.  When this option is set to a custom function, Org
+invokes the function with these two arguments: the source code language and
+the body of the code block.  The custom function must return either a
address@hidden or @code{nil}, which determines if the user is prompted.  Each
+source code language can be handled separately through this function
+argument.
 @end defopt
 
-For example, here is how to execute "ditaa" code (which is considered safe)
-without asking:
+For example, this function enables execution of @samp{ditaa} code +blocks
+without prompting:
 
 @lisp
 (defun my-org-confirm-babel-evaluate (lang body)
@@ -16110,86 +17114,73 @@ without asking:
 @end lisp
 
 @item Following @code{shell} and @code{elisp} links
-Org has two link types that can directly evaluate code (@pxref{External
-links}).  These links can be problematic because the code to be evaluated is
-not visible.
+Org has two link types that can also directly evaluate code (@pxref{External
+links}).  Because such code is not visible, these links have a potential
+risk.  Org therefore prompts the user when it encounters such links.  The
+customization variables are:
 
 @defopt org-confirm-shell-link-function
-Function to queries user about shell link execution.
+Function that prompts the user before executing a shell link.
 @end defopt
 @defopt org-confirm-elisp-link-function
-Functions to query user for Emacs Lisp link execution.
+Function that prompts the user before executing an Emacs Lisp link.
 @end defopt
 
 @item Formulas in tables
-Formulas in tables (@pxref{The spreadsheet}) are code that is evaluated
-either by the @i{calc} interpreter, or by the @i{Emacs Lisp} interpreter.
+Org executes formulas in tables (@pxref{The spreadsheet}) either through the
address@hidden or the @emph{Emacs Lisp} interpreters.
 @end table
 
address@hidden Customization, In-buffer settings, Code evaluation security, 
Miscellaneous
address@hidden Customization
 @section Customization
 @cindex customization
 @cindex options, for customization
 @cindex variables, for customization
 
-There are more than 500 variables that can be used to customize
-Org.  For the sake of compactness of the manual, I am not
-describing the variables here.  A structured overview of customization
-variables is available with @kbd{M-x org-customize RET}.  Or select
address@hidden Org Group} from the @code{Org->Customization} menu.  Many
-settings can also be activated on a per-file basis, by putting special
-lines into the buffer (@pxref{In-buffer settings}).
+Org has more than 500 variables for customization.  They can be accessed
+through the usual @kbd{M-x org-customize RET} command.  Or through the Org
+menu, @code{Org->Customization->Browse Org Group}.  Org also has per-file
+settings for some variables (@pxref{In-buffer settings}).
 
address@hidden In-buffer settings, The very busy C-c C-c key, Customization, 
Miscellaneous
address@hidden In-buffer settings
 @section Summary of in-buffer settings
 @cindex in-buffer settings
 @cindex special keywords
+In-buffer settings start with @samp{#+}, followed by a keyword, a colon, and
+then a word for each setting.  Org accepts multiple settings on the same
+line.  Org also accepts multiple lines for a keyword.  This manual describes
+these settings throughout.  A summary follows here.
 
-Org mode uses special lines in the buffer to define settings on a
-per-file basis.  These lines start with a @samp{#+} followed by a
-keyword, a colon, and then individual words defining a setting.  Several
-setting words can be in the same line, but you can also have multiple
-lines for the keyword.  While these settings are described throughout
-the manual, here is a summary.  After changing any of those lines in the
-buffer, press @kbd{C-c C-c} with the cursor still in the line to
-activate the changes immediately.  Otherwise they become effective only
-when the file is visited again in a new Emacs session.
address@hidden C-c} activates any changes to the in-buffer settings.  Closing 
and
+reopening the Org file in Emacs also activates the changes.
 
 @vindex org-archive-location
 @table @kbd
 @item #+ARCHIVE: %s_done::
-This line sets the archive location for the agenda file.  It applies for
-all subsequent lines until the next @samp{#+ARCHIVE} line, or the end
-of the file.  The first such line also applies to any entries before it.
+Sets the archive location of the agenda file.  This location applies to the
+lines until the next @samp{#+ARCHIVE} line, if any, in the Org file.  The
+first archive location in the Org file also applies to any entries before it.
 The corresponding variable is @code{org-archive-location}.
 @item #+CATEGORY:
-This line sets the category for the agenda file.  The category applies
-for all subsequent lines until the next @samp{#+CATEGORY} line, or the
-end of the file.  The first such line also applies to any entries before it.
+Sets the category of the agenda file, which applies to the entire document.
 @item #+COLUMNS: %25ITEM ...
 @cindex property, COLUMNS
-Set the default format for columns view.  This format applies when
-columns view is invoked in locations where no @code{COLUMNS} property
-applies.
+Sets the default format for columns view.  Org uses this format for column
+views where there is no @code{COLUMNS} property.
 @item #+CONSTANTS: name1=value1 ...
 @vindex org-table-formula-constants
 @vindex org-table-formula
-Set file-local values for constants to be used in table formulas.  This
-line sets the local variable @code{org-table-formula-constants-local}.
-The global version of this variable is
address@hidden
+Set file-local values for constants that table formulas can use.  This line
+sets the local variable @code{org-table-formula-constants-local}.  The global
+version of this variable is @code{org-table-formula-constants}.
 @item #+FILETAGS: :tag1:tag2:tag3:
-Set tags that can be inherited by any entry in the file, including the
+Set tags that all entries in the file will inherit from here, including the
 top-level entries.
address@hidden #+DRAWERS: NAME1 ...
address@hidden org-drawers
-Set the file-local set of additional drawers.  The corresponding global
-variable is @code{org-drawers}.
 @item #+LINK: linkword replace
 @vindex org-link-abbrev-alist
-These lines (several are allowed) specify link abbreviations.
address@hidden abbreviations}.  The corresponding variable is
address@hidden
+Each line specifies one abbreviation for one link.  Use multiple
address@hidden:} lines for more, @pxref{Link abbreviations}.  The corresponding
+variable is @code{org-link-abbrev-alist}.
 @item #+PRIORITIES: highest lowest default
 @vindex org-highest-priority
 @vindex org-lowest-priority
@@ -16202,22 +17193,22 @@ This line sets a default inheritance value for 
entries in the current
 buffer, most useful for specifying the allowed values of a property.
 @cindex #+SETUPFILE
 @item #+SETUPFILE: file
-This line defines a file that holds more in-buffer setup.  Normally this is
-entirely ignored.  Only when the buffer is parsed for option-setting lines
-(i.e., when starting Org mode for a file, when pressing @kbd{C-c C-c} in a
-settings line, or when exporting), then the contents of this file are parsed
-as if they had been included in the buffer.  In particular, the file can be
-any other Org mode file with internal setup.  You can visit the file the
-cursor is in the line with @kbd{C-c '}.
+The setup file is for additional in-buffer settings.  Org loads this file and
+parses it for any settings in it only when Org opens the main file.  @kbd{C-c
+C-c} on the settings line will also parse and load.  Org also parses and
+loads the file during normal exporting process.  Org parses the contents of
+this file as if it was included in the buffer.  It can be another Org file.
+To visit the file, @kbd{C-c '} while the cursor is on the line with the file
+name.
 @item #+STARTUP:
 @cindex #+STARTUP
-This line sets options to be used at startup of Org mode, when an
-Org file is being visited.
+Startup options Org uses when first visiting a file.
 
 The first set of options deals with the initial visibility of the outline
 tree.  The corresponding variable for global default settings is
address@hidden, with a default value @code{t}, which means
address@hidden
address@hidden with a default value of @code{t}, which is the same
+as @code{overview}.
+
 @vindex org-startup-folded
 @cindex @code{overview}, STARTUP keyword
 @cindex @code{content}, STARTUP keyword
@@ -16234,17 +17225,17 @@ showeverything   @r{show even drawer contents}
 @cindex @code{indent}, STARTUP keyword
 @cindex @code{noindent}, STARTUP keyword
 Dynamic virtual indentation is controlled by the variable
address@hidden@footnote{Emacs 23 and Org mode 6.29 are required}
address@hidden
 @example
 indent     @r{start with @code{org-indent-mode} turned on}
 noindent   @r{start with @code{org-indent-mode} turned off}
 @end example
 
 @vindex org-startup-align-all-tables
-Then there are options for aligning tables upon visiting a file.  This
-is useful in files containing narrowed table columns.  The corresponding
-variable is @code{org-startup-align-all-tables}, with a default value
address@hidden
+Aligns tables consistently upon visiting a file; useful for restoring
+narrowed table columns.  The corresponding variable is
address@hidden with @code{nil} as default value.
+
 @cindex @code{align}, STARTUP keyword
 @cindex @code{noalign}, STARTUP keyword
 @example
@@ -16253,9 +17244,9 @@ noalign    @r{don't align tables on startup}
 @end example
 
 @vindex org-startup-with-inline-images
-When visiting a file, inline images can be automatically displayed.  The
-corresponding variable is @code{org-startup-with-inline-images}, with a
-default value @code{nil} to avoid delays when visiting a file.
+Whether Org should automatically display inline images.  The corresponding
+variable is @code{org-startup-with-inline-images}, with a default value
address@hidden to avoid delays when visiting a file.
 @cindex @code{inlineimages}, STARTUP keyword
 @cindex @code{noinlineimages}, STARTUP keyword
 @example
@@ -16264,10 +17255,9 @@ noinlineimages @r{don't show inline images on startup}
 @end example
 
 @vindex org-startup-with-latex-preview
-When visiting a file, @LaTeX{} fragments can be converted to images
-automatically.  The variable @code{org-startup-with-latex-preview} which
-controls this behavior, is set to @code{nil} by default to avoid delays on
-startup.
+Whether Org should automatically convert @LaTeX{} fragments to images.  The
+variable @code{org-startup-with-latex-preview}, which controls this setting,
+is set to @code{nil} by default to avoid startup delays.
 @cindex @code{latexpreview}, STARTUP keyword
 @cindex @code{nolatexpreview}, STARTUP keyword
 @example
@@ -16328,21 +17318,21 @@ nologstatesreversed @r{do not reverse the order of 
states notes}
 
 @vindex org-hide-leading-stars
 @vindex org-odd-levels-only
-Here are the options for hiding leading stars in outline headings, and for
-indenting outlines.  The corresponding variables are
address@hidden and @code{org-odd-levels-only}, both with a
-default setting @code{nil} (meaning @code{showstars} and @code{oddeven}).
+These options hide leading stars in outline headings, and indent outlines.
+The corresponding variables are @code{org-hide-leading-stars} and
address@hidden, both with a default setting of @code{nil}
+(meaning @code{showstars} and @code{oddeven}).
 @cindex @code{hidestars}, STARTUP keyword
 @cindex @code{showstars}, STARTUP keyword
 @cindex @code{odd}, STARTUP keyword
 @cindex @code{even}, STARTUP keyword
 @example
-hidestars  @r{make all but one of the stars starting a headline invisible.}
-showstars  @r{show all stars starting a headline}
-indent     @r{virtual indentation according to outline level}
-noindent   @r{no virtual indentation according to outline level}
-odd        @r{allow only odd outline levels (1,3,...)}
-oddeven    @r{allow all outline levels}
+hidestars  @r{hide all stars on the headline except one.}
+showstars  @r{show all stars on the headline}
+indent     @r{virtual indents according to the outline level}
+noindent   @r{no virtual indents}
+odd        @r{show odd outline levels only (1,3,...)}
+oddeven    @r{show all outline levels}
 @end example
 
 @vindex org-put-time-stamp-overlays
@@ -16368,8 +17358,8 @@ constSI    @address@hidden should use the SI unit 
system}
 @vindex org-footnote-define-inline
 @vindex org-footnote-auto-label
 @vindex org-footnote-auto-adjust
-To influence footnote settings, use the following keywords.  The
-corresponding variables are @code{org-footnote-define-inline},
+For footnote settings, use the following keywords.  The corresponding
+variables are @code{org-footnote-define-inline},
 @code{org-footnote-auto-label}, and @code{org-footnote-auto-adjust}.
 @cindex @code{fninline}, STARTUP keyword
 @cindex @code{nofninline}, STARTUP keyword
@@ -16414,67 +17404,57 @@ entitiesplain   @r{Leave entities plain}
 
 @item #+TAGS:  TAG1(c1) TAG2(c2)
 @vindex org-tag-alist
-These lines (several such lines are allowed) specify the valid tags in
-this file, and (potentially) the corresponding @emph{fast tag selection}
-keys.  The corresponding variable is @code{org-tag-alist}.
+These lines specify valid tags for this file.  Org accepts multiple tags
+lines.  Tags could correspond to the @emph{fast tag selection} keys.  The
+corresponding variable is @code{org-tag-alist}.
 @cindex #+TBLFM
 @item #+TBLFM:
-This line contains the formulas for the table directly above the line.
-
-Table can have multiple lines containing @samp{#+TBLFM:}.  Note
-that only the first line of @samp{#+TBLFM:} will be applied when
-you recalculate the table.  For more details see @ref{Using
-multiple #+TBLFM lines} in @ref{Editing and debugging formulas}.
-
+This line is for formulas for the table directly above.  A table can have
+multiple @samp{#+TBLFM:} lines.  On table recalculation, Org applies only the
+first @samp{#+TBLFM:} line.  For details see @ref{Using multiple #+TBLFM
+lines} in @ref{Editing and debugging formulas}.
 @item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+DATE:,
 @itemx #+OPTIONS:, #+BIND:,
address@hidden #+DESCRIPTION:, #+KEYWORDS:,
address@hidden #+LaTeX_HEADER:, #+LaTeX_HEADER_EXTRA:,
address@hidden #+HTML_HEAD:, #+HTML_HEAD_EXTRA:, #+HTML_LINK_UP:, 
#+HTML_LINK_HOME:,
 @itemx #+SELECT_TAGS:, #+EXCLUDE_TAGS:
 These lines provide settings for exporting files.  For more details see
 @ref{Export settings}.
 @item #+TODO:    #+SEQ_TODO:   #+TYP_TODO:
 @vindex org-todo-keywords
-These lines set the TODO keywords and their interpretation in the
-current file.  The corresponding variable is @code{org-todo-keywords}.
+These lines set the TODO keywords and their significance to the current file.
+The corresponding variable is @code{org-todo-keywords}.
 @end table
 
address@hidden The very busy C-c C-c key, Clean view, In-buffer settings, 
Miscellaneous
address@hidden The very busy C-c C-c key
 @section The very busy C-c C-c key
 @kindex C-c C-c
 @cindex C-c C-c, overview
 
-The key @kbd{C-c C-c} has many purposes in Org, which are all
-mentioned scattered throughout this manual.  One specific function of
-this key is to add @emph{tags} to a headline (@pxref{Tags}).  In many
-other circumstances it means something like @emph{``Hey Org, look
-here and update according to what you see here''}.  Here is a summary of
-what this means in different contexts.
+The @kbd{C-c C-c} key in Org serves many purposes depending on the context.
+It is probably the most over-worked, multi-purpose key combination in Org.
+Its uses are well-documented through out this manual, but here is a
+consolidated list for easy reference.
 
 @itemize @minus
 @item
-If there are highlights in the buffer from the creation of a sparse
-tree, or from clock display, remove these highlights.
+If any highlights shown in the buffer from the creation of a sparse tree, or
+from clock display, remove such highlights.
 @item
-If the cursor is in one of the special @code{#+KEYWORD} lines, this
-triggers scanning the buffer for these lines and updating the
-information.
+If the cursor is in one of the special @code{#+KEYWORD} lines, scan the
+buffer for these lines and update the information.
 @item
-If the cursor is inside a table, realign the table.  This command
-works even if the automatic table editor has been turned off.
+If the cursor is inside a table, realign the table.  The table realigns even
+if automatic table editor is turned off.
 @item
 If the cursor is on a @code{#+TBLFM} line, re-apply the formulas to
 the entire table.
 @item
-If the current buffer is a capture buffer, close the note and file it.
-With a prefix argument, file it, without further interaction, to the
-default location.
+If the current buffer is a capture buffer, close the note and file it.  With
+a prefix argument, also jump to the target location after saving the note.
 @item
 If the cursor is on a @code{<<<target>>>}, update radio targets and
 corresponding links in this buffer.
 @item
-If the cursor is in a property line or at the start or end of a property
+If the cursor is on a property line or at the start or end of a property
 drawer, offer property commands.
 @item
 If the cursor is at a footnote reference, go to the corresponding
@@ -16494,18 +17474,18 @@ block is updated.
 If the cursor is at a timestamp, fix the day name in the timestamp.
 @end itemize
 
address@hidden Clean view, TTY keys, The very busy C-c C-c key, Miscellaneous
address@hidden Clean view
 @section A cleaner outline view
 @cindex hiding leading stars
 @cindex dynamic indentation
 @cindex odd-levels-only outlines
 @cindex clean outline view
 
-Some people find it noisy and distracting that the Org headlines start with a
-potentially large number of stars, and that text below the headlines is not
-indented.  While this is no problem when writing a @emph{book-like} document
-where the outline headings are really section headings, in a more
address@hidden outline, indented structure is a lot cleaner:
+Org's default outline with stars and no indents can become too cluttered for
+short documents.  For @emph{book-like} long documents, the effect is not as
+noticeable.  Org provides an alternate stars and indentation scheme, as shown
+on the right in the following table.  It uses only one star and indents text
+to line with the heading:
 
 @example
 @group
@@ -16521,38 +17501,40 @@ more text                        |          more text
 
 @noindent
 
-If you are using at least Emacs address@hidden 23.1 can actually crash
-with @code{org-indent-mode}} and version 6.29 of Org, this kind of view can
-be achieved dynamically at display time using @code{org-indent-mode}.  In
-this minor mode, all lines are prefixed for display with the necessary amount
-of address@hidden@code{org-indent-mode} also sets the @code{wrap-prefix}
-property, such that @code{visual-line-mode} (or purely setting
address@hidden) wraps long lines (including headlines) correctly indented.
-}.  Also headlines are prefixed with additional stars, so that the amount of
-indentation shifts by address@hidden the variable
address@hidden  spaces per level.  All headline
-stars but the last one are made invisible using the @code{org-hide}
address@hidden on @code{org-indent-mode} sets
+To turn this mode on, use the minor mode, @code{org-indent-mode}.  Text lines
+that are not headlines are prefixed with spaces to vertically align with the
+headline address@hidden @code{org-indent-mode} also sets the
address@hidden correctly for indenting and wrapping long lines of
+headlines or text.  This minor mode handles @code{visual-line-mode} and
+directly applied settings through @code{word-wrap}.}.
+
+To make more horizontal space, the headlines are shifted by two stars.  This
+can be configured by the @code{org-indent-indentation-per-level} variable.
+Only one star on each headline is visible, the rest are masked with the same
+font color as the background.  This font face can be configured with the
address@hidden variable.
+
+Note that turning on @code{org-indent-mode} sets
 @code{org-hide-leading-stars} to @code{t} and @code{org-adapt-indentation} to
address@hidden; see below under @samp{2.} for more information on how this
-works.  You can turn on @code{org-indent-mode} for all files by customizing
-the variable @code{org-startup-indented}, or you can turn it on for
-individual files using
address@hidden; @samp{2.} below shows how this works.
+
+To globally turn on @code{org-indent-mode} for all files, customize the
+variable @code{org-startup-indented}.
+
+To turn on indenting for individual files, use @code{#+STARTUP} option as
+follows:
 
 @example
 #+STARTUP: indent
 @end example
 
-If you want a similar effect in an earlier version of Emacs and/or Org, or if
-you want the indentation to be hard space characters so that the plain text
-file looks as similar as possible to the Emacs display, Org supports you in
-the following way:
+Indent on startup makes Org use hard spaces to align text with headings as
+shown in examples below.
 
 @enumerate
 @item
 @emph{Indentation of text below address@hidden
-You may indent text below each headline to make the left boundary line up
-with the headline, like
+Indent text to align with the headline.
 
 @example
 *** 3rd level
@@ -16560,23 +17542,21 @@ with the headline, like
 @end example
 
 @vindex org-adapt-indentation
-Org supports this with paragraph filling, line wrapping, and structure
address@hidden also the variable @code{org-adapt-indentation}.},
-preserving or adapting the indentation as appropriate.
+Org adapts indentations with paragraph filling, line wrapping, and structure
address@hidden see the variable @code{org-adapt-indentation}.}.
 
 @item
 @vindex org-hide-leading-stars
address@hidden leading address@hidden You can modify the display in such a way 
that
-all leading stars become invisible.  To do this in a global way, configure
-the variable @code{org-hide-leading-stars} or change this on a per-file basis
-with
address@hidden leading address@hidden Org can make leading stars invisible.  For
+global preference, configure the variable @code{org-hide-leading-stars}.  For
+per-file preference, use these file @code{#+STARTUP} options:
 
 @example
 #+STARTUP: hidestars
 #+STARTUP: showstars
 @end example
 
-With hidden stars, the tree becomes:
+With stars hidden, the tree is shown as:
 
 @example
 @group
@@ -16589,50 +17569,39 @@ With hidden stars, the tree becomes:
 
 @noindent
 @vindex org-hide @r{(face)}
-The leading stars are not truly replaced by whitespace, they are only
-fontified with the face @code{org-hide} that uses the background color as
-font color.  If you are not using either white or black background, you may
-have to customize this face to get the wanted effect.  Another possibility is
-to set this font such that the extra stars are @i{almost} invisible, for
-example using the color @code{grey90} on a white background.
+Because Org makes the font color same as the background color to hide to
+stars, sometimes @code{org-hide} face may need tweaking to get the effect
+right.  For some black and white combinations, @code{grey90} on a white
+background might mask the stars better.
 
 @item
 @vindex org-odd-levels-only
-Things become cleaner still if you skip all the even levels and use only odd
-levels 1, 3, 5..., effectively adding two stars to go from one outline level
-to the address@hidden you need to specify a level for a property search
-or refile targets, @samp{LEVEL=2} will correspond to 3 stars, etc.}.  In this
-way we get the outline view shown at the beginning of this section.  In order
-to make the structure editing and export commands handle this convention
-correctly, configure the variable @code{org-odd-levels-only}, or set this on
-a per-file basis with one of the following lines:
+Using stars for only odd levels, 1, 3, 5, @dots{}, can also clean up the
+clutter.  This removes two stars from each address@hidden
address@hidden has 3 stars, @samp{LEVEL=3} has 4 stars, and so on}.  For Org
+to properly handle this cleaner structure during edits and exports, configure
+the variable @code{org-odd-levels-only}.  To set this per-file, use either
+one of the following lines:
 
 @example
 #+STARTUP: odd
 #+STARTUP: oddeven
 @end example
 
-You can convert an Org file from single-star-per-level to the
-double-star-per-level convention with @kbd{M-x org-convert-to-odd-levels
-RET} in that file.  The reverse operation is @kbd{M-x
-org-convert-to-oddeven-levels}.
+To switch between single and double stars layouts, use @kbd{M-x
+org-convert-to-odd-levels RET} and @kbd{M-x org-convert-to-oddeven-levels}.
 @end enumerate
 
address@hidden TTY keys, Interaction, Clean view, Miscellaneous
address@hidden TTY keys
 @section Using Org on a tty
 @cindex tty key bindings
 
-Because Org contains a large number of commands, by default many of
-Org's core commands are bound to keys that are generally not
-accessible on a tty, such as the cursor keys (@key{left}, @key{right},
address@hidden, @key{down}), @key{TAB} and @key{RET}, in particular when used
-together with modifiers like @key{Meta} and/or @key{Shift}.  To access
-these commands on a tty when special keys are unavailable, the following
-alternative bindings can be used.  The tty bindings below will likely be
-more cumbersome; you may find for some of the bindings below that a
-customized workaround suits you better.  For example, changing a timestamp
-is really only fun with @address@hidden keys, whereas on a
-tty you would rather use @kbd{C-c .} to re-insert the timestamp.
+Org provides alternative key bindings for TTY and modern mobile devices that
+cannot handle cursor keys and complex modifier key chords.  Some of these
+workarounds may be more cumbersome than necessary.  Users should look into
+customizing these further based on their usage needs.  For example, the
+normal @address@hidden for editing timestamp might be better with
address@hidden .} chord.
 
 @multitable @columnfractions 0.15 0.2 0.1 0.2
 @item @b{Default} @tab @b{Alternative 1} @tab @b{Speed key} @tab 
@b{Alternative 2}
@@ -16657,74 +17626,62 @@ tty you would rather use @kbd{C-c .} to re-insert the 
timestamp.
 @end multitable
 
 
address@hidden Interaction, org-crypt, TTY keys, Miscellaneous
address@hidden Interaction
 @section Interaction with other packages
 @cindex packages, interaction with other
-Org lives in the world of GNU Emacs and interacts in various ways
-with other code out there.
+Org's compatibility and the level of interaction with other Emacs packages
+are documented here.
+
 
 @menu
 * Cooperation::                 Packages Org cooperates with
 * Conflicts::                   Packages that lead to conflicts
 @end menu
 
address@hidden Cooperation, Conflicts, Interaction, Interaction
address@hidden Cooperation
 @subsection Packages that Org cooperates with
 
 @table @asis
 @cindex @file{calc.el}
 @cindex Gillespie, Dave
 @item @file{calc.el} by Dave Gillespie
-Org uses the Calc package for implementing spreadsheet
-functionality in its tables (@pxref{The spreadsheet}).  Org
-checks for the availability of Calc by looking for the function
address@hidden which will have been autoloaded during setup if Calc has
-been installed properly.  As of Emacs 22, Calc is part of the Emacs
-distribution.  Another possibility for interaction between the two
-packages is using Calc for embedded calculations.  @xref{Embedded Mode,
-, Embedded Mode, calc, GNU Emacs Calc Manual}.
+Org uses the Calc package for tables to implement spreadsheet functionality
+(@pxref{The spreadsheet}).  Org also uses Calc for embedded calculations.
address@hidden Mode, , Embedded Mode, calc, GNU Emacs Calc Manual}.
 @item @file{constants.el} by Carsten Dominik
 @cindex @file{constants.el}
 @cindex Dominik, Carsten
 @vindex org-table-formula-constants
-In a table formula (@pxref{The spreadsheet}), it is possible to use
-names for natural constants or units.  Instead of defining your own
-constants in the variable @code{org-table-formula-constants}, install
-the @file{constants} package which defines a large number of constants
-and units, and lets you use unit prefixes like @samp{M} for
address@hidden, etc.  You will need version 2.0 of this package, available
-at @url{http://www.astro.uva.nl/~dominik/Tools}.  Org checks for
-the function @code{constants-get}, which has to be autoloaded in your
-setup.  See the installation instructions in the file
address@hidden
+Org can use names for constants in formulas in tables.  Org can also use
+calculation suffixes for units, such as @samp{M} for @samp{Mega}.  For a
+standard collection of such constants, install the @file{constants} package.
+Install version 2.0 of this package, available at
address@hidden://www.astro.uva.nl/~dominik/Tools}.  Org checks if the function
address@hidden has been autoloaded.  Installation instructions are in
+the file, @file{constants.el}.
 @item @file{cdlatex.el} by Carsten Dominik
 @cindex @file{cdlatex.el}
 @cindex Dominik, Carsten
-Org mode can make use of the address@hidden package to efficiently enter
address@hidden fragments into Org files.  See @ref{CDLaTeX mode}.
+Org mode can use address@hidden package to efficiently enter @LaTeX{} fragments
+into Org files (@pxref{CDLaTeX mode}).
 @item @file{imenu.el} by Ake Stenhoff and Lars Lindberg
 @cindex @file{imenu.el}
-Imenu allows menu access to an index of items in a file.  Org mode
-supports Imenu---all you need to do to get the index is the following:
+Imenu creates dynamic menus based on an index of items in a file.  Org mode
+supports Imenu menus.  Enable it with a mode hook as follows:
 @lisp
 (add-hook 'org-mode-hook
           (lambda () (imenu-add-to-menubar "Imenu")))
 @end lisp
 @vindex org-imenu-depth
-By default the index is two levels deep---you can modify the depth using
-the option @code{org-imenu-depth}.
address@hidden @file{remember.el} by John Wiegley
address@hidden @file{remember.el}
address@hidden Wiegley, John
-Org used to use this package for capture, but no longer does.
+By default the Imenu index is two levels deep.  Change the index depth using
+thes variable, @code{org-imenu-depth}.
 @item @file{speedbar.el} by Eric M. Ludlam
 @cindex @file{speedbar.el}
 @cindex Ludlam, Eric M.
-Speedbar is a package that creates a special frame displaying files and
-index items in files.  Org mode supports Speedbar and allows you to
-drill into Org files directly from the Speedbar.  It also allows you to
-restrict the scope of agenda commands to a file or a subtree by using
-the command @kbd{<} in the Speedbar frame.
+Speedbar package creates a special Emacs frame for displaying files and index
+items in files.  Org mode supports Speedbar; users can drill into Org files
+directly from the Speedbar.  The @kbd{<} in the Speedbar frame tweeks the
+agenda commands to that file or to a subtree.
 @cindex @file{table.el}
 @item @file{table.el} by Takaaki Ota
 @kindex C-c C-c
@@ -16733,13 +17690,11 @@ the command @kbd{<} in the Speedbar frame.
 @cindex Ota, Takaaki
 
 Complex ASCII tables with automatic line wrapping, column- and row-spanning,
-and alignment can be created using the Emacs table package by Takaaki Ota
-(@uref{http://sourceforge.net/projects/table}, and also part of Emacs 22).
-Org mode will recognize these tables and export them properly.  Because of
-interference with other Org mode functionality, you unfortunately cannot edit
-these tables directly in the buffer.  Instead, you need to use the command
address@hidden '} to edit them, similar to source code snippets.
-
+and alignment can be created using the Emacs table package by Takaaki Ota.
+Org mode recognizes such tables and export them properly.  @kbd{C-c '} to
+edit these tables in a special buffer, much like Org's @samp{src} code
+blocks.  Because of interference with other Org mode functionality, Takaaki
+Ota tables cannot be edited directly in the Org buffer.
 @table @kbd
 @orgcmd{C-c ',org-edit-special}
 Edit a @file{table.el} table.  Works when the cursor is in a table.el table.
@@ -16747,50 +17702,37 @@ Edit a @file{table.el} table.  Works when the cursor 
is in a table.el table.
 @orgcmd{C-c ~,org-table-create-with-table.el}
 Insert a @file{table.el} table.  If there is already a table at point, this
 command converts it between the @file{table.el} format and the Org mode
-format.  See the documentation string of the command
address@hidden for the restrictions under which this is
-possible.
+format.  See the documentation string of the command @code{org-convert-table}
+for details.
 @end table
address@hidden is part of Emacs since Emacs 22.
address@hidden @file{footnote.el} by Steven L. Baur
address@hidden @file{footnote.el}
address@hidden Baur, Steven L.
-Org mode recognizes numerical footnotes as provided by this package.
-However, Org mode also has its own footnote support (@pxref{Footnotes}),
-which makes using @file{footnote.el} unnecessary.
 @end table
 
address@hidden Conflicts,  , Cooperation, Interaction
address@hidden Packages that lead to conflicts with Org mode
address@hidden Conflicts
address@hidden Packages that conflict with Org mode
 
 @table @asis
 
 @cindex @code{shift-selection-mode}
 @vindex org-support-shift-select
-In Emacs 23, @code{shift-selection-mode} is on by default, meaning that
-cursor motions combined with the shift key should start or enlarge regions.
-This conflicts with the use of @address@hidden commands in Org to change
-timestamps, TODO keywords, priorities, and item bullet types if the cursor is
-at such a location.  By default, @address@hidden commands outside
-special contexts don't do anything, but you can customize the variable
address@hidden  Org mode then tries to accommodate shift
-selection by (i) using it outside of the special contexts where special
-commands apply, and by (ii) extending an existing active region even if the
-cursor moves across a special context.
+In Emacs, @code{shift-selection-mode} combines cursor motions with shift key
+to enlarge regions.  Emacs sets this mode by default.  This conflicts with
+Org's use of @address@hidden commands to change timestamps, TODO
+keywords, priorities, and item bullet types, etc.  Since @address@hidden
+commands outside of specific contexts don't do anything, Org offers the
+variable @code{org-support-shift-select} for customization.  Org mode
+accommodates shift selection by (i) making it available outside of the
+special contexts where special commands apply, and (ii) extending an
+existing active region even if the cursor moves across a special context.
 
 @item @file{CUA.el} by Kim. F. Storm
 @cindex @file{CUA.el}
 @cindex Storm, Kim. F.
 @vindex org-replace-disputed-keys
-Key bindings in Org conflict with the @kbd{S-<cursor>} keys used by CUA mode
-(as well as @code{pc-select-mode} and @code{s-region-mode}) to select and 
extend the
-region.  In fact, Emacs 23 has this built-in in the form of
address@hidden, see previous paragraph.  If you are using Emacs
-23, you probably don't want to use another package for this purpose.  However,
-if you prefer to leave these keys to a different package while working in
-Org mode, configure the variable @code{org-replace-disputed-keys}.  When set,
-Org will move the following key bindings in Org files, and in the agenda
-buffer (but not during date selection).
+Org key bindings conflict with @kbd{S-<cursor>} keys used by CUA mode.  For
+Org to relinquish these bindings to CUA mode, configure the variable
address@hidden  When set, Org moves the following key
+bindings in Org files, and in the agenda buffer (but not during date
+selection).
 
 @example
 S-UP      @result{}  M-p             S-DOWN     @result{}  M-n
@@ -16799,9 +17741,8 @@ C-S-LEFT  @result{}  M-S--           C-S-RIGHT  
@result{}  M-S-+
 @end example
 
 @vindex org-disputed-keys
-Yes, these are unfortunately more difficult to remember.  If you want
-to have other replacement keys, look at the variable
address@hidden
+Yes, these are unfortunately more difficult to remember.  To define a
+different replacement keys, look at the variable @code{org-disputed-keys}.
 
 @item @file{ecomplete.el} by Lars Magne Ingebrigtsen @email{larsi@@gnus.org}
 @cindex @file{ecomplete.el}
@@ -16819,9 +17760,8 @@ manually when needed in the messages body.
 @cindex @file{filladapt.el}
 
 Org mode tries to do the right thing when filling paragraphs, list items and
-other elements.  Many users reported they had problems using both
address@hidden and Org mode, so a safe thing to do is to disable it like
-this:
+other elements.  Many users reported problems using both @file{filladapt.el}
+and Org mode, so a safe thing to do is to disable filladapt like this:
 
 @lisp
 (add-hook 'org-mode-hook 'turn-off-filladapt-mode)
@@ -16836,20 +17776,19 @@ fixed this problem:
 @lisp
 (add-hook 'org-mode-hook
           (lambda ()
-            (org-set-local 'yas/trigger-key [tab])
+            (setq-local yas/trigger-key [tab])
             (define-key yas/keymap [tab] 'yas/next-field-or-maybe-expand)))
 @end lisp
 
 The latest version of yasnippet doesn't play well with Org mode.  If the
-above code does not fix the conflict, start by defining the following
-function:
+above code does not fix the conflict, first define the following function:
 
 @lisp
 (defun yas/org-very-safe-expand ()
   (let ((yas/fallback-behavior 'return-nil)) (yas/expand)))
 @end lisp
 
-Then, tell Org mode what to do with the new function:
+Then tell Org mode to use that function:
 
 @lisp
 (add-hook 'org-mode-hook
@@ -16892,21 +17831,19 @@ another key for this command, or override the key in
 
 @end table
 
address@hidden org-crypt,  , Interaction, Miscellaneous
address@hidden org-crypt
 @section org-crypt.el
 @cindex @file{org-crypt.el}
 @cindex @code{org-decrypt-entry}
 
-Org-crypt will encrypt the text of an entry, but not the headline, or
-properties.  Org-crypt uses the Emacs EasyPG library to encrypt and decrypt
-files.
+Org crypt encrypts the text of an Org entry, but not the headline, or
+properties.  Org crypt uses the Emacs EasyPG library to encrypt and decrypt.
 
 Any text below a headline that has a @samp{:crypt:} tag will be automatically
-be encrypted when the file is saved.  If you want to use a different tag just
-customize the @code{org-crypt-tag-matcher} setting.
+be encrypted when the file is saved.  To use a different tag, customize the
address@hidden variable.
 
-To use org-crypt it is suggested that you have the following in your
address@hidden:
+Suggested Org crypt settings in Emacs init file:
 
 @lisp
 (require 'org-crypt)
@@ -16928,14 +17865,14 @@ To use org-crypt it is suggested that you have the 
following in your
   ;; # -*- buffer-auto-save-file-name: nil; -*-
 @end lisp
 
-Excluding the crypt tag from inheritance prevents already encrypted text
-being encrypted again.
+Excluding the crypt tag from inheritance prevents encrypting previously
+encrypted text.
 
address@hidden Hacking, MobileOrg, Miscellaneous, Top
address@hidden Hacking
 @appendix Hacking
 @cindex hacking
 
-This appendix covers some aspects where users can extend the functionality of
+This appendix covers some areas where users can extend the functionality of
 Org.
 
 @menu
@@ -16953,38 +17890,35 @@ Org.
 * Using the mapping API::       Mapping over all or selected entries
 @end menu
 
address@hidden Hooks, Add-on packages, Hacking, Hacking
address@hidden Hooks
 @section Hooks
 @cindex hooks
 
-Org has a large number of hook variables that can be used to add
-functionality.  This appendix about hacking is going to illustrate the
-use of some of them.  A complete list of all hooks with documentation is
-maintained by the Worg project and can be found at
address@hidden://orgmode.org/worg/org-configs/org-hooks.php}.
+Org has a large number of hook variables for adding functionality.  This
+appendix illustrates using a few.  A complete list of hooks with
+documentation is maintained by the Worg project at
address@hidden://orgmode.org/worg/doc.html#hooks}.
 
address@hidden Add-on packages, Adding hyperlink types, Hooks, Hacking
address@hidden Add-on packages
 @section Add-on packages
 @cindex add-on packages
 
-A large number of add-on packages have been written by various authors.
+Various authors wrote a large number of add-on packages for Org.
 
 These packages are not part of Emacs, but they are distributed as contributed
 packages with the separate release available at @uref{http://orgmode.org}.
 See the @file{contrib/README} file in the source code directory for a list of
-contributed files.  You may also find some more information on the Worg page:
+contributed files.  Worg page with more information is at:
 @uref{http://orgmode.org/worg/org-contrib/}.
 
address@hidden Adding hyperlink types, Adding export back-ends, Add-on 
packages, Hacking
address@hidden Adding hyperlink types
 @section Adding hyperlink types
 @cindex hyperlinks, adding new types
 
-Org has a large number of hyperlink types built-in
-(@pxref{Hyperlinks}).  If you would like to add new link types, Org
-provides an interface for doing so.  Let's look at an example file,
address@hidden, that will add support for creating links like
address@hidden:printf][The printf manpage]]} to show Unix manual pages inside
-Emacs:
+Org has many built-in hyperlink types (@pxref{Hyperlinks}), and an interface
+for adding new link types.  The example file, @file{org-man.el}, shows the
+process of adding Org links to Unix man pages, which look like this:
address@hidden:printf][The printf manpage]]}:
 
 @lisp
 ;;; org-man.el - Support for links to manpages in Org
@@ -17029,149 +17963,118 @@ PATH should be a topic that can be thrown at the 
man command."
 @end lisp
 
 @noindent
-You would activate this new link type in @file{.emacs} with
+To activate links to man pages in Org, enter this in the init file:
 
 @lisp
 (require 'org-man)
 @end lisp
 
 @noindent
-Let's go through the file and see what it does.
+A review of @file{org-man.el}:
 @enumerate
 @item
-It does @code{(require 'org)} to make sure that @file{org.el} has been
-loaded.
+First, @code{(require 'org)} ensures @file{org.el} is loaded.
 @item
-The next line calls @code{org-add-link-type} to define a new link type
-with prefix @samp{man}.  The call also contains the name of a function
-that will be called to follow such a link.
+The @code{org-add-link-type} defines a new link type with @samp{man} prefix.
+The call contains the function to call that follows the link type.
 @item
 @vindex org-store-link-functions
-The next line adds a function to @code{org-store-link-functions}, in
-order to allow the command @kbd{C-c l} to record a useful link in a
-buffer displaying a man page.
+The next line adds a function to @code{org-store-link-functions} that records
+a useful link with the command @kbd{C-c l} in a buffer displaying a man page.
 @end enumerate
 
-The rest of the file defines the necessary variables and functions.
-First there is a customization variable that determines which Emacs
-command should be used to display man pages.  There are two options,
address@hidden and @code{woman}.  Then the function to follow a link is
-defined.  It gets the link path as an argument---in this case the link
-path is just a topic for the manual command.  The function calls the
-value of @code{org-man-command} to display the man page.
-
-Finally the function @code{org-man-store-link} is defined.  When you try
-to store a link with @kbd{C-c l}, this function will be called to
-try to make a link.  The function must first decide if it is supposed to
-create the link for this buffer type; we do this by checking the value
-of the variable @code{major-mode}.  If not, the function must exit and
-return the value @code{nil}.  If yes, the link is created by getting the
-manual topic from the buffer name and prefixing it with the string
address@hidden:}.  Then it must call the command @code{org-store-link-props}
-and set the @code{:type} and @code{:link} properties.  Optionally you
-can also set the @code{:description} property to provide a default for
-the link description when the link is later inserted into an Org
-buffer with @kbd{C-c C-l}.
-
-When it makes sense for your new link type, you may also define a function
address@hidden that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
-
address@hidden Adding export back-ends, Context-sensitive commands, Adding 
hyperlink types, Hacking
+The rest of the file defines necessary variables and functions.  First is the
+customization variable @code{org-man-command}.  It has two options,
address@hidden and @code{woman}.  Next is a function whose argument is the link
+path, which for man pages is the topic of the man command.  To follow the
+link, the function calls the @code{org-man-command} to display the man page.
+
+
address@hidden l} constructs and stores the link.
+
address@hidden l} calls the function @code{org-man-store-link}, which first 
checks
+if the @code{major-mode} is appropriate.  If check fails, the function
+returns @code{nil}.  Otherwise the function makes a link string by combining
+the @samp{man:} prefix with the man topic.  The function then calls
address@hidden with @code{:type} and @code{:link} properties.  A
address@hidden:description} property is an optional string that is displayed 
when the
+function inserts the link in the Org buffer.
+
address@hidden C-l} inserts the stored link.
+
+To define new link types, define a function that implements completion
+support with @kbd{C-c C-l}.  This function should not accept any arguments
+but return the appropriate prefix and complete link string.
+
address@hidden Adding export back-ends
 @section Adding export back-ends
 @cindex Export, writing back-ends
 
-Org 8.0 comes with a completely rewritten export engine which makes it easy
-to write new export back-ends, either from scratch, or from deriving them
-from existing ones.
-
-Your two entry points are respectively @code{org-export-define-backend} and
address@hidden  To grok these functions, you
-should first have a look at @file{ox-latex.el} (for how to define a new
-back-end from scratch) and @file{ox-beamer.el} (for how to derive a new
-back-end from an existing one.
-
-When creating a new back-end from scratch, the basic idea is to set the name
-of the back-end (as a symbol) and an an alist of elements and export
-functions.  On top of this, you will need to set additional keywords like
address@hidden:menu-entry} (to display the back-end in the export dispatcher),
address@hidden:export-block} (to specify what blocks should not be exported by 
this
-back-end), and @code{:options-alist} (to let the user set export options that
-are specific to this back-end.)
-
-Deriving a new back-end is similar, except that you need to set
address@hidden:translate-alist} to an alist of export functions that should be 
used
-instead of the parent back-end functions.
-
-For a complete reference documentation, see
+Org's export engine makes it easy for writing new back-ends.  The framework
+on which the engine was built makes it easy to derive new back-ends from
+existing ones.
+
+The two main entry points to the export engine are:
address@hidden and
address@hidden  To grok these functions, see
address@hidden for an example of defining a new back-end from scratch,
+and @file{ox-beamer.el} for an example of deriving from an existing engine.
+
+For creating a new back-end from scratch, first set its name as a symbol in
+an alist consisting of elements and export functions.  To make the back-end
+visible to the export dispatcher, set @code{:menu-entry} keyword.  For export
+options specific to this back-end, set the @code{:options-alist}.
+
+For creating a new back-end from an existing one, set @code{:translate-alist}
+to an alist of export functions.  This alist replaces the parent back-end
+functions.
+
+For complete documentation, see
 @url{http://orgmode.org/worg/dev/org-export-reference.html, the Org Export
 Reference on Worg}.
 
address@hidden Context-sensitive commands, Tables in arbitrary syntax, Adding 
export back-ends, Hacking
address@hidden Context-sensitive commands
 @section Context-sensitive commands
 @cindex context-sensitive commands, hooks
 @cindex add-ons, context-sensitive commands
 @vindex org-ctrl-c-ctrl-c-hook
 
-Org has several commands that act differently depending on context.  The most
-important example is the @kbd{C-c C-c} (@pxref{The very busy C-c C-c key}).
-Also the @kbd{M-cursor} and @kbd{M-S-cursor} keys have this property.
-
-Add-ons can tap into this functionality by providing a function that detects
-special context for that add-on and executes functionality appropriate for
-the context.  Here is an example from Dan Davison's @file{org-R.el} which
-allows you to evaluate commands based on the @file{R} programming language
address@hidden@file{org-R.el} has been replaced by the Org mode functionality
-described in @ref{Working With Source Code} and is now obsolete.}.  For this
-package, special contexts are lines that start with @code{#+R:} or
address@hidden:}.
-
address@hidden
-(defun org-R-apply-maybe ()
-  "Detect if this is context for org-R and execute R commands."
-  (if (save-excursion
-        (beginning-of-line 1)
-        (looking-at "#\\+RR?:"))
-      (progn (call-interactively 'org-R-apply)
-             t) ;; to signal that we took action
-    nil)) ;; to signal that we did not
-
-(add-hook 'org-ctrl-c-ctrl-c-hook 'org-R-apply-maybe)
address@hidden lisp
+Org has facilities for building context sensitive commands.  Authors of Org
+add-ons can tap into this functionality.
 
-The function first checks if the cursor is in such a line.  If that is the
-case, @code{org-R-apply} is called and the function returns @code{t} to
-signal that action was taken, and @kbd{C-c C-c} will stop looking for other
-contexts.  If the function finds it should do nothing locally, it returns
address@hidden so that other, similar functions can have a try.
+Some Org commands change depending on the context.  The most important
+example of this behavior is the @kbd{C-c C-c} (@pxref{The very busy C-c C-c
+key}).  Other examples are @kbd{M-cursor} and @kbd{M-S-cursor}.
 
+These context sensitive commands work by providing a function that detects
+special context for that add-on and executes functionality appropriate for
+that context.
 
address@hidden Tables in arbitrary syntax, Dynamic blocks, Context-sensitive 
commands, Hacking
address@hidden Tables in arbitrary syntax
 @section Tables and lists in arbitrary syntax
 @cindex tables, in other modes
 @cindex lists, in other modes
 @cindex Orgtbl mode
 
-Since Orgtbl mode can be used as a minor mode in arbitrary buffers, a
-frequent feature request has been to make it work with native tables in
-specific languages, for example @LaTeX{}.  However, this is extremely
-hard to do in a general way, would lead to a customization nightmare,
-and would take away much of the simplicity of the Orgtbl mode table
-editor.
-
-This appendix describes a different approach.  We keep the Orgtbl mode
-table in its native format (the @i{source table}), and use a custom
-function to @i{translate} the table to the correct syntax, and to
address@hidden it in the right location (the @i{target table}).  This puts
-the burden of writing conversion functions on the user, but it allows
-for a very flexible system.
-
-Bastien added the ability to do the same with lists, in Orgstruct mode.  You
-can use Org's facilities to edit and structure lists by turning
address@hidden on, then locally exporting such lists in another format
-(HTML, @LaTeX{} or Texinfo.)
-
+Because of Org's success in handling tables with Orgtbl, a frequently asked
+feature is to Org's usability functions to other table formats native to
+other modem's, such as @LaTeX{}.  This would be hard to do in a general way
+without complicated customization nightmares.  Moreover, that would take Org
+away from its simplicity roots that Orgtbl has proven.  There is, however, an
+alternate approach to accomplishing the same.
+
+This approach involves implementing a custom @emph{translate} function that
+operates on a native Org @emph{source table} to produce a table in another
+format.  This strategy would keep the excellently working Orgtbl simple and
+isolate complications, if any, confined to the translate function.  To add
+more alien table formats, we just add more translate functions.  Also the
+burden of developing custom translate functions for new table formats will be
+in the hands of those who know those formats best.
+
+For an example of how this strategy works, see Orgstruct mode.  In that mode,
+Bastien added the ability to use Org's facilities to edit and re-structure
+lists.  He did by turning @code{orgstruct-mode} on, and then exporting the
+list locally to another format, such as HTML, @LaTeX{} or Texinfo.
 
 @menu
 * Radio tables::                Sending and receiving radio tables
@@ -17180,15 +18083,17 @@ can use Org's facilities to edit and structure lists 
by turning
 * Radio lists::                 Sending and receiving lists
 @end menu
 
address@hidden Radio tables, A @LaTeX{} example, Tables in arbitrary syntax, 
Tables in arbitrary syntax
address@hidden Radio tables
 @subsection Radio tables
 @cindex radio tables
 
-To define the location of the target table, you first need to create two
-lines that are comments in the current mode, but contain magic words
address@hidden/END RECEIVE ORGTBL} for Orgtbl mode to find.  Orgtbl mode will
-insert the translated table between these lines, replacing whatever was there
-before.  For example in C mode where comments are between @code{/* ... */}:
+Radio tables are target locations for translated tables that are not near
+their source.  Org finds the target location and inserts the translated
+table.
+
+The key to finding the target location are the magic words @code{BEGIN/END
+RECEIVE ORGTBL}.  They have to appear as comments in the current mode.  If
+the mode is C, then:
 
 @example
 /* BEGIN RECEIVE ORGTBL table_name */
@@ -17196,8 +18101,8 @@ before.  For example in C mode where comments are 
between @code{/* ... */}:
 @end example
 
 @noindent
-Just above the source table, we put a special line that tells
-Orgtbl mode how to translate this table and where to install it.  For
+At the location of source, Org needs a special line to direct Orgtbl to
+translate and to find the target for inserting the translated table.  For
 example:
 @cindex #+ORGTBL
 @example
@@ -17205,67 +18110,53 @@ example:
 @end example
 
 @noindent
address@hidden is the reference name for the table that is also used
-in the receiver lines.  @code{translation_function} is the Lisp function
-that does the translation.  Furthermore, the line can contain a list of
-arguments (alternating key and value) at the end.  The arguments will be
-passed as a property list to the translation function for
-interpretation.  A few standard parameters are already recognized and
-acted upon before the translation function is called:
address@hidden is the table's reference name, which is also used in the
+receiver lines, and the @code{translation_function} is the Lisp function that
+translates.  This line, in addition, may also contain alternating key and
+value arguments at the end.  The translation function gets these values as a
+property list.  A few standard parameters are already recognized and acted
+upon before the translation function is called:
 
 @table @code
 @item :skip N
-Skip the first N lines of the table.  Hlines do count as separate lines for
-this parameter!
+Skip the first N lines of the table.  Hlines do count; include them if they
+are to be skipped.
 
 @item :skipcols (n1 n2 ...)
-List of columns that should be skipped.  If the table has a column with
-calculation marks, that column is automatically discarded as well.
-Please note that the translator function sees the table @emph{after} the
-removal of these columns, the function never knows that there have been
-additional columns.
-
address@hidden :no-escape t
-When address@hidden, do not escape special characters @code{&%#_^} when 
exporting
-the table.  The default value is @code{nil}.
+List of columns to be skipped.  First Org automatically discards columns with
+calculation marks and then sends the table to the translator function, which
+then skips columns as specified in @samp{skipcols}.
 @end table
 
 @noindent
-The one problem remaining is how to keep the source table in the buffer
-without disturbing the normal workings of the file, for example during
-compilation of a C file or processing of a @LaTeX{} file.  There are a
-number of different solutions:
+To keep the source table intact in the buffer without being disturbed when
+the source file is compiled or otherwise being worked on, use one of these
+strategies:
 
 @itemize @bullet
 @item
-The table could be placed in a block comment if that is supported by the
-language.  For example, in C mode you could wrap the table between
address@hidden/*} and @samp{*/} lines.
+Place the table in a block comment.  For example, in C mode you could wrap
+the table between @samp{/*} and @samp{*/} lines.
 @item
-Sometimes it is possible to put the table after some kind of @i{END}
-statement, for example @samp{\bye} in @TeX{} and @address@hidden@}}
-in @LaTeX{}.
+Put the table after an @samp{END} statement.  For example @samp{\bye} in
address@hidden and @address@hidden@}} in @LaTeX{}.
 @item
-You can just comment the table line-by-line whenever you want to process
-the file, and uncomment it whenever you need to edit the table.  This
-only sounds tedious---the command @kbd{M-x orgtbl-toggle-comment RET}
-makes this comment-toggling very easy, in particular if you bind it to a
-key.
+Comment and uncomment each line of the table during edits.  The @kbd{M-x
+orgtbl-toggle-comment RET} command makes toggling easy.
 @end itemize
 
address@hidden A @LaTeX{} example, Translator functions, Radio tables, Tables 
in arbitrary syntax
address@hidden A @LaTeX{} example
 @subsection A @LaTeX{} example of radio tables
 @cindex @LaTeX{}, and Orgtbl mode
 
-The best way to wrap the source table in @LaTeX{} is to use the
address@hidden environment provided by @file{comment.sty}.  It has to be
-activated by placing @address@hidden@}} into the document
-header.  Orgtbl mode can insert a radio table address@hidden
-default this works only for @LaTeX{}, HTML, and Texinfo.  Configure the
-variable @code{orgtbl-radio-table-templates} to install templates for other
-modes.}  with the command @kbd{M-x orgtbl-insert-radio-table RET}.  You will
-be prompted for a table name, let's say we use @samp{salesfigures}.  You
-will then get the following template:
+To wrap a source table in @LaTeX{}, use the @code{comment} environment
+provided by @file{comment.sty}.  To activate it, put
address@hidden@address@hidden in the document header.  Orgtbl mode inserts a
+radio table address@hidden default this works only for @LaTeX{}, HTML,
+and Texinfo.  Configure the variable @code{orgtbl-radio-table-templates} to
+install templates for other export formats.}  with the command @kbd{M-x
+orgtbl-insert-radio-table RET}, which prompts for a table name.  For example,
+if @samp{salesfigures} is the name, the template inserts:
 
 @cindex #+ORGTBL, SEND
 @example
@@ -17279,17 +18170,17 @@ will then get the following template:
 
 @noindent
 @vindex @LaTeX{}-verbatim-environments
-The @code{#+ORGTBL: SEND} line tells Orgtbl mode to use the function
address@hidden to convert the table into @LaTeX{} and to put it
-into the receiver location with name @code{salesfigures}.  You may now
-fill in the table---feel free to use the spreadsheet address@hidden
-the @samp{#+TBLFM} line contains an odd number of dollar characters,
-this may cause problems with font-lock in @LaTeX{} mode.  As shown in the
-example you can fix this by adding an extra line inside the
address@hidden environment that is used to balance the dollar
-expressions.  If you are using address@hidden with the font-latex library, a
-much better solution is to add the @code{comment} environment to the
-variable @code{LaTeX-verbatim-environments}.}:
+The line @code{#+ORGTBL: SEND} tells Orgtbl mode to use the function
address@hidden to convert the table to @LaTeX{} format, then insert
+the table at the target (receive) location named @code{salesfigures}.  Now
+the table is ready for data entry.  It can even use spreadsheet
address@hidden the @samp{#+TBLFM} line contains an odd number of dollar
+characters, this may cause problems with font-lock in @LaTeX{} mode.  As
+shown in the example you can fix this by adding an extra line inside the
address@hidden environment that is used to balance the dollar expressions.
+If you are using address@hidden with the font-latex library, a much better
+solution is to add the @code{comment} environment to the variable
address@hidden:
 
 @example
 % BEGIN RECEIVE ORGTBL salesfigures
@@ -17307,14 +18198,12 @@ variable @code{LaTeX-verbatim-environments}.}:
 @end example
 
 @noindent
-When you are done, press @kbd{C-c C-c} in the table to get the converted
-table inserted between the two marker lines.
+After editing, @kbd{C-c C-c} inserts translated table at the target location,
+between the two marker lines.
 
-Now let's assume you want to make the table header by hand, because you
-want to control how columns are aligned, etc.  In this case we make sure
-that the table translator skips the first 2 lines of the source
-table, and tell the command to work as a @i{splice}, i.e., to not produce
-header and footer commands of the target table:
+For hand-made custom tables, note that the translator needs to skip the first
+two lines of the source table.  Also the command has to @emph{splice} out the
+target table without the header and footer.
 
 @example
 address@hidden@address@hidden@}
@@ -17335,135 +18224,109 @@ Month & 
address@hidden@address@hidden@address@hidden@} & Nr.\ sold & per day\\
 @end example
 
 The @LaTeX{} translator function @code{orgtbl-to-latex} is already part of
-Orgtbl mode.  It uses a @code{tabular} environment to typeset the table
-and marks horizontal lines with @code{\hline}.  Furthermore, it
-interprets the following parameters (see also @pxref{Translator functions}):
+Orgtbl mode and uses @code{tabular} environment by default to typeset the
+table and mark the horizontal lines with @code{\hline}.  For additional
+parameters to control output, @pxref{Translator functions}:
 
 @table @code
 @item :splice nil/t
-When set to t, return only table body lines, don't wrap them into a
-tabular environment.  Default is @code{nil}.
+When address@hidden, returns only table body lines; not wrapped in tabular
+environment.  Default is @code{nil}.
 
 @item :fmt fmt
-A format to be used to wrap each field, it should contain @code{%s} for the
-original field value.  For example, to wrap each field value in dollars,
-you could use @code{:fmt "$%s$"}.  This may also be a property list with
+Format to warp each field.  It should contain @code{%s} for the original
+field value.  For example, to wrap each field value in dollar symbol, you
+could use @code{:fmt "$%s$"}.  Format can also wrap a property list with
 column numbers and formats, for example @code{:fmt (2 "$%s$" 4 "%s\\%%")}.
-A function of one argument can be used in place of the strings; the
-function must return a formatted string.
+In place of a string, a function of one argument can be used; the function
+must return a formatted string.
 
 @item :efmt efmt
-Use this format to print numbers with exponentials.  The format should
-have @code{%s} twice for inserting mantissa and exponent, for example
address@hidden"address@hidden@}"}.  The default is @code{"%s\\,(%s)"}.  This
-may also be a property list with column numbers and formats, for example
+Format numbers as exponentials.  The spec should have @code{%s} twice for
+inserting mantissa and exponent, for example @code{"address@hidden@}"}.
+This may also be a property list with column numbers and formats, for example
 @code{:efmt (2 "address@hidden@}$" 4 "address@hidden@}$")}.  After
address@hidden has been applied to a value, @code{fmt} will also be
-applied.  Similar to @code{fmt}, functions of two arguments can be
-supplied instead of strings.
address@hidden has been applied to a value, @code{fmt} will also be applied.
+Functions with two arguments can be supplied instead of strings.  By default,
+no special formatting is applied.
 @end table
 
address@hidden Translator functions, Radio lists, A @LaTeX{} example, Tables in 
arbitrary syntax
address@hidden Translator functions
 @subsection Translator functions
 @cindex HTML, and Orgtbl mode
 @cindex translator function
 
-Orgtbl mode has several translator functions built-in: @code{orgtbl-to-csv}
-(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values)
address@hidden, @code{orgtbl-to-html}, and @code{orgtbl-to-texinfo}.
-Except for @address@hidden HTML translator uses the same
-code that produces tables during HTML export.}, these all use a generic
-translator, @code{orgtbl-to-generic}.  For example, @code{orgtbl-to-latex}
-itself is a very short function that computes the column definitions for the
address@hidden environment, defines a few field and line separators and then
-hands processing over to the generic translator.  Here is the entire code:
-
address@hidden
address@hidden
-(defun orgtbl-to-latex (table params)
-  "Convert the Orgtbl mode TABLE to LaTeX."
-  (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
-                               org-table-last-alignment ""))
-         (params2
-          (list
-           :tstart (concat "address@hidden@address@hidden" alignment "@}")
-           :tend "address@hidden@}"
-           :lstart "" :lend " \\\\" :sep " & "
-           :efmt "%s\\,(%s)" :hline "\\hline")))
-    (orgtbl-to-generic table (org-combine-plists params2 params))))
address@hidden group
address@hidden lisp
+Orgtbl mode has built-in translator functions: @code{orgtbl-to-csv}
+(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values),
address@hidden, @code{orgtbl-to-html}, @code{orgtbl-to-texinfo},
address@hidden and @code{orgtbl-to-orgtbl}.  They use the generic
+translator, @code{orgtbl-to-generic}, which delegates translations to various
+export back-ends.
 
-As you can see, the properties passed into the function (variable
address@hidden) are combined with the ones newly defined in the function
-(variable @var{PARAMS2}).  The ones passed into the function (i.e., the
-ones set by the @samp{ORGTBL SEND} line) take precedence.  So if you
-would like to use the @LaTeX{} translator, but wanted the line endings to
-be @samp{\\[2mm]} instead of the default @samp{\\}, you could just
-overrule the default with
+Properties passed to the function through the @samp{ORGTBL SEND} line take
+precedence over properties defined inside the function.  For example, this
+overrides the default @LaTeX{} line endings, @samp{\\}, with @samp{\\[2mm]}:
 
 @example
 #+ORGTBL: SEND test orgtbl-to-latex :lend " \\\\[2mm]"
 @end example
 
-For a new language, you can either write your own converter function in
-analogy with the @LaTeX{} translator, or you can use the generic function
-directly.  For example, if you have a language where a table is started
-with @samp{!BTBL!}, ended with @samp{!ETBL!}, and where table lines are
-started with @samp{!BL!}, ended with @samp{!EL!}, and where the field
-separator is a TAB, you could call the generic translator like this (on
-a single line!):
+For a new language translator, define a converter function.  It can be a
+generic function, such as shown in this example.  It marks a beginning and
+ending of a table with @samp{!BTBL!} and @samp{!ETBL!}; a beginning and
+ending of lines with @samp{!BL!} and @samp{!EL!}; and uses a TAB for a field
+separator:
 
address@hidden
-#+ORGTBL: SEND test orgtbl-to-generic :tstart "!BTBL!" :tend "!ETBL!"
-                              :lstart "!BL! " :lend " !EL!" :sep "\t"
address@hidden example
address@hidden
+(defun orgtbl-to-language (table params)
+  "Convert the orgtbl-mode TABLE to language."
+  (orgtbl-to-generic
+   table
+   (org-combine-plists
+    '(:tstart "!BTBL!" :tend "!ETBL!" :lstart "!BL!" :lend "!EL!" :sep "\t")
+    params)))
address@hidden lisp
 
 @noindent
-Please check the documentation string of the function
address@hidden for a full list of parameters understood by
-that function, and remember that you can pass each of them into
+The documentation for the @code{orgtbl-to-generic} function shows a complete
+list of parameters, each of which can be passed through to
 @code{orgtbl-to-latex}, @code{orgtbl-to-texinfo}, and any other function
-using the generic function.
-
-Of course you can also write a completely new function doing complicated
-things the generic translator cannot do.  A translator function takes
-two arguments.  The first argument is the table, a list of lines, each
-line either the symbol @code{hline} or a list of fields.  The second
-argument is the property list containing all parameters specified in the
address@hidden: SEND} line.  The function must return a single string
-containing the formatted table.  If you write a generally useful
-translator, please post it on @email{emacs-orgmode@@gnu.org} so that
-others can benefit from your work.
-
address@hidden Radio lists,  , Translator functions, Tables in arbitrary syntax
+using that generic function.
+
+For complicated translations the generic translator function could be
+replaced by a custom translator function.  Such a custom function must take
+two arguments and return a single string containing the formatted table.  The
+first argument is the table whose lines are a list of fields or the symbol
address@hidden  The second argument is the property list consisting of
+parameters specified in the @samp{#+ORGTBL: SEND} line.  Please share your
+translator functions by posting them to the Org users mailing list,
address@hidden@@gnu.org}.
+
address@hidden Radio lists
 @subsection Radio lists
 @cindex radio lists
 @cindex org-list-insert-radio-list
 
-Sending and receiving radio lists works exactly the same way as sending and
-receiving radio tables (@pxref{Radio tables}).  As for radio tables, you can
-insert radio list templates in HTML, @LaTeX{} and Texinfo modes by calling
address@hidden
-
-Here are the differences with radio tables:
+Call the @code{org-list-insert-radio-list} function to insert a radio list
+template in HTML, @LaTeX{}, and Texinfo mode documents.  Sending and
+receiving radio lists works is the same as for radio tables (@pxref{Radio
+tables}) except for these differences:
 
address@hidden #+ORGLST
 @itemize @minus
 @item
 Orgstruct mode must be active.
 @item
-Use the @code{ORGLST} keyword instead of @code{ORGTBL}.
+Use @code{ORGLST} keyword instead of @code{ORGTBL}.
 @item
-The available translation functions for radio lists don't take
-parameters.
address@hidden
address@hidden C-c} will work when pressed on the first item of the list.
address@hidden C-c} works only on the first list item.
 @end itemize
 
-Here is a @LaTeX{} example.  Let's say that you have this in your
address@hidden file:
+Built-in translators functions are: @code{org-list-to-latex},
address@hidden and @code{org-list-to-texinfo}.  They use the
address@hidden translator function.  See its documentation for
+parameters for accurate customizations of lists.  Here is a @LaTeX{} example:
 
address@hidden #+ORGLST
 @example
 % BEGIN RECEIVE ORGLST to-buy
 % END RECEIVE ORGLST to-buy
@@ -17477,21 +18340,21 @@ Here is a @LaTeX{} example.  Let's say that you have 
this in your
 address@hidden@}
 @end example
 
-Pressing @kbd{C-c C-c} on @code{a new house} and will insert the converted
address@hidden list between the two marker lines.
address@hidden C-c} on @samp{a new house} inserts the translated @LaTeX{} list
+in-between the BEGIN and END marker lines.
 
address@hidden Dynamic blocks, Special agenda views, Tables in arbitrary 
syntax, Hacking
address@hidden Dynamic blocks
 @section Dynamic blocks
 @cindex dynamic blocks
 
-Org documents can contain @emph{dynamic blocks}.  These are
-specially marked regions that are updated by some user-written function.
-A good example for such a block is the clock table inserted by the
-command @kbd{C-c C-x C-r} (@pxref{Clocking work time}).
+Org supports @emph{dynamic blocks} in Org documents.  They are inserted with
+begin and end markers like any other @samp{src} code block, but the contents
+are updated automatically by a user function.  For example, @kbd{C-c C-x C-r}
+inserts a dynamic table that updates the work time (@pxref{Clocking work
+time}).
 
-Dynamic blocks are enclosed by a BEGIN-END structure that assigns a name
-to the block and can also specify parameters for the function producing
-the content of the block.
+Dynamic blocks can have names and function parameters.  The syntax is similar
+to @samp{src} code block specifications:
 
 @cindex #+BEGIN:dynamic block
 @example
@@ -17500,7 +18363,7 @@ the content of the block.
 #+END:
 @end example
 
-Dynamic blocks are updated with the following commands
+These command update dynamic blocks:
 
 @table @kbd
 @orgcmd{C-c C-x C-u,org-dblock-update}
@@ -17509,17 +18372,16 @@ Update dynamic block at point.
 Update all dynamic blocks in the current file.
 @end table
 
-Updating a dynamic block means to remove all the text between BEGIN and
-END, parse the BEGIN line for parameters and then call the specific
-writer function for this block to insert the new content.  If you want
-to use the original content in the writer function, you can use the
-extra parameter @code{:content}.
+Before updating a dynamic block, Org removes content between the BEGIN and
+END markers.  Org then reads the parameters on the BEGIN line for passing to
+the writer function.  If the function expects to access the removed content,
+then Org expects an extra parameter, @code{:content}, on the BEGIN line.
 
-For a block with name @code{myblock}, the writer function is
address@hidden:myblock} with as only parameter a property list
-with the parameters given in the begin line.  Here is a trivial example
-of a block that keeps track of when the block update function was last
-run:
+To syntax for calling a writer function with a named block, @code{myblock}
+is: @code{org-dblock-write:myblock}.  Parameters come from the BEGIN line.
+
+The following is an example of a dynamic block and a block writer function
+that updates the time when the function was last run:
 
 @example
 #+BEGIN: block-update-time :format "on %m/%d/%Y at %H:%M"
@@ -17528,7 +18390,7 @@ run:
 @end example
 
 @noindent
-The corresponding block writer function could look like this:
+The dynamic block's writer function:
 
 @lisp
 (defun org-dblock-write:block-update-time (params)
@@ -17537,47 +18399,40 @@ The corresponding block writer function could look 
like this:
             (format-time-string fmt))))
 @end lisp
 
-If you want to make sure that all dynamic blocks are always up-to-date,
-you could add the function @code{org-update-all-dblocks} to a hook, for
-example @code{before-save-hook}.  @code{org-update-all-dblocks} is
-written in a way such that it does nothing in buffers that are not in
address@hidden
+To keep dynamic blocks up-to-date in an Org file, use the function,
address@hidden in hook, such as @code{before-save-hook}.  The
address@hidden function does not run if the file is not in
+Org mode.
 
-You can narrow the current buffer to the current dynamic block (like any
-other block) with @code{org-narrow-to-block}.
+Dynamic blocks, like any other block, can be narrowed with
address@hidden
 
address@hidden Special agenda views, Speeding up your agendas, Dynamic blocks, 
Hacking
address@hidden Special agenda views
 @section Special agenda views
 @cindex agenda views, user-defined
 
 @vindex org-agenda-skip-function
 @vindex org-agenda-skip-function-global
-Org provides a special hook that can be used to narrow down the selection
-made by these agenda views: @code{agenda}, @address@hidden
address@hidden view is the same than @code{agenda} except that it only
-considers @emph{appointments}, i.e., scheduled and deadline items that have a
-time specification @code{[h]h:mm} in their time-stamps.}, @code{todo},
address@hidden, @code{tags}, @code{tags-todo}, @code{tags-tree}.  You may
-specify a function that is used at each match to verify if the match should
-indeed be part of the agenda view, and if not, how much should be skipped.
-You can specify a global condition that will be applied to all agenda views,
-this condition would be stored in the variable
address@hidden  More commonly, such a definition is
-applied only to specific custom searches, using
address@hidden
-
-Let's say you want to produce a list of projects that contain a WAITING
-tag anywhere in the project tree.  Let's further assume that you have
-marked all tree headings that define a project with the TODO keyword
address@hidden  In this case you would run a TODO search for the keyword
-PROJECT, but skip the match unless there is a WAITING tag anywhere in
-the subtree belonging to the project line.
-
-To achieve this, you must write a function that searches the subtree for
-the tag.  If the tag is found, the function must return @code{nil} to
-indicate that this match should not be skipped.  If there is no such
-tag, return the location of the end of the subtree, to indicate that
-search should continue from there.
+Org provides a special hook to further limit items in agenda views:
address@hidden, @address@hidden @code{agenda*} view is the same as
address@hidden except that it only considers @emph{appointments}, i.e.,
+scheduled and deadline items that have a time specification @samp{[h]h:mm} in
+their time-stamps.}, @code{todo}, @code{alltodo}, @code{tags},
address@hidden, @code{tags-tree}.  Specify a custom function that tests
+inclusion of every matched item in the view.  This function can also
+skip as much as is needed.
+
+For a global condition applicable to agenda views, use the
address@hidden variable.  Org uses a global condition
+with @code{org-agenda-skip-function} for custom searching.
+
+This example defines a function for a custom view showing TODO items with
+WAITING status.  Manually this is a multi step search process, but with a
+custom view, this can be automated as follows:
+
+The custom function searches the subtree for the WAITING tag and returns
address@hidden on match.  Otherwise it gives the location from where the search
+continues.
 
 @lisp
 (defun my-skip-unless-waiting ()
@@ -17588,8 +18443,7 @@ search should continue from there.
       subtree-end))) ; tag not found, continue after end of subtree
 @end lisp
 
-Now you may use this function in an agenda custom command, for example
-like this:
+To use this custom function in a custom agenda command:
 
 @lisp
 (org-add-agenda-custom-command
@@ -17599,22 +18453,20 @@ like this:
 @end lisp
 
 @vindex org-agenda-overriding-header
-Note that this also binds @code{org-agenda-overriding-header} to get a
-meaningful header in the agenda view.
+Note that this also binds @code{org-agenda-overriding-header} to a more
+meaningful string suitable for the agenda view.
 
 @vindex org-odd-levels-only
 @vindex org-agenda-skip-function
-A general way to create custom searches is to base them on a search for
-entries with a certain level limit.  If you want to study all entries with
-your custom search function, simply do a search for
address@hidden>address@hidden that, when using @code{org-odd-levels-only}, a
-level number corresponds to order in the hierarchy, not to the number of
-stars.}, and then use @code{org-agenda-skip-function} to select the entries
-you really want to have.
-
-You may also put a Lisp form into @code{org-agenda-skip-function}.  In
-particular, you may use the functions @code{org-agenda-skip-entry-if}
-and @code{org-agenda-skip-subtree-if} in this form, for example:
+
+Search for entries with a limit set on levels for the custom search.  This is
+a general appraoch to creating custom searches in Org.  To include all
+levels, use @samp{LEVEL>address@hidden that, for
address@hidden, a level number corresponds to order in the
+hierarchy, not to the number of stars.}.  Then to selectively pick the
+matched entries, use @code{org-agenda-skip-function}, which also accepts Lisp
+forms, such as @code{org-agenda-skip-entry-if} and
address@hidden  For example:
 
 @table @code
 @item (org-agenda-skip-entry-if 'scheduled)
@@ -17640,8 +18492,8 @@ Skip current entry unless the regular expression 
matches.
 Same as above, but check and skip the entire subtree.
 @end table
 
-Therefore we could also have written the search for WAITING projects
-like this, even without defining a special function:
+The following is an example of a search for @samp{WAITING} without the
+special function:
 
 @lisp
 (org-add-agenda-custom-command
@@ -17651,72 +18503,71 @@ like this, even without defining a special function:
     (org-agenda-overriding-header "Projects waiting for something: "))))
 @end lisp
 
address@hidden Speeding up your agendas, Extracting agenda information, Special 
agenda views, Hacking
address@hidden Speeding up your agendas
 @section Speeding up your agendas
 @cindex agenda views, optimization
 
-When your Org files grow in both number and size, agenda commands may start
-to become slow.  Below are some tips on how to speed up the agenda commands.
+Some agenda commands slow down when the Org files grow in size or number.
+Here are tips to speed up:
 
 @enumerate
 @item
-Reduce the number of Org agenda files: this will reduce the slowness caused
-by accessing a hard drive.
+Reduce the number of Org agenda files to avoid slowdowns due to hard drive
+accesses.
 @item
-Reduce the number of DONE and archived headlines: this way the agenda does
-not need to skip them.
+Reduce the number of @samp{DONE} and archived headlines so agenda operations
+that skip over these can finish faster.
 @item
 @vindex org-agenda-dim-blocked-tasks
-Inhibit the dimming of blocked tasks:
+Do not dim blocked tasks:
 @lisp
 (setq org-agenda-dim-blocked-tasks nil)
 @end lisp
 @item
 @vindex org-startup-folded
 @vindex org-agenda-inhibit-startup
-Inhibit agenda files startup options:
+Stop preparing agenda buffers on startup:
 @lisp
 (setq org-agenda-inhibit-startup nil)
 @end lisp
 @item
 @vindex org-agenda-show-inherited-tags
 @vindex org-agenda-use-tag-inheritance
-Disable tag inheritance in agenda:
+Disable tag inheritance for agendas:
 @lisp
 (setq org-agenda-use-tag-inheritance nil)
 @end lisp
 @end enumerate
 
-You can set these options for specific agenda views only.  See the docstrings
-of these variables for details on why they affect the agenda generation, and
-this @uref{http://orgmode.org/worg/agenda-optimization.html, dedicated Worg
-page} for further explanations.
+These options can be applied to selected agenda views.  For more details
+about generation of agenda views, see the docstrings for the relevant
+variables, and this @uref{http://orgmode.org/worg/agenda-optimization.html,
+dedicated Worg page} for agenda optimization.
 
address@hidden Extracting agenda information, Using the property API, Speeding 
up your agendas, Hacking
address@hidden Extracting agenda information
 @section Extracting agenda information
 @cindex agenda, pipe
 @cindex Scripts, for agenda processing
 
 @vindex org-agenda-custom-commands
-Org provides commands to access agenda information for the command
-line in Emacs batch mode.  This extracted information can be sent
-directly to a printer, or it can be read by a program that does further
-processing of the data.  The first of these commands is the function
address@hidden, that produces an agenda view and sends it as
-ASCII text to address@hidden  The command takes a single string as parameter.
-If the string has length 1, it is used as a key to one of the commands
-you have configured in @code{org-agenda-custom-commands}, basically any
-key you can use after @kbd{C-c a}.  For example, to directly print the
-current TODO list, you could use
+Org provides commands to access agendas through Emacs batch mode.  Through
+this command-line interface, agendas are automated for further processing or
+printing.
+
address@hidden creates an agenda view in ASCII and outputs to
+STDOUT.  This command takes one string parameter.  When string length=1, Org
+uses it as a key to @code{org-agenda-custom-commands}.  These are the same
+ones available through @kbd{C-c a}.
+
+This example command line directly prints the TODO list to the printer:
 
 @example
 emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' | lpr
 @end example
 
-If the parameter is a string with 2 or more characters, it is used as a
-tags/TODO match string.  For example, to print your local shopping list
-(all items with the tag @samp{shop}, but excluding the tag
address@hidden), you could use
+When the string parameter length is two or more characters, Org matches it
+with tags/TODO strings.  For example, this example command line prints items
+tagged with @samp{shop}, but excludes items tagged with @samp{NewYork}:
 
 @example
 emacs -batch -l ~/.emacs                                      \
@@ -17724,7 +18575,7 @@ emacs -batch -l ~/.emacs                                
      \
 @end example
 
 @noindent
-You may also modify parameters on the fly like this:
+An example showing on-the-fly parameter modifications:
 
 @example
 emacs -batch -l ~/.emacs                                      \
@@ -17736,14 +18587,11 @@ emacs -batch -l ~/.emacs                              
        \
 @end example
 
 @noindent
-which will produce a 30-day agenda, fully restricted to the Org file
address@hidden/org/projects.org}, not even including the diary.
+which will produce an agenda for the next 30 days from just the
address@hidden/org/projects.org} file.
 
-If you want to process the agenda data in more sophisticated ways, you
-can use the command @code{org-batch-agenda-csv} to get a comma-separated
-list of values for each agenda item.  Each line in the output will
-contain a number of fields separated by commas.  The fields in a line
-are:
+For structured processing of agenda output, use @code{org-batch-agenda-csv}
+with the following fields:
 
 @example
 category     @r{The category of the item}
@@ -17769,12 +18617,15 @@ priority-n   @r{The computed numerical priority}
 @end example
 
 @noindent
-Time and date will only be given if a timestamp (or deadline/scheduled)
-led to the selection of the item.
+If the selection of the agenda item was based on a timestamp, including those
+items with @samp{DEADLINE} and @samp{SCHEDULED} keywords, then Org includes
+date and time in the output.
 
-A CSV list like this is very easy to use in a post-processing script.
-For example, here is a Perl program that gets the TODO list from
-Emacs/Org and prints all the items, preceded by a checkbox:
+If the selection of the agenda item was based on a timestamp  (or
+deadline/scheduled), then Org includes date and time in the output.
+
+Here is an example of a post-processing script in Perl.  It takes the CSV
+output from Emacs and prints with a checkbox:
 
 @example
 #!/usr/bin/perl
@@ -17795,13 +18646,12 @@ foreach $line (split(/\n/,$agenda)) @{
 @}
 @end example
 
address@hidden Using the property API, Using the mapping API, Extracting agenda 
information, Hacking
address@hidden Using the property API
 @section Using the property API
 @cindex API, for properties
 @cindex properties, API
 
-Here is a description of the functions that can be used to work with
-properties.
+Functions for working with properties.
 
 @defun org-entry-properties &optional pom which
 Get all properties of the entry at point-or-marker address@hidden
@@ -17813,14 +18663,15 @@ POM may also be @code{nil}, in which case the current 
entry is used.
 If WHICH is @code{nil} or @code{all}, get all properties.  If WHICH is
 @code{special} or @code{standard}, only get that subclass.
 @end defun
+
 @vindex org-use-property-inheritance
 @findex org-insert-property-drawer
 @defun org-entry-get pom property &optional inherit
-Get value of @code{PROPERTY} for entry at point-or-marker @address@hidden  By 
default,
-this only looks at properties defined locally in the entry.  If @code{INHERIT}
-is address@hidden and the entry does not have the property, then also check
-higher levels of the hierarchy.  If @code{INHERIT} is the symbol
address@hidden, use inheritance if and only if the setting of
+Get value of @code{PROPERTY} for entry at point-or-marker @address@hidden  By
+default, this only looks at properties defined locally in the entry.  If
address@hidden is address@hidden and the entry does not have the property,
+then also check higher levels of the hierarchy.  If @code{INHERIT} is the
+symbol @code{selective}, use inheritance if and only if the setting of
 @code{org-use-property-inheritance} selects @code{PROPERTY} for inheritance.
 @end defun
 
@@ -17837,7 +18688,7 @@ Get all property keys in the current buffer.
 @end defun
 
 @defun org-insert-property-drawer
-Insert a property drawer for the current entry.  Also
+Insert a property drawer for the current entry.
 @end defun
 
 @defun org-entry-put-multivalued-property pom property &rest values
@@ -17875,41 +18726,37 @@ to be entered.  The functions must return @code{nil} 
if they are not
 responsible for this property.
 @end defopt
 
address@hidden Using the mapping API,  , Using the property API, Hacking
address@hidden Using the mapping API
 @section Using the mapping API
 @cindex API, for mapping
 @cindex mapping entries, API
 
-Org has sophisticated mapping capabilities to find all entries satisfying
-certain criteria.  Internally, this functionality is used to produce agenda
-views, but there is also an API that can be used to execute arbitrary
-functions for each or selected entries.  The main entry point for this API
-is:
+Org has sophisticated mapping capabilities for finding entries.  Org uses
+this functionality internally for generating agenda views.  Org also exposes
+an API for executing arbitrary functions for each selected entry.  The API's
+main entry point is:
 
 @defun org-map-entries func &optional match scope &rest skip
-Call @code{FUNC} at each headline selected by @code{MATCH} in @code{SCOPE}.
+Call @samp{FUNC} at each headline selected by @code{MATCH} in @code{SCOPE}.
 
address@hidden is a function or a Lisp form.  The function will be called
-without arguments, with the cursor positioned at the beginning of the
-headline.  The return values of all calls to the function will be collected
-and returned as a list.
address@hidden is a function or a Lisp form.  With the cursor positioned at the
+beginning of the headline, call the function without arguments.  Org returns
+an alist of return values of calls to the function.
 
-The call to @code{FUNC} will be wrapped into a save-excursion form, so
address@hidden does not need to preserve point.  After evaluation, the cursor
-will be moved to the end of the line (presumably of the headline of the
-processed entry) and search continues from there.  Under some circumstances,
-this may not produce the wanted results.  For example, if you have removed
-(e.g., archived) the current (sub)tree it could mean that the next entry will
-be skipped entirely.  In such cases, you can specify the position from where
-search should continue by making @code{FUNC} set the variable
address@hidden to the desired buffer position.
+To avoid preserving point, Org wraps the call to @code{FUNC} in
+save-excursion form.  After evaluation, Org moves the cursor to the end of
+the line that was just processed.  Search continues from that point forward.
+This may not always work as expected under some conditions, such as if the
+current sub-tree was removed by a previous archiving operation.  In such rare
+circumstances, Org skips the next entry entirely when it should not.  To stop
+Org from such skips, make @samp{FUNC} set the variable
address@hidden to a specific buffer position.
 
address@hidden is a tags/property/todo match as it is used in the agenda match
-view.  Only headlines that are matched by this query will be considered
-during the iteration.  When @code{MATCH} is @code{nil} or @code{t}, all
-headlines will be visited by the iteration.
address@hidden is a tags/property/TODO match.  Org iterates only matched
+headlines.  Org iterates over all headlines when @code{MATCH} is @code{nil}
+or @code{t}.
 
address@hidden determines the scope of this command.  It can be any of:
address@hidden determines the scope of this command.  It can be any of:
 
 @example
 nil     @r{the current buffer, respecting the restriction if any}
@@ -17925,8 +18772,8 @@ agenda-with-archives
         @r{if this is a list, all files in the list will be scanned}
 @end example
 @noindent
-The remaining args are treated as settings for the skipping facilities of
-the scanner.  The following items can be given here:
+The remaining args are treated as settings for the scanner's skipping
+facilities.  Valid args are:
 
 @vindex org-agenda-skip-function
 @example
@@ -17940,10 +18787,9 @@ function or Lisp form
 @end example
 @end defun
 
-The function given to that mapping routine can really do anything you like.
-It can use the property API (@pxref{Using the property API}) to gather more
-information about the entry, or in order to change metadata in the entry.
-Here are a couple of functions that might be handy:
+The mapping routine can call any arbitrary function, even functions that
+change meta data or query the property API (@pxref{Using the property API}).
+Here are some handy functions:
 
 @defun org-todo &optional arg
 Change the TODO state of the entry.  See the docstring of the functions for
@@ -17969,9 +18815,9 @@ Promote the current entry.
 Demote the current entry.
 @end defun
 
-Here is a simple example that will turn all entries in the current file with
-a tag @code{TOMORROW} into TODO entries with the keyword @code{UPCOMING}.
-Entries in comment trees and in archive trees will be ignored.
+This example turns all entries tagged with @code{TOMORROW} into TODO entries
+with keyword @code{UPCOMING}.  Org ignores entries in comment trees and
+archive trees.
 
 @lisp
 (org-map-entries
@@ -17986,105 +18832,103 @@ The following example counts the number of entries 
with TODO keyword
 (length (org-map-entries t "/+WAITING" 'agenda))
 @end lisp
 
address@hidden MobileOrg, History and Acknowledgments, Hacking, Top
address@hidden MobileOrg
 @appendix MobileOrg
 @cindex iPhone
 @cindex MobileOrg
 
address@hidden is the name of the mobile companion app for Org mode, currently
-available for iOS and for Android.  @i{MobileOrg} offers offline viewing and
-capture support for an Org mode system rooted on a ``real'' computer.  It
-does also allow you to record changes to existing entries.  The
address@hidden://github.com/MobileOrg/, iOS implementation} for the
address@hidden/iPod Touch/iPad} series of devices, was started by Richard 
Moreland
-and is now in the hands Sean Escriva.  Android users should check out
address@hidden://wiki.github.com/matburt/mobileorg-android/, MobileOrg Android}
-by Matt Jones.  The two implementations are not identical but offer similar
-features.
-
-This appendix describes the support Org has for creating agenda views in a
-format that can be displayed by @i{MobileOrg}, and for integrating notes
-captured and changes made by @i{MobileOrg} into the main system.
-
-For changing tags and TODO states in MobileOrg, you should have set up the
-customization variables @code{org-todo-keywords} and @code{org-tag-alist} to
-cover all important tags and TODO keywords, even if individual files use only
-part of these.  MobileOrg will also offer you states and tags set up with
-in-buffer settings, but it will understand the logistics of TODO state
address@hidden (@pxref{Per-file keywords}) and @i{mutually exclusive} tags
+MobileOrg is a companion mobile app that runs on iOS and Android devices.
+MobileOrg enables offline-views and capture support for an Org mode system
+that is rooted on a ``real'' computer.  MobileOrg can record changes to
+existing entries.
+
+The @uref{https://github.com/MobileOrg/, iOS implementation} for the
address@hidden/iPod Touch/iPad} series of devices, was started by Richard
+Moreland and is now in the hands Sean Escriva.  Android users should check
+out @uref{http://wiki.github.com/matburt/mobileorg-android/, MobileOrg
+Android} by Matt Jones.  Though the two implementations are not identical,
+they offer similar features.
+
+This appendix describes Org's support for agenda view formats compatible with
+MobileOrg.  It also describes synchronizing changes, such as to notes,
+between MobileOrg and the computer.
+
+To change tags and TODO states in MobileOrg, first customize the variables
address@hidden and @code{org-tag-alist}.  These should cover all
+the important tags and TODO keywords, even if Org files use only some of
+them.  Though MobileOrg has in-buffer settings, it understands TODO states
address@hidden (@pxref{Per-file keywords}) and @emph{mutually exclusive} tags
 (@pxref{Setting tags}) only for those set in these variables.
 
 @menu
-* Setting up the staging area::  Where to interact with the mobile device
+* Setting up the staging area::  For the mobile device
 * Pushing to MobileOrg::        Uploading Org files and agendas
 * Pulling from MobileOrg::      Integrating captured and flagged items
 @end menu
 
address@hidden Setting up the staging area, Pushing to MobileOrg, MobileOrg, 
MobileOrg
address@hidden Setting up the staging area
 @section Setting up the staging area
 
-MobileOrg needs to interact with Emacs through a directory on a server.  If you
-are using a public server, you should consider to encrypt the files that are
-uploaded to the server.  This can be done with Org mode 7.02 and with
address@hidden 1.5} (iPhone version), and you need an @file{openssl}
-installation on your system.  To turn on encryption, set a password in
address@hidden and, on the Emacs side, configure the variable
address@hidden@footnote{If you can safely store the
-password in your Emacs setup, you might also want to configure
address@hidden  Please read the docstring of that
-variable.  Note that encryption will apply only to the contents of the
address@hidden files.  The file names themselves will remain visible.}.
-
-The easiest way to create that directory is to use a free
address@hidden://dropbox.com,Dropbox.com} address@hidden you cannot use
-Dropbox, or if your version of MobileOrg does not support it, you can use a
-webdav server.  For more information, check out the documentation of MobileOrg 
and also this
+MobileOrg needs access to a file directory on a server to interact with
+Emacs.  With a public server, consider encrypting the files.  MobileOrg
+version 1.5 supports encryption for the iPhone.  Org also requires
address@hidden installed on the local computer.  To turn on encryption, set
+the same password in MobileOrg and in Emacs.  Set the password in the
+variable @address@hidden Emacs is configured for
+safe storing of passwords, then configure the variable,
address@hidden; please read the docstring of that
+variable.}.  Note that even after MobileOrg encrypts the file contents, the
+file names will remain visible on the file systems of the local computer, the
+server, and the mobile device.
+
+For a server to host files, consider options like
address@hidden://dropbox.com,Dropbox.com} address@hidden alternative is to
+use webdav server.  MobileOrg documentation has details of webdav server
+configuration.  Additional help is at
 @uref{http://orgmode.org/worg/org-faq.html#mobileorg_webdav, FAQ entry}.}.
-When MobileOrg first connects to your Dropbox, it will create a directory
address@hidden inside the Dropbox.  After the directory has been created, tell
-Emacs about it:
+On first connection, MobileOrg creates a directory @file{MobileOrg/} on
+Dropbox.  Pass its location to Emacs through an init file variable as
+follows:
 
 @lisp
 (setq org-mobile-directory "~/Dropbox/MobileOrg")
 @end lisp
 
-Org mode has commands to put files for @i{MobileOrg} into that directory,
-and to read captured notes from there.
+Org copies files to the above directory for MobileOrg.  Org also uses the
+same directory for sharing notes between Org and MobileOrg.
 
address@hidden Pushing to MobileOrg, Pulling from MobileOrg, Setting up the 
staging area, MobileOrg
address@hidden Pushing to MobileOrg
 @section Pushing to MobileOrg
 
-This operation copies all files currently listed in @code{org-mobile-files}
-to the directory @code{org-mobile-directory}.  By default this list contains
-all agenda files (as listed in @code{org-agenda-files}), but additional files
-can be included by customizing @code{org-mobile-files}.  File names will be
-staged with paths relative to @code{org-directory}, so all files should be
-inside this address@hidden links in @code{org-directory} need to
-have the same name than their targets.}.
-
-The push operation also creates a special Org file @file{agendas.org} with
-all custom agenda view defined by the address@hidden creating the
-agendas, Org mode will force ID properties on all referenced entries, so that
-these entries can be uniquely identified if @i{MobileOrg} flags them for
-further action.  If you do not want to get these properties in so many
-entries, you can set the variable @code{org-mobile-force-id-on-agenda-items}
-to @code{nil}.  Org mode will then rely on outline paths, in the hope that
-these will be unique enough.}.
-
-Finally, Org writes the file @file{index.org}, containing links to all other
-files.  @i{MobileOrg} first reads this file from the server, and then
-downloads all agendas and Org files listed in it.  To speed up the download,
-MobileOrg will only read files whose address@hidden are stored
-automatically in the file @file{checksums.dat}} have changed.
-
address@hidden Pulling from MobileOrg,  , Pushing to MobileOrg, MobileOrg
+Org pushes files listed in @code{org-mobile-files} to
address@hidden  Files include agenda files (as listed in
address@hidden).  Customize @code{org-mobile-files} to add other
+files.  File names will be staged with paths relative to
address@hidden, so all files should be inside this
address@hidden links in @code{org-directory} should have the
+same name as their targets.}.
+
+Push creates a special Org file @file{agendas.org} with custom agenda views
+defined by the address@hidden creating the agendas, Org mode will force
+ID properties on all referenced entries, so that these entries can be
+uniquely identified if MobileOrg flags them for further action.  To avoid
+setting properties configure the variable
address@hidden to @code{nil}.  Org mode will then
+rely on outline paths, assuming they are unique.}.
+
+Org writes the file @file{index.org}, containing links to other files.
+MobileOrg reads this file first from the server to determine what other files
+to download for agendas.  For faster downloads, MobileOrg will read only
+those files whose address@hidden are stored automatically in
+the file @file{checksums.dat}.} have changed.
+
address@hidden Pulling from MobileOrg
 @section Pulling from MobileOrg
 
-When @i{MobileOrg} synchronizes with the server, it not only pulls the Org
-files for viewing.  It also appends captured entries and pointers to flagged
-and changed entries to the file @file{mobileorg.org} on the server.  Org has
-a @emph{pull} operation that integrates this information into an inbox file
-and operates on the pointers to flagged entries.  Here is how it works:
+When MobileOrg synchronizes with the server, it pulls the Org files for
+viewing.  It then appends to the file @file{mobileorg.org} on the server the
+captured entries, pointers to flagged and changed entries.  Org integrates
+its data in an inbox file format.
 
 @enumerate
 @item
@@ -18092,46 +18936,37 @@ Org moves all entries found in
 @address@hidden@file{mobileorg.org} will be empty after this
 operation.} and appends them to the file pointed to by the variable
 @code{org-mobile-inbox-for-pull}.  Each captured entry and each editing event
-will be a top-level entry in the inbox file.
+is a top-level entry in the inbox file.
 @item
-After moving the entries, Org will attempt to implement the changes made in
address@hidden  Some changes are applied directly and without user
-interaction.  Examples are all changes to tags, TODO state, headline and body
-text that can be cleanly applied.  Entries that have been flagged for further
-action will receive a tag @code{:FLAGGED:}, so that they can be easily found
-again.  When there is a problem finding an entry or applying the change, the
-pointer entry will remain in the inbox and will be marked with an error
-message.  You need to later resolve these issues by hand.
+After moving the entries, Org attempts changes to MobileOrg.  Some changes
+are applied directly and without user interaction.  Examples include changes
+to tags, TODO state, headline and body text.  Entries for further action are
+tagged as @code{:FLAGGED:}.  Org marks entries with problems with an error
+message in the inbox.  They have to be resolved manually.
 @item
-Org will then generate an agenda view with all flagged entries.  The user
-should then go through these entries and do whatever actions are necessary.
-If a note has been stored while flagging an entry in @i{MobileOrg}, that note
-will be displayed in the echo area when the cursor is on the corresponding
-agenda line.
+Org generates an agenda view for flagged entries for user intervention to
+clean up.  For notes stored in flagged entries, MobileOrg displays them in
+the echo area when the cursor is on the corresponding agenda item.
 
 @table @kbd
 @kindex ?
 @item ?
-Pressing @kbd{?} in that special agenda will display the full flagging note in
-another window and also push it onto the kill ring.  So you could use @kbd{?
-z C-y C-c C-c} to store that flagging note as a normal note in the entry.
-Pressing @kbd{?} twice in succession will offer to remove the
address@hidden:FLAGGED:} tag along with the recorded flagging note (which is 
stored
-in a property).  In this way you indicate that the intended processing for
-this flagged entry is finished.
+Pressing @kbd{?} displays the entire flagged note in another window.  Org
+also pushes it to the kill ring.  To store flagged note as a normal note, use
address@hidden  z C-y C-c C-c}.  Pressing @kbd{?} twice does these things: 
first it
+removes the @code{:FLAGGED:} tag; second, it removes the flagged note from
+the property drawer; third, it signals that manual editing of the flagged
+entry is now finished.
 @end table
 @end enumerate
 
 @kindex C-c a ?
-If you are not able to process all flagged entries directly, you can always
-return to this agenda address@hidden, however, that there is a subtle
-difference.  The view created automatically by @kbd{M-x org-mobile-pull RET}
-is guaranteed to search all files that have been addressed by the last pull.
-This might include a file that is not currently in your list of agenda files.
-If you later use @kbd{C-c a ?} to regenerate the view, only the current
-agenda files will be searched.} using @kbd{C-c a ?}.
-
address@hidden History and Acknowledgments, GNU Free Documentation License, 
MobileOrg, Top
address@hidden a ?} returns to the agenda view to finish processing flagged
+entries.  Note that these entries may not be the most recent since MobileOrg
+searches files that were last pulled.  To get an updated agenda view with
+changes since the last pull, pull again.
+
address@hidden History and acknowledgments
 @appendix History and acknowledgments
 @cindex acknowledgments
 @cindex history
@@ -18143,17 +18978,17 @@ Org was born in 2003, out of frustration over the 
user interface of the Emacs
 Outline mode.  I was trying to organize my notes and projects, and using
 Emacs seemed to be the natural way to go.  However, having to remember eleven
 different commands with two or three keys per command, only to hide and show
-parts of the outline tree, that seemed entirely unacceptable to me.  Also,
-when using outlines to take notes, I constantly wanted to restructure the
-tree, organizing it parallel to my thoughts and plans.  @emph{Visibility
-cycling} and @emph{structure editing} were originally implemented in the
-package @file{outline-magic.el}, but quickly moved to the more general
address@hidden  As this environment became comfortable for project planning,
-the next step was adding @emph{TODO entries}, basic @emph{timestamps}, and
address@hidden support}.  These areas highlighted the two main goals that Org
-still has today: to be a new, outline-based, plain text mode with innovative
-and intuitive editing features, and to incorporate project planning
-functionality directly into a notes file.
+parts of the outline tree, that seemed entirely unacceptable.  Also, when
+using outlines to take notes, I constantly wanted to restructure the tree,
+organizing it paralleling my thoughts and plans.  @emph{Visibility cycling}
+and @emph{structure editing} were originally implemented in the package
address@hidden, but quickly moved to the more general @file{org.el}.
+As this environment became comfortable for project planning, the next step
+was adding @emph{TODO entries}, basic @emph{timestamps}, and @emph{table
+support}.  These areas highlighted the two main goals that Org still has
+today: to be a new, outline-based, plain text mode with innovative and
+intuitive editing features, and to incorporate project planning functionality
+directly into a notes file.
 
 Since the first release, literally thousands of emails to me or to
 @email{emacs-orgmode@@gnu.org} have provided a constant stream of bug
@@ -18169,15 +19004,17 @@ Before I get to this list, a few special mentions are 
in order:
 @table @i
 @item Bastien Guerry
 Bastien has written a large number of extensions to Org (most of them
-integrated into the core by now), including the @LaTeX{} exporter and the plain
-list parser.  His support during the early days, when he basically acted as
-co-maintainer, was central to the success of this project.  Bastien also
-invented Worg, helped establishing the Web presence of Org, and sponsored
-hosting costs for the orgmode.org website.
+integrated into the core by now), including the @LaTeX{} exporter and the
+plain list parser.  His support during the early days was central to the
+success of this project.  Bastien also invented Worg, helped establishing the
+Web presence of Org, and sponsored hosting costs for the orgmode.org website.
+Bastien stepped in as maintainer of Org between 2011 and 2013, at a time when
+I desperately needed a break.
 @item Eric Schulte and Dan Davison
 Eric and Dan are jointly responsible for the Org-babel system, which turns
 Org into a multi-language environment for evaluating code and doing literate
-programming and reproducible research.
+programming and reproducible research.  This has become one of Org's killer
+features that define what Org is today.
 @item John Wiegley
 John has contributed a number of great ideas and patches directly to Org,
 including the attachment system (@file{org-attach.el}), integration with
@@ -18198,9 +19035,8 @@ let me know what I am missing here!
 
 @section From Bastien
 
-I (Bastien) have been maintaining Org since January 2011.  This appendix
-would not be complete without adding a few more acknowledgements and thanks
-to Carsten's ones above.
+I (Bastien) have been maintaining Org between 2011 and 2013.  This appendix
+would not be complete without adding a few more acknowledgments and thanks.
 
 I am first grateful to Carsten for his trust while handing me over the
 maintainership of Org.  His unremitting support is what really helped me
@@ -18218,13 +19054,13 @@ Eric is maintaining the Babel parts of Org.  His 
reactivity here kept me away
 from worrying about possible bugs here and let me focus on other parts.
 
 @item Nicolas Goaziou
-Nicolas is maintaining the consistency of the deepest parts of Org.  His
-work on @file{org-element.el} and @file{ox.el} has been outstanding, and
-opened the doors for many new ideas and features.  He rewrote many of the
-old exporters to use the new export engine, and helped with documenting
-this major change.  More importantly (if that's possible), he has been more
-than reliable during all the work done for Org 8.0, and always very
-reactive on the mailing list.
+Nicolas is maintaining the consistency of the deepest parts of Org.  His work
+on @file{org-element.el} and @file{ox.el} has been outstanding, and it opened
+the doors for many new ideas and features.  He rewrote many of the old
+exporters to use the new export engine, and helped with documenting this
+major change.  More importantly (if that's possible), he has been more than
+reliable during all the work done for Org 8.0, and always very reactive on
+the mailing list.
 
 @item Achim Gratz
 Achim rewrote the building process of Org, turning some @emph{ad hoc} tools
@@ -18280,13 +19116,14 @@ specified time.
 calculations and improved XEmacs compatibility, in particular by porting
 @file{nouline.el} to XEmacs.
 @item
address@hidden Chua} suggested copying some linking code from Planner.
address@hidden Chua} suggested copying some linking code from Planner, and 
helped
+make Org pupular through her blog.
 @item
 @i{Toby S. Cubitt} contributed to the code for clock formats.
 @item
address@hidden Cui} contributed the DocBook exporter.  It has been deleted from
-Org 8.0: you can now export to Texinfo and export the @file{.texi} file to
-DocBook using @code{makeinfo}.
address@hidden Cui} contributed the first DocBook exporter.  In Org 8.0, we go a
+different route: you can now export to Texinfo and export the @file{.texi}
+file to DocBook using @code{makeinfo}.
 @item
 @i{Eddward DeVilla} proposed and tested checkbox statistics.  He also
 came up with the idea of properties, and that there should be an API for
@@ -18383,7 +19220,7 @@ basis.
 @i{Stefan Monnier} provided a patch to keep the Emacs-Lisp compiler
 happy.
 @item
address@hidden Moreland} wrote @i{MobileOrg} for the iPhone.
address@hidden Moreland} wrote MobileOrg for the iPhone.
 @item
 @i{Rick Moynihan} proposed allowing multiple TODO sequences in a file
 and being able to quickly restrict the agenda to a subtree.
@@ -18501,35 +19338,37 @@ work on a tty.
 @item
 @i{Piotr Zielinski} wrote @file{org-mouse.el}, proposed agenda blocks
 and contributed various ideas and code snippets.
address@hidden
address@hidden Wahl} wrote @file{org-eww.el}.
 @end itemize
 
 
address@hidden GNU Free Documentation License, Main Index, History and 
Acknowledgments, Top
address@hidden GNU Free Documentation License
 @appendix GNU Free Documentation License
 @include doclicense.texi
 
 
address@hidden Main Index, Key Index, GNU Free Documentation License, Top
address@hidden Main Index
 @unnumbered Concept index
 
 @printindex cp
 
address@hidden Key Index, Command and Function Index, Main Index, Top
address@hidden Key Index
 @unnumbered Key index
 
 @printindex ky
 
address@hidden Command and Function Index, Variable Index, Key Index, Top
address@hidden Command and Function Index
 @unnumbered Command and function index
 
 @printindex fn
 
address@hidden Variable Index,  , Command and Function Index, Top
address@hidden Variable Index
 @unnumbered Variable index
 
 This is not a complete index of variables and faces, only the ones that are
-mentioned in the manual.  For a more complete list, use @kbd{M-x
-org-customize @key{RET}} and then click yourself through the tree.
+mentioned in the manual.  For a complete list, use @kbd{M-x org-customize
address@hidden
 
 @printindex vr
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 38df7b2..fb50175 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -1,17 +1,1368 @@
-ORG NEWS -- history of user-visible changes.   -*- mode: org; coding: utf-8 -*-
+ORG NEWS -- history of user-visible changes.           -*- org -*-
 
 #+LINK: doc http://orgmode.org/worg/doc.html#%s
-#+LINK: git http://orgmode.org/w/?p=org-mode.git;a=commit;h=%s
+#+LINK: git http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=%s
 
 Copyright (C) 2012-2017 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
-Please send Org bug reports to address@hidden
+Please send Org bug reports to mailto:address@hidden
 
-* Version 8.2.3
+* Version 9.0
 
 ** Incompatible changes
 
+*** Emacs 23 support has been dropped
+
+From now on, Org expects at least Emacs 24.3, although Emacs 24.4 or
+above is suggested.
+
+*** XEmacs support has been dropped
+
+Incomplete compatibility layer with XEmacs has been removed.  If you
+want to take over maintainance of this compatibility, please contact
+our mailing list.
+
+*** New syntax for export blocks
+
+Export blocks are explicitly marked as such at the syntax level to
+disambiguate their parsing from special blocks.  The new syntax is
+
+#+BEGIN_SRC org
+,#+BEGIN_EXPORT backend
+...
+,#+END_EXPORT
+#+END_SRC
+
+instead of
+
+#+BEGIN_SRC org
+,#+BEGIN_backend
+...
+,#+END_backend
+#+END_SRC
+
+As a consequence, =INCLUDE= keywords syntax is modified, e.g.,
+
+#+BEGIN_SRC org
+,#+INCLUDE: "file.org" HTML
+#+END_SRC
+
+becomes
+
+#+BEGIN_SRC org
+,#+INCLUDE: "file.org" export html
+#+END_SRC
+
+The following function repairs export blocks and =INCLUDE= keywords
+using previous syntax:
+
+#+BEGIN_SRC emacs-lisp
+(defun org-repair-export-blocks ()
+  "Repair export blocks and INCLUDE keywords in current buffer."
+  (interactive)
+  (when (eq major-mode 'org-mode)
+    (let ((case-fold-search t)
+          (back-end-re (regexp-opt
+                        '("HTML" "ASCII" "LATEX" "ODT" "MARKDOWN" "MD" "ORG"
+                          "MAN" "BEAMER" "TEXINFO" "GROFF" "KOMA-LETTER")
+                        t)))
+      (org-with-wide-buffer
+       (goto-char (point-min))
+       (let ((block-re (concat "^[ \t]*#\\+BEGIN_" back-end-re)))
+         (save-excursion
+           (while (re-search-forward block-re nil t)
+             (let ((element (save-match-data (org-element-at-point))))
+               (when (eq (org-element-type element) 'special-block)
+                 (save-excursion
+                   (goto-char (org-element-property :end element))
+                   (save-match-data (search-backward "_"))
+                   (forward-char)
+                   (insert "EXPORT")
+                   (delete-region (point) (line-end-position)))
+                 (replace-match "EXPORT \\1" nil nil nil 1))))))
+       (let ((include-re
+              (format "^[ \t]*#\\+INCLUDE: .*?%s[ \t]*$" back-end-re)))
+         (while (re-search-forward include-re nil t)
+           (let ((element (save-match-data (org-element-at-point))))
+             (when (and (eq (org-element-type element) 'keyword)
+                        (string= (org-element-property :key element) 
"INCLUDE"))
+               (replace-match "EXPORT \\1" nil nil nil 1)))))))))
+#+END_SRC
+
+Moreover, ~:export-block~ keyword used in ~org-export-define-backend~ and
+~org-export-define-derived-backend~ is no longer used and needs to be
+removed.
+
+*** Footnotes
+
+**** [1]-like constructs are not valid footnotes
+
+Using =[1]= as a footnote was already discouraged in the manual, since
+it introduced too many false-positives in many Org documents.  These
+constructs are now unsupported.
+
+If you used =[N]= in some of your documents, consider turning them into
+=[fn:N]=.
+
+**** /Org Footnote/ library doesn't handle non-Org buffers
+
+Commands for footnotes in an Org document no longer try to do
+something in non-Org ones.  If you need to have footnotes there,
+consider using the =footnote.el= library, shipped with Emacs.
+
+In particular, ~org-footnote-tag-for-non-org-mode-files~ no longer
+exists.
+
+*** ~org-file-apps~ no longer accepts S-expressions as commands
+
+The variable now accepts functions of two arguments instead of plain
+S-expressions.  Replacing a S-expresion with an appropriate function
+is straightforward.  For example
+
+: ("pdf" . (foo))
+
+becomes
+
+: ("pdf" . (lambda (file link) (foo)))
+
+*** The ~{{{modification-time}}}~ macro can get time via =vc=
+
+The modification time will be determined via =vc.el= if the second
+argument is non-nil.  See the manual for details.
+
+*** Preparation and completion functions in publishing projects change 
signature
+
+Preparation and completion functions are now called with an argument,
+which is the project property list.  It used to be dynamically scoped
+through the ~project-plist~ variable.
+
+*** Old Babel header properties are no longer supported
+
+Using header arguments as property names is no longer possible.  As
+such, the following
+
+#+BEGIN_EXAMPLE
+,* Headline
+:PROPERTIES:
+:exports: code
+:var: a=1 b=2
+:var+: c=3
+:END:
+#+END_EXAMPLE
+
+should be written instead
+
+#+BEGIN_EXAMPLE
+,* Headline
+:PROPERTIES:
+:header-args: :exports code
+:header-args: :var a=1 b=2
+:header-args+: :var c=3
+:END:
+#+END_EXAMPLE
+
+Please note that, however, old properties were defined at the source
+block definition.  Current ones are defined where the block is called.
+
+** New features
+
+*** ~org-eww~ has been moved into core
+*** New org-protocol key=value syntax
+
+Org-protocol can now handle query-style parameters such as:
+
+#+begin_example
+org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title
+org-protocol://capture?template=x&title=Hello&body=World&url=http:%2F%2Fexample.com
+#+end_example
+
+Old-style links such as
+: org-protocol://store-link:/http:%2F%2Flocalhost%2Findex.html/The%20title
+continue to be supported.
+
+If you have defined your own handler functions for
+~org-protocol-protocol-alist~, change them to accept either a property
+list (for new-style links) or a string (for old-style links).  Use
+~org-protocol-parse-parameters~ to convert old-style links into property
+lists.
+
+*** New Org linter library
+
+~org-lint~ can check syntax and report common issues in Org documents.
+
+*** New option ~date-tree-last~ for ~org-agenda-insert-diary-strategy~
+
+When ~org-agenda-insert-diary-strategy~ is set to ~date-tree-last~, diary
+entries are added to last in the date tree.
+
+*** New ~vbar~ entity
+
+~\vbar~ or ~\vbar{}~ will be exported unconditionnally as a =|=,
+unlike to existing ~\vert~, which is expanded as ~&vert;~ when using
+a HTML derived export back-end.
+
+*** Export
+
+**** New =#+latex_compiler= keyword to set LaTeX compiler.
+
+PDFLaTeX, XeLaTeX, and LuaLaTeX are supported.  See the manual for
+details.
+
+**** New option ~org-export-with-broken-links~
+
+This option tells the export process how to behave when encountering
+a broken internal link.  See its docstring for more information.
+
+**** Attributes support in custom language environments for LaTeX export
+
+Custom language environments for LaTeX export can now define the
+string to be inserted during export, using attributes to indicate the
+position of the elements. See variable ~org-latex-custom-lang-environments~
+for more details.
+
+**** New Texinfo ~options~ attribute on special blocks
+
+Using ~:options~ as a Texinfo attribute, it is possible to add
+information to custom environments.  See manual for details.
+
+**** New HTML ~id~ attributes on special, example and quote blocks
+
+If the block has a =#+NAME:= attribute assigned, then the HTML element
+will have an ~id~ attribute with that name in the HTML export. This
+enables one to create links to these elements in other places, e.g.,
+~<a href="#name">text</a>~.
+
+**** Listings with captions are now numbered in HTML export
+
+The class associated to the numbering is "listing-number".  If you
+don't want these blocks to be numbered, as it was the case until now,
+You may want to add ~.listing-number { display: none; }~ to the CSS
+used.
+
+**** Line Numbering in SRC/EXAMPLE blocks support arbitrary start number
+
+The ~-n~ option to ~SRC~ and ~EXAMPLE~ blocks can now take a numeric
+argument to specify the staring line number for the source or example
+block.  The ~+n~ option can now take a numeric argument that will be
+added to the last line number from the previous block as the starting
+point for the SRC/EXAMPLE block.
+
+#+BEGIN_SRC org
+,#+BEGIN_SRC emacs-lisp -n 20
+;; this will export with line number 20
+(message "This is line 21")
+,#+END_SRC
+,#+BEGIN_SRC emacs-lisp +n 10
+;; This will be listed as line 31
+(message "This is line 32")
+,#+END_SRC
+#+END_SRC
+
+**** Allow toggling center for images in LaTeX export
+
+With the global variable ~org-latex-images-centered~ or the local
+attribute ~:center~ it is now possible to center an image in LaTeX
+export.
+
+**** Default CSS class ~org-svg~ for SVG images in HTML export
+
+SVG images exported in HTML are now by default assigned a CSS class
+~org-svg~ if no CSS class is specified with the ~:class~ attribute. By
+default, the CSS styling of class ~org-svg~ specifies an image width of
+90\thinsp{}% of the container the image.
+
+**** Markdown footnote export customization
+
+Variables ~org-md-footnotes-section~ and ~org-md-footnote-format~
+introduced for =ox-md.el=.  Both new variables define template strings
+which can be used to customize the format of the exported footnotes
+section and individual footnotes, respectively.
+
+*** Babel
+
+**** Blocks with coderefs labels can now be evaluated
+
+The labels are removed prior to evaluating the block.
+
+**** Support for Lua language
+**** Support for SLY in Lisp blocks
+
+See ~org-babel-lisp-eval-fn~ to activate it.
+
+**** Support for Stan language
+
+New ob-stan.el library.
+
+Evaluating a Stan block can produce two different results.
+
+1. Dump the source code contents to a file.
+
+   This file can then be used as a variable in other blocks, which
+   allows interfaces like RStan to use the model.
+
+2. Compile the contents to a model file.
+
+   This provides access to the CmdStan interface.  To use this, set
+   ~org-babel-stan-cmdstan-directory~ and provide a ~:file~ argument
+   that does not end in ".stan".
+
+For more information and usage examples, visit
+http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html
+
+**** Support for Oracle databases via ~sqlplus~
+
+=ob-sql= library supports running SQL blocks against an Oracle
+database using ~sqlplus~.  Use with properties like this (all
+mandatory):
+
+#+BEGIN_EXAMPLE
+:engine oracle
+:dbhost <host.com>
+:dbport <1521>
+:dbuser <username>
+:database <database>
+:dbpassword <secret>
+#+END_EXAMPLE
+
+**** Improved support to Microsoft SQL Server via ~sqlcmd~
+
+=ob-sql= library removes support to the ~msosql~ engine which uses the
+deprecated ~osql~ command line tool, and replaces it with ~mssql~
+engine which uses the ~sqlcmd~ command line tool.  Use with properties
+like this:
+
+#+BEGIN_EXAMPLE
+:engine mssql
+:dbhost <host.com>
+:dbuser <username>
+:dbpassword <secret>
+:database <database>
+#+END_EXAMPLE
+
+If you want to use the *trusted connection* feature, omit *both* the
+=dbuser= and =dbpassword= properties and add =cmdline -E= to the properties.
+
+If your Emacs is running in a Cygwin environment, the =ob-sql= library
+can pass the converted path to the =sqlcmd= tool.
+
+**** Improved support of header arguments for postgresql
+
+The postgresql engine in a sql code block supports now ~:dbport~ nd
+~:dbpassword~ as header arguments.
+
+**** Support for additional plantuml output formats
+
+The support for output formats of [[http://plantuml.com/][plantuml]] has been 
extended to now
+include:
+
+All Diagrams:
+- png ::
+- svg ::
+- eps ::
+- pdf ::
+- vdx ::
+- txt :: ASCII art
+- utxt :: ASCII art using unicode characters
+
+Class Diagrams:
+- xmi ::
+- html ::
+
+State Diagrams:
+- scxml ::
+
+The output formats are determined by the file extension specified
+using the :file property, e.g.:
+
+#+begin_src plantuml :file diagram.png
address@hidden
+Alice -> Bob: Authentication Request
+Bob --> Alice: Authentication Response
+
+Alice -> Bob: Another authentication Request
+Alice <-- Bob: another authentication Response
address@hidden
+#+end_src
+
+Please note that *pdf* *does not work out of the box* and needs additional
+setup in addition to plantuml.  See [[http://plantuml.com/pdf.html]] for
+details and setup information.
+
+*** Rewrite of radio lists
+
+Radio lists, i.e, Org plain lists in foreign buffers, have been
+rewritten to be on par with Radio tables.  You can use a large set of
+parameters to control how a given list should be rendered.  See manual
+for details.
+
+*** org-bbdb-anniversaries-future
+
+Used like ~org-bbdb-anniversaries~, it provides a few days warning for
+upcoming anniversaries (default: 7 days).
+
+*** Clear non-repeated SCHEDULED upon repeating a task
+
+If the task is repeated, and therefore done at least one, scheduling
+information is no longer relevant.  It is therefore removed.
+
+See [[git:481719fbd5751aaa9c672b762cb43aea8ee986b0][commit message]] for more 
information.
+
+*** Support for ISO week trees
+
+ISO week trees are an alternative date tree format that orders entries
+by ISO week and not by month.
+
+For example:
+
+: * 2015
+: ** 2015-W35
+: ** 2015-W36
+: *** 2015-08-31 Monday
+
+They are supported in org-capture via ~file+weektree~ and
+~file+weektree+prompt~ target specifications.
+
+*** Accept ~:indent~ parameter when capturing column view
+
+When defining a "columnview" dynamic block, it is now possible to add
+an :indent parameter, much like the one in the clock table.
+
+On the other hand, stars no longer appear in an ITEM field.
+
+*** Columns view
+
+**** ~org-columns~ accepts a prefix argument
+
+When called with a prefix argument, ~org-columns~ apply to the whole
+buffer unconditionally.
+
+**** New variable : ~org-agenda-view-columns-initially~
+
+The variable used to be a ~defvar~, it is now a ~defcustom~.
+
+**** Allow custom summaries
+
+It is now possible to add new summary types, or override those
+provided by Org by customizing ~org-columns-summary-types~, which see.
+
+**** Allow multiple summaries for any property
+
+Columns can now summarize the same property using different summary
+types.
+
+*** Preview LaTeX snippets in buffers not visiting files
+*** New option ~org-attach-commit~
+
+When non-nil, commit attachments with git, assuming the document is in
+a git repository.
+
+*** Allow conditional case-fold searches in ~org-occur~
+
+When set to ~smart~, the new variable ~org-occur-case-fold-search~ allows
+to mimic =isearch.el=: if the regexp searched contains any upper case
+character (or character class), the search is case sensitive.
+Otherwise, it is case insensitive.
+
+*** More robust repeated =ox-latex= footnote handling
+
+Repeated footnotes are now numbered by referring to a label in the
+first footnote.
+
+*** The ~org-block~ face is inherited by ~src-blocks~
+
+This works also when =org-src-fontify-natively= is non-nil.  It is also
+possible to specify per-languages faces.  See =org-src-block-faces= and
+the manual for details.
+
+*** Links are now customizable
+
+Links can now have custom colors, tooltips, keymaps, display behavior,
+etc.  Links are now centralized in ~org-link-parameters~.
+
+** New functions
+
+*** ~org-next-line-empty-p~
+
+It replaces the deprecated ~next~ argument to ~org-previous-line-empty-p~.
+
+*** ~org-show-children~
+
+It is a faster implementation of ~outline-show-children~.
+
+** Removed functions
+
+*** ~org-agenda-filter-by-tag-refine~ has been removed.
+
+Use ~org-agenda-filter-by-tag~ instead.
+
+*** ~org-agenda-todayp~ is deprecated.
+
+Use ~org-agenda-today-p~ instead.
+
+*** ~org-babel-get-header~ is removed.
+
+Use ~org-babel--get-vars~ or ~assq~ instead, as applicable.
+
+*** ~org-babel-trim~ is deprecated.
+
+Use ~org-trim~ instead.
+
+*** ~org-element-remove-indentation~ is deprecated.
+
+Use ~org-remove-indentation~ instead.
+
+*** ~org-image-file-name-regexp~ is deprecated
+
+Use ~image-file-name-regexp~ instead.
+The never-used-in-core ~extensions~ argument has been dropped.
+
+*** ~org-list-parse-list~ is deprecated
+
+Use ~org-list-to-lisp~ instead.
+
+*** ~org-on-heading-p~ is deprecated
+
+A comment to this effect was in the source code since 7.8.03, but
+now a byte-compiler warning will be generated as well.
+
+*** ~org-table-p~ is deprecated
+
+Use ~org-at-table-p~ instead.
+
+*** ~org-table-recognize-table.el~ is deprecated
+
+It was not called by any org code since 2010.
+
+*** Various reimplementations of cl-lib functions are deprecated
+
+The affected functions are:
+- ~org-count~
+- ~org-remove-if~
+- ~org-remove-if-not~
+- ~org-reduce~
+- ~org-every~
+- ~org-some~
+
+Additionally, ~org-sublist~ is deprecated in favor of ~cl-subseq~.  Note
+the differences in indexing conventions: ~org-sublist~ is 1-based and
+end-inclusive; ~cl-subseq~ is 0-based and end-exclusive.
+
+** Removed options
+
+*** Remove all options related to ~ido~ or ~iswitchb~
+
+This includes ~org-completion-use-iswitchb~ and ~org-completion-use-ido~.
+Instead Org uses regular functions, e.g., ~completion-read~ so as to
+let those libraries operate.
+
+*** Remove ~org-list-empty-line-terminates-plain-lists~
+
+Two consecutive blank lines always terminate all levels of current
+plain list.
+
+*** ~fixltx2e~ is removed from ~org-latex-default-packages-alist~
+
+fixltx2e is obsolete, see LaTeX News 22.
+
+** Miscellaneous
+*** Add Icelandic smart quotes
+*** Allow multiple receiver locations in radio tables and lists
+*** Allow angular links within link descriptions
+
+It is now allowed to write, e.g.,
+~[[http:orgmode.org][<file:unicorn.png>]]~ as an equivalent to
+~[[http:orgmode.org][file:unicorn.png]]~.  The advantage of the former
+is that spaces are allowed within the path.
+
+*** Beamer export back-ends uses ~org-latex-prefer-user-labels~
+*** ~:preparation-function~ called earlier during publishing
+
+Functions in this list are called before any file is associated to the
+current projet.  Thus, they can be used to generate to be published
+Org files.
+
+*** Function ~org-remove-indentation~ changes.
+
+The new algorithm doesn't remove TAB characters not used for
+indentation.
+
+*** Secure placeholders in capture templates
+
+Placeholders in capture templates are no longer expanded recursively.
+However, ~%(...)~ constructs are expanded very late, so you can fill
+the contents of the S-exp with the replacement text of non-interactive
+placeholders.  As before, interactive ones are still expanded as the
+very last step, so the previous statement doesn't apply to them.
+
+Note that only ~%(...)~ placeholders initially present in the
+template, or introduced using a file placeholder, i.e., ~%[...]~ are
+expanded.  This prevents evaluating potentially malicious code when
+another placeholder, e.g., ~%i~ expands to a S-exp.
+
+*** Links stored by ~org-gnus-store-link~ in nnir groups
+
+Since gnus nnir groups are temporary, ~org-gnus-store-link~ now refers
+to the article's original group.
+
+*** ~org-babel-check-confirm-evaluate~ is now a function instead of a macro
+
+The calling convention has changed.
+
+*** HTML export table row customization changes
+
+Variable ~org-html-table-row-tags~ has been split into
+~org-html-table-row-open-tag~ and ~org-html-table-row-close-tag~.
+Both new variables can be either a string or a function which will be
+called with 6 parameters.
+
+*** =ITEM= special property returns headline without stars
+*** Rename ~org-insert-columns-dblock~ into ~org-columns-insert-dblock~
+
+The previous name is, for the time being, kept as an obsolete alias.
+
+*** ~org-trim~ can preserve leading indentation.
+
+When setting a new optional argument to a non-nil value, ~org-trim~
+preserves leading indentation while removing blank lines at the
+beginning of the string.  The behavior is identical for white space at
+the end of the string.
+
+*** Function ~org-info-export~ changes.
+
+HTML links created from certain info links now point to =gnu.org= URL's rather
+than just to local files. For example info links such as =info:emacs#List
+Buffers= used to be converted to HTML links like this:
+
+: <a href="emacs.html#List-Buffers">emacs#List Buffers</a>
+
+where local file =emacs.html= is referenced.
+For most folks this file does not exist.
+Thus the new behavior is to generate this HTML link instead:
+
+: <a 
href="http://www.gnu.org/software/emacs/manual/html_mono/emacs.html#List-Buffers";>emacs#List
 Buffers</a>
+
+All emacs related info links are similarly translated plus few other
+=gnu.org= manuals.
+
+*** Repeaters with a ~++~ interval and a time can be shifted to later today
+
+Previously, if a recurring task had a timestamp of
+~<2016-01-01 Fri 20:00 ++1d>~ and was completed on =2016-01-02= at
+=08:00=, the task would skip =2016-01-02= and would be rescheduled for
+=2016-01-03=.  Timestamps with ~++~ cookies and a specific time will
+now shift to the first possible future occurrence, even if the
+occurrence is later the same day the task is completed.  (Timestamps
+already in the future are still shifted one time further into the
+future.)
+
+*** ~org-mobile-action-alist~ is now a defconst
+
+It used to be a defcustom, with a warning that it shouldn't be
+modified anyway.
+
+*** ~file+emacs~ and ~file+sys~ link types are deprecated
+
+They are still supported in Org 9.0 but will eventually be removed in
+a later release.  Use ~file~ link type along with universal arguments
+to force opening it in either Emacs or with system application.
+
+*** New defcustom ~org-babel-J-command~ stores the j command
+*** New defalias ~org-babel-execute:j~
+
+Allows J source blocks be indicated by letter j.  Previously the
+indication letter was solely J.
+
+*** ~org-open-line~ ignores tables at the very beginning of the buffer
+
+When ~org-special-ctrl-o~ is non-nil, it is impractical to create
+a blank line above a table at the beginning of the document. Now, as
+a special case, ~org-open-line~ behaves normally in this situation.
+
+*** ~org-babel-hash-show-time~ is now customizable
+
+The experimental variable used to be more or less confidential, as
+a ~defvar~.
+
+*** New ~:format~ property to parsed links
+
+It defines the format of the original link.  Possible values are:
+~plain~, ~bracket~ and ~angle~.
+
+* Version 8.3
+
+** Incompatible changes
+
+*** Properties drawers syntax changes
+
+Properties drawers are now required to be located right after a
+headline and its planning line, when applicable.
+
+It will break some documents as TODO states changes were sometimes
+logged before the property drawer.
+
+The following function will repair them:
+
+#+BEGIN_SRC emacs-lisp
+(defun org-repair-property-drawers ()
+  "Fix properties drawers in current buffer.
+Ignore non Org buffers."
+  (when (eq major-mode 'org-mode)
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (let ((case-fold-search t)
+           (inline-re (and (featurep 'org-inlinetask)
+                           (concat (org-inlinetask-outline-regexp)
+                                   "END[ \t]*$"))))
+       (org-map-entries
+        (lambda ()
+          (unless (and inline-re (org-looking-at-p inline-re))
+            (save-excursion
+              (let ((end (save-excursion (outline-next-heading) (point))))
+                (forward-line)
+                (when (org-looking-at-p org-planning-line-re) (forward-line))
+                (when (and (< (point) end)
+                           (not (org-looking-at-p org-property-drawer-re))
+                           (save-excursion
+                             (and (re-search-forward org-property-drawer-re 
end t)
+                                  (eq (org-element-type
+                                       (save-match-data 
(org-element-at-point)))
+                                      'drawer))))
+                  (insert (delete-and-extract-region
+                           (match-beginning 0)
+                           (min (1+ (match-end 0)) end)))
+                  (unless (bolp) (insert "\n"))))))))))))
+#+END_SRC
+
+*** Using "COMMENT" is now equivalent to commenting with "#"
+
+If you used "COMMENT" in headlines to prevent a subtree from being
+exported, you can still do it but all information within the subtree
+is now commented out, i.e. no #+OPTIONS line will be parsed or taken
+into account when exporting.
+
+If you want to exclude a headline from export while using its contents
+for setting options, use =:noexport:= (see =org-export-exclude-tags=.)
+
+*** =#+CATEGORY= keywords no longer apply partially to document
+
+It was possible to use several such keywords and have them apply to
+the text below until the next one, but strongly deprecated since Org
+5.14 (2008).
+
+=#+CATEGORY= keywords are now global to the document.  You can use node
+properties to set category for a subtree, e.g.,
+
+#+BEGIN_SRC org
+,* Headline
+   :PROPERTIES:
+   :CATEGORY: some category
+   :END:
+#+END_SRC
+
+*** New variable to control visibility when revealing a location
+
+~org-show-following-heading~, ~org-show-siblings~, ~org-show-entry-below~
+and ~org-show-hierarchy-above~ no longer exist.  Instead, visibility is
+controlled through a single variable: ~org-show-context-detail~, which
+see.
+
+*** Replace disputed keys again when reading a date
+
+~org-replace-disputed-keys~ has been ignored when reading date since
+version 8.1, but the former behavior is restored again.
+
+Keybinding for reading date can be customized with a new variable
+~org-read-date-minibuffer-local-map~.
+
+*** No default title is provided when =TITLE= keyword is missing
+
+Skipping =TITLE= keyword no longer provides the current file name, or
+buffer name, as the title.  Instead, simply ignore the title.
+
+*** Default bindings of =C-c C-n= and =C-c C-p= changed
+
+The key sequences =C-c C-n= and =C-c C-p= are now bound to
+~org-next-visible-heading~ and ~org-previous-visible-heading~
+respectively, rather than the =outline-mode= versions of these
+functions.  The Org version of these functions skips over inline tasks
+(and even-level headlines when ~org-odd-levels-only~ is set).
+
+*** ~org-element-context~ no longer return objects in keywords
+
+~org-element-context~ used to return objects on some keywords, i.e.,
+=TITLE=, =DATE= and =AUTHOR=.  It now returns only the keyword.
+
+*** ~org-timer-default-timer~ type changed from number to string
+
+If you have, in your configuration, something like =(setq
+org-timer-default-timer 10)= replace it with =(setq
+org-timer-default-timer "10")=.
+
+*** Functions signature changes
+
+The following functions require an additional argument.  See their
+docstring for more information.
+
+- ~org-export-collect-footnote-definitions~
+- ~org-html-format-headline-function~
+- ~org-html-format-inlinetask-function~
+- ~org-latex-format-headline-function~
+- ~org-latex-format-inlinetask-function~
+- ~org-link-search~
+
+** New features
+
+*** Default lexical evaluation of emacs-lisp src blocks
+
+Emacs-lisp src blocks in babel are now evaluated using lexical
+scoping.  There is a new header to control this behavior.
+
+The default results in an eval with lexical scoping.
+:lexical yes
+
+This turns lexical scoping off in the eval (the former behavior).
+:lexical no
+
+This uses the lexical environment with x=42 in the eval.
+:lexical '((x . 42))
+
+*** Behavior of ~org-return~ changed
+
+If point is before or after the headline title, insert a new line
+without changing the headline.
+
+*** Hierarchies of tags
+
+The functionality of nesting tags in hierarchies is added to org-mode.
+This is the generalization of what was previously called "Tag groups"
+in the manual.  That term is now changed to "Tag hierarchy".
+
+The following in-buffer definition:
+
+#+BEGIN_SRC org
+  ,#+TAGS: [ Group : SubOne SubTwo ]
+  ,#+TAGS: [ SubOne : SubOne1 SubOne2 ]
+  ,#+TAGS: [ SubTwo : SubTwo1 SubTwo2 ]
+#+END_SRC
+
+Should be seen as the following tree of tags:
+
+- Group
+  - SubOne
+    - SubOne1
+    - SubOne2
+  - SubTwo
+    - SubTwo1
+    - SubTwo2
+
+Searching for "Group" should return all tags defined above.  Filtering
+on SubOne filters also it's sub-tags.  Etc.
+
+There is no limit on the depth for the tag hierarchy.
+
+*** Additional syntax for non-unique grouptags
+
+Additional syntax is defined for grouptags if the tags in the group
+don't have to be distinct on a heading.
+
+Grouptags had to previously be defined with { }.  This syntax is
+already used for exclusive tags and Grouptags need their own,
+non-exclusive syntax.  This behaviour is achieved with [ ].  Note: { }
+can still be used also for Grouptags but then only one of the given
+tags can be used on the headline at the same time.  Example:
+
+[ group : sub1 sub2 ]
+
+#+BEGIN_SRC org
+,* Test                                                            :sub1:sub2:
+#+END_SRC
+
+This is a more general case than the already existing syntax for
+grouptags; { }.
+
+*** Define regular expression patterns as tags
+
+Tags can be defined as grouptags with regular expressions as
+"sub-tags".
+
+The regular expressions in the group must be marked up within { }.
+Example use:
+
+: #+TAGS: [ Project : address@hidden ]
+
+Searching for the tag Project will now list all tags also including
+regular expression matches for address@hidden  This is good for example for
+projects tagged with a common identifier, i.e. address@hidden
+
+*** Filtering in the agenda on grouptags (Tag hierarchies)
+
+Filtering in the agenda on grouptags filters all of the related tags.
+Except if a filter is applied with a (double) prefix-argument.
+
+Filtering in the agenda on subcategories does not filter the "above"
+levels anymore.
+
+If a grouptag contains a regular expression the regular expression
+is also used as a filter.
+
+*** Minor refactoring of ~org-agenda-filter-by-tag~
+
+Now uses the argument ARG and optional argument exclude instead of
+strip and narrow.  ARG because the argument has multiple purposes and
+makes more sense than strip now.  The term "narrowing" is changed to
+exclude.
+
+The main purpose is for the function to make more logical sense when
+filtering on tags now when tags can be structured in hierarchies.
+
+*** Babel: support for sed scripts
+
+Thanks to Bjarte Johansen for this feature.
+
+*** Babel: support for Processing language
+
+New ob-processing.el library.
+
+This library implements necessary functions for implementing editing
+of Processing code blocks, viewing the resulting sketches in an
+external viewer, and HTML export of the sketches.
+
+Check the documentation for more details.
+
+Thanks to Jarmo Hurri for this feature.
+
+*** New behaviour for ~org-toggle-latex-fragment~
+
+The new behaviour is the following:
+
+- With a double prefix argument or with a single prefix argument when
+  point is before the first headline, toggle overlays in the whole
+  buffer;
+
+- With a single prefix argument, toggle overlays in the current
+  subtree;
+
+- On latex code, toggle overlay at point;
+
+- Otherwise, toggle overlays in the current section.
+
+*** Additional markup with =#+INCLUDE= keyword
+
+The content of the included file can now be optionally marked up, for
+instance as HTML.  See the documentation for details.
+
+*** File links with =#+INCLUDE= keyword
+
+Objects can be extracted via =#+INCLUDE= using file links.  It is
+possible to include only the contents of the object.  See manual for
+more information.
+
+*** Drawers do not need anymore to be referenced in =#+DRAWERS=
+
+One can use a drawer without listing it in the =#+DRAWERS= keyword,
+which is now obsolete.  As a consequence, this change also deprecates
+~org-drawers~ variable.
+
+*** ~org-edit-special~ can edit export blocks
+
+Using C-c ' on an export block now opens a sub-editing buffer.  Major
+mode in that buffer is determined by export backend name (e.g.,
+"latex" \to "latex-mode").  You can define exceptions to this rule by
+configuring ~org-src-lang-modes~, which see.
+
+*** Additional =:hline= processing to ob-shell
+
+If the argument =:hlines yes= is present in a babel call, an optional
+argument =:hlines-string= can be used to define a string to use as a
+representation for the lisp symbol ='hline= in the shell program.  The
+default is =hline=.
+
+*** Markdown export supports switches in source blocks
+
+For example, it is now possible to number lines using the =-n= switch in
+a source block.
+
+*** New option in ASCII export
+
+Plain lists can have an extra margin by setting ~org-ascii-list-margin~
+variable to an appopriate integer.
+
+*** New blocks in ASCII export
+
+ASCII export now supports =#+BEGIN_JUSTIFYRIGHT= and =#+BEGIN_JUSTIFYLEFT=
+blocks.  See documentation for details.
+
+*** More back-end specific publishing options
+
+The number of publishing options specific to each back-end has been
+increased.  See manual for details.
+
+*** Export inline source blocks
+
+Inline source code was used to be removed upon exporting.  They are
+now handled as standard code blocks, i.e., the source code can appear
+in the output, depending on the parameters.
+
+*** Extend ~org-export-first-sibling-p~ and ~org-export-last-sibling-p~
+
+These functions now support any element or object, not only headlines.
+
+*** New function: ~org-export-table-row-in-header-p~
+
+*** New function: ~org-export-get-reference~
+
+*** New function: ~org-element-lineage~
+
+This function deprecates ~org-export-get-genealogy~.  It also provides
+more features.  See docstring for details.
+
+*** New function: ~org-element-copy~
+
+*** New filter: ~org-export-filter-body-functions~
+
+Functions in this filter are applied on the body of the exported
+document, befor wrapping it within the template.
+
+*** New :environment parameter when exporting example blocks to LaTeX
+
+: #+ATTR_LATEX: :environment myverbatim
+: #+BEGIN_EXAMPLE
+: This sentence is false.
+: #+END_EXAMPLE
+
+will be exported using address@hidden(myverbatim)= instead of 
address@hidden(verbatim)=.
+
+*** Various improvements on radio tables
+
+Radio tables feature now relies on Org's export framework ("ox.el").
+~:no-escape~ parameter no longer exists, but additional global
+parameters are now supported: ~:raw~, ~:backend~.  Moreover, there are new
+parameters specific to some pre-defined translators, e.g.,
+~:environment~ and ~:booktabs~ for ~orgtbl-to-latex~.  See translators
+docstrings (including ~orgtbl-to-generic~) for details.
+
+*** Non-floating minted listings in Latex export
+
+It is not possible to specify =#+attr_latex: :float nil= in conjunction
+with source blocks exported by the minted package.
+
+*** Field formulas can now create columns as needed
+
+Previously, evaluating formulas that referenced out-of-bounds columns
+would throw an error. A new variable ~org-table-formula-create-columns~
+was added to adjust this behavior. It is now possible to silently add
+new columns, to do so with a warning or to explicitly ask the user
+each time.
+
+*** ASCII plot
+
+Ability to plot values in a column through ASCII-art bars.  See manual
+for details.
+
+*** New hook: ~org-archive-hook~
+
+This hook is called after successfully archiving a subtree, with point
+on the original subtree, not yet deleted.
+
+*** New option: ~org-attach-archive-delete~
+
+When non-nil, attachments from archived subtrees are removed.
+
+*** New option: ~org-latex-caption-above~
+
+This variable generalizes ~org-latex-table-caption-above~, which is now
+deprecated.  In addition to tables, it applies to source blocks,
+special blocks and images.  See docstring for more information.
+
+*** New option: ~org-latex-prefer-user-labels~
+
+See the docstring for more information.
+
+*** Export unnumbered headlines
+
+Headlines, for which the property ~UNNUMBERED~ is non-nil, are now
+exported without section numbers irrespective of their levels.  The
+property is inherited by children.
+
+*** Tables can be sorted with an arbitrary function
+
+It is now possible to specify a function, both programatically,
+through a new optional argument, and interactively with ~f~ or ~F~ keys,
+to sort a table.
+
+*** Table of contents can be local to a section
+
+The ~TOC~ keywords now accepts an optional ~local~ parameter.  See manual
+for details.
+
+*** Countdown timers can now be paused
+
+~org-timer-pause-time~ now pauses and restarts both relative and
+countdown timers.
+
+*** New option ~only-window~ for ~org-agenda-window-setup~
+
+When ~org-agenda-window-setup~ is set to ~only-window~, the agenda is
+displayed as the sole window of the current frame.
+
+*** ~{{{date}}}~ macro supports optional formatting argument
+
+It is now possible to supply and optional formatting argument to
+~{{{date}}}~. See manual for details.
+
+*** ~{{{property}}}~ macro supports optional search argument
+
+It is now possible to supply an optional search option to
+~{{{property}}}~ in order to retrieve remote properties optional.  See
+manual for details.
+
+*** New option ~org-export-with-title~
+
+It is possible to suppress the title insertion with ~#+OPTIONS:
+title:nil~ or globally using the variable ~org-export-with-title~.
+
+*** New entities family: "\_ "
+
+"\_ " are used to insert up to 20 contiguous spaces in various
+back-ends.  In particular, this family can be used to introduce
+leading spaces within table cells.
+
+*** New MathJax configuration options
+
+Org uses the MathJax CDN by default.  See the manual and the docstring
+of ~org-html-mathjax-options~ for details.
+
+*** New behaviour in `org-export-options-alist'
+
+When defining a back-end, it is now possible to specify to give
+`parse' behaviour on a keyword.  It is equivalent to call
+`org-element-parse-secondary-string' on the value.
+
+However, parsed =KEYWORD= is automatically associated to an
+=:EXPORT_KEYWORD:= property, which can be used to override the keyword
+value during a subtree export.  Moreover, macros are expanded in such
+keywords and properties.
+
+*** Viewport support in html export
+
+Viewport for mobile-optimized website is now automatically inserted
+when exporting to html.  See ~org-html-viewport~ for details.
+
+*** New ~#+SUBTITLE~ export keyword
+
+Org can typeset a subtitle in some export backends.  See the manual
+for details.
+
+*** Remotely edit a footnote definition
+
+Calling ~org-edit-footnote-reference~ (C-c ') on a footnote reference
+allows to edit its definition, as long as it is not anonymous, in a
+dedicated buffer.  It works even if buffer is currently narrowed.
+
+*** New function ~org-delete-indentation~ bound to ~M-^~
+
+Work as ~delete-indentation~ unless at heading, in which case text is
+added to headline text.
+
+*** Support for images in Texinfo export
+
+~Texinfo~ back-end now handles images.  See the manual for details.
+
+*** Support for captions in Texinfo export
+
+Tables and source blocks can now have captions.  Additionally, lists
+of tables and lists of listings can be inserted in the document with
+=#+TOC= keyword.
+
+*** Countdown timer support hh:mm:ss format
+
+In addition to setting countdown timers in minutes, they can also be
+set using the hh:mm:ss format.
+
+*** Extend ~org-clone-subtree-with-time-shift~
+
+~org-clone-subtree-with-time-shift~ now accepts 0 as an argument for the
+number of clones, which removes the repeater from the original subtree
+and creates one shifted, repeating clone.
+
+*** New time block for clock tables: ~untilnow~
+
+It encompasses all past closed clocks.
+
+*** Support for the ~polyglossia~ LaTeX package
+
+See the docstring of ~org-latex-classes~ and
+~org-latex-guess-polyglossia-language~ for details.
+
+*** None-floating tables, graphics and blocks can have captions
+
+*** `org-insert-heading' can be forced to insert top-level headline
+
+** Removed functions
+
+*** Removed function ~org-translate-time~
+
+Use ~org-timestamp-translate~ instead.
+
+*** Removed function ~org-beamer-insert-options-template~
+
+This function inserted a Beamer specific template at point or in
+current subtree.  Use ~org-export-insert-default-template~ instead, as
+it provides more features and covers all export back-ends.  It is also
+accessible from the export dispatcher.
+
+*** Removed function ~org-timer-cancel-timer~
+
+~org-timer-stop~ now stops both relative and countdown timers.
+
+*** Removed function ~org-export-solidify-link-text~
+
+This function, being non-bijective, introduced bug in internal
+references.  Use ~org-export-get-reference~ instead.
+
+*** Removed function ~org-end-of-meta-data-and-drawers~
+
+The function is superseded by ~org-end-of-meta-data~, called with an
+optional argument.
+
+*** Removed functions ~org-table-colgroup-line-p~, ~org-table-cookie-line-p~
+
+These functions were left-over from pre 8.0 era.  They are not correct
+anymore.  Since they are not needed, they have no replacement.
+
+** Removed options
+
+*** ~org-list-empty-line-terminates-plain-lists~ is deprecated
+
+It will be kept in code base until next release, for backward
+compatibility.
+
+If you need to separate consecutive lists with blank lines, always use
+two of them, as if this option was nil (default value).
+
+*** ~org-export-with-creator~ is a boolean
+
+Special ~comment~ value is no longer allowed.  It is possible to use a
+body filter to add comments about the creator at the end of the
+document instead.
+
+*** Removed option =org-html-use-unicode-chars=
+
+Setting this to non-nil was problematic as it converted characters
+everywhere in the buffer, possibly corrupting URLs.
+
+*** Removed option =org-babel-sh-command=
+
+This undocumented option defaulted to the value of =shell-file-name= at
+the time of loading =ob-shell=.  The new behaviour is to use the value
+of =shell-file-name= directly when the shell langage is =shell=.  To chose
+a different shell, either customize =shell-file-name= or bind this
+variable locally.
+
+*** Removed option =org-babel-sh-var-quote-fmt=
+
+This undocumented option was supposed to provide different quoting
+styles when changing the shell type.  Changing the shell type can now
+be done directly from the source block and the quoting style has to be
+compatible across all shells, so a customization doesn't make sense
+anymore.  The chosen hard coded quoting style conforms to POSIX.
+
+*** Removed option ~org-insert-labeled-timestamps-at-point~
+
+Setting this option to anything else that the default value (nil)
+would create invalid planning info.  This dangerous option is now
+removed.
+
+*** Removed option ~org-koma-letter-use-title~
+
+Use org-export-with-title instead.  See also below.
+
+*** Removed option ~org-entities-ascii-explanatory~
+
+This variable has no effect since Org 8.0.
+
+*** Removed option ~org-table-error-on-row-ref-crossing-hline~
+
+This variable has no effect since August 2009.
+
+*** Removed MathML-related options from ~org-html-mathjax-options~
+
+MathJax automatically chooses the best display technology based on the
+end-users browser.  You may force initial usage of MathML via
+~org-html-mathjax-template~ or by setting the ~path~ property of
+~org-html-mathjax-options~.
+
+*** Removed comment-related filters
+
+~org-export-filter-comment-functions~ and
+~org-export-filter-comment-block-functions~ variables do not exist
+anymore.
+
+** Miscellaneous
+
+*** Strip all meta data from ITEM special property
+
+ITEM special property does not contain TODO, priority or tags anymore.
+
+*** File names in links accept are now compatible with URI syntax
+
+Absolute file names can now start with =///= in addition to =/=. E.g.,
+=[[file:///home/me/unicorn.jpg]]=.
+
+*** Footnotes in included files are now local to the file
+
+As a consequence, it is possible to include multiple Org files with
+footnotes in a master document without being concerned about footnote
+labels colliding.
+
+*** Mailto links now use regular URI syntax
+
+This change deprecates old Org syntax for mailto links:
+=mailto:address@hidden::Subject=.
+
+*** =QUOTE= keywords do not exist anymore
+
+=QUOTE= keywords have been deprecated since Org 8.2.
+
+*** Select tests to perform with the build system
+
+The build system has been enhanced to allow test selection with a
+regular expression by defining =BTEST_RE= during the test invocation.
+This is especially useful during bisection to find just when a
+particular test failure was introduced.
+
+*** Exact heading search for external links ignore spaces and cookies
+
+Exact heading search for links now ignore spaces and cookies. This is
+the case for links of the form ~file:projects.org::*task title~, as well
+as links of the form ~file:projects.org::some words~ when
+~org-link-search-must-match-exact-headline~ is not nil.
+
+*** ~org-latex-hyperref-template~, ~org-latex-title-command~ formatting
+
+New formatting keys are supported.  See the respective docstrings.
+Note, ~org-latex-hyperref-template~ has a new default value.
+
+*** ~float, wasysym, marvosym~ are removed from 
~org-latex-default-packages-alist~
+
+If you require any of these package add them to your preamble via
+~org-latex-packages-alist~. Org also uses default LaTeX ~\tolerance~ now.
+
+*** When exporting, throw an error on unresolved id/fuzzy links and code refs
+
+This helps spotting wrong links.
+
+* Version 8.2
+
+** Incompatible changes
+*** =ob-sh.el= renamed to =ob-shell=
+This may require two changes in user config.
+
+1. In =org-babel-do-load-languages=, change =(sh . t)= to =(shell . t)=.
+2. Edit =local.mk= files to change the value of =BTEST_OB_LANGUAGES=
+   to remove "sh" and include "shell".
+
 *** Combine org-mac-message.el and org-mac-link-grabber into org-mac-link.el
 
 Please remove calls to =(require 'org-mac-message)= and =(require
@@ -171,6 +1522,18 @@ then inline code snippets will be wrapped into the 
formatting string.
 - =org-screenshot.el= by Max Mikhanosha :: an utility to handle
      screenshots easily from Org, using the external tool 
[[http://freecode.com/projects/scrot][scrot]].
 
+** Miscellaneous
+
+*** "QUOTE" keywords in headlines are deprecated
+
+"QUOTE" keywords are an undocumented feature in Org.  When a headline
+starts with the keyword "QUOTE", its contents are parsed as
+a ~quote-section~ and treated as an example block.  You can achieve
+the same with example blocks.
+
+This feature is deprecated and will be removed in the next Org
+release.
+
 * Version 8.0.1
 
 ** Installation
@@ -835,14 +2198,14 @@ See [[http://orgmode.org/org.html#Lookup-functions][the 
manual]] for details.
 
 These new startup keywords are now available:
 
-| Startup keyword                  | Option                                    
  |
-|----------------------------------+---------------------------------------------|
+| Startup keyword                | Option                                    |
+|--------------------------------+-------------------------------------------|
 | =#+STARTUP: logdrawer=           | =(setq org-log-into-drawer t)=            
  |
 | =#+STARTUP: nologdrawer=         | =(setq org-log-into-drawer nil)=          
  |
-|----------------------------------+---------------------------------------------|
+|--------------------------------+-------------------------------------------|
 | =#+STARTUP: logstatesreversed=   | =(setq org-log-states-order-reversed t)=  
  |
 | =#+STARTUP: nologstatesreversed= | =(setq org-log-states-order-reversed 
nil)=  |
-|----------------------------------+---------------------------------------------|
+|--------------------------------+-------------------------------------------|
 | =#+STARTUP: latexpreview=        | =(setq org-startup-with-latex-preview t)= 
  |
 | =#+STARTUP: nolatexpreview=      | =(setq org-startup-with-latex-preview 
nil)= |
 
@@ -952,7 +2315,7 @@ instead of requiring each Babel library one by one.
 - New option [[doc:org-gnus-no-server][org-gnus-no-server]] to start Gnus with 
=gnus-no-server=
 - Org is now distributed with =htmlize.el= version 1.43
 - ~org-drill.el~ has been updated to version 2.3.7
-- ~org-mac-iCal.el~ now supports OS X versions up to 10.8
+- ~org-mac-iCal.el~ now supports MacOSX version up to 10.8
 - Various improvements to ~org-contacts.el~ and =orgpan.el=
 
 ** Outside Org
@@ -1021,6 +2384,13 @@ consistent with using the `:' key in agenda view.
 You can now use `=' for [[doc::org-columns][org-columns]].
 
 ** =org-float= is now obsolete, use =diary-float= instead
+** No GPL manual anymore
+
+There used to be a GPL version of the Org manual, but this is not the
+case anymore, the Free Software Foundation does not permit this.
+
+The GNU FDL license is now included in the manual directly.
+
 ** Enhanced compatibility with Emacs 22 and XEmacs
 
 Thanks to Achim for his work on enhancing Org's compatibility with
@@ -1046,8 +2416,8 @@ See http://orgmode.org/elpa/
 
 ** Overview of the new keybindings
 
-   | Keybinding      | Speedy | Command                     |
-   |-----------------+--------+-----------------------------|
+   | Keybinding    | Speedy | Command                     |
+   |---------------+--------+-----------------------------|
    | =C-c C-x C-z=   |        | [[doc::org-clock-resolve][org-clock-resolve]]  
         |
    | =C-c C-x C-q=   |        | [[doc::org-clock-cancel][org-clock-cancel]]    
        |
    | =C-c C-x C-x=   |        | [[doc::org-clock-in-last][org-clock-in-last]]  
         |
@@ -1055,12 +2425,12 @@ See http://orgmode.org/elpa/
    | =*=             |        | 
[[doc::org-agenda-bulk-mark-all][org-agenda-bulk-mark-all]]    |
    | =C-c C-M-l=     |        | 
[[doc::org-insert-all-links][org-insert-all-links]]        |
    | =C-c C-x C-M-v= |        | 
[[doc::org-redisplay-inline-images][org-redisplay-inline-images]] |
-   | =C-c C-x E=     | =E=    | [[doc::org-inc-effort][org-inc-effort]]        
      |
-   |                 | =#=    | 
[[doc::org-toggle-comment][org-toggle-comment]]          |
-   |                 | =:=    | [[doc::org-columns][org-columns]]              
   |
-   |                 | =W=    | Set =APPT_WARNTIME=         |
+   | =C-c C-x E=     | =E=      | [[doc::org-inc-effort][org-inc-effort]]      
        |
+   |               | =#=      | 
[[doc::org-toggle-comment][org-toggle-comment]]          |
+   |               | =:=      | [[doc::org-columns][org-columns]]              
   |
+   |               | =W=      | Set =APPT_WARNTIME=           |
    | =k=             |        | 
[[doc::org-agenda-capture][org-agenda-capture]]          |
-   | C-c ,           | ,      | [[doc::org-priority][org-priority]]            
    |
+   | C-c ,         | ,      | [[doc::org-priority][org-priority]]              
  |
 
 ** New package and Babel language
 
@@ -1225,7 +2595,7 @@ See http://orgmode.org/elpa/
 
 **** New =todo-unblocked= and =nottodo-unblocked= skip conditions
 
-     See the 
[[http://orgmode.org/w/?p%3Dorg-mode.git%3Ba%3Dcommit%3Bh%3Df426da][git 
commit]] for more explanations.
+     See the [[http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=f426da][git 
commit]] for more explanations.
 
 **** Allow category filtering in the agenda
 
@@ -1542,7 +2912,7 @@ See http://orgmode.org/elpa/
      Thanks to Carsten for implementing this.
 
 **** ODT: Add support for ODT export in org-bbdb.el
-**** ODT: Add support for indented tables (see 
[[http://orgmode.org/w/?p%3Dorg-mode.git%3Ba%3Dcommit%3Bh%3De9fd33][this 
commit]] for details)
+**** ODT: Add support for indented tables (see 
[[http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=e9fd33][this commit]] for 
details)
 **** ODT: Improve the conversion from ODT to other formats
 **** ASCII: Swap the level-1/level-2 characters to underline the headlines
 **** Support for Chinese, simplified Chinese, Russian, Ukrainian and Japanese
diff --git a/etc/org/OrgOdtStyles.xml b/etc/org/OrgOdtStyles.xml
index f41d984..1a8edee 100644
--- a/etc/org/OrgOdtStyles.xml
+++ b/etc/org/OrgOdtStyles.xml
@@ -110,33 +110,53 @@
   <style:style style:name="Heading_20_1" style:display-name="Heading 1" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="1" 
style:class="text">
    <style:text-properties fo:font-size="115%" fo:font-weight="bold" 
style:font-size-asian="115%" style:font-weight-asian="bold" 
style:font-size-complex="115%" style:font-weight-complex="bold"/>
   </style:style>
+   <style:style style:name="Heading_20_1_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_1" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_2" style:display-name="Heading 2" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="2" 
style:class="text">
    <style:text-properties fo:font-size="14pt" fo:font-style="italic" 
fo:font-weight="bold" style:font-size-asian="14pt" 
style:font-style-asian="italic" style:font-weight-asian="bold" 
style:font-size-complex="14pt" style:font-style-complex="italic" 
style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_2_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_2" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_3" style:display-name="Heading 3" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="3" 
style:class="text">
    <style:text-properties fo:font-size="14pt" fo:font-weight="bold" 
style:font-size-asian="14pt" style:font-weight-asian="bold" 
style:font-size-complex="14pt" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_3_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_3" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_4" style:display-name="Heading 4" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="4" 
style:class="text">
    <style:text-properties fo:font-size="85%" fo:font-style="italic" 
fo:font-weight="bold" style:font-size-asian="85%" 
style:font-style-asian="italic" style:font-weight-asian="bold" 
style:font-size-complex="85%" style:font-style-complex="italic" 
style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_4_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_4" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_5" style:display-name="Heading 5" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="5" 
style:class="text">
    <style:text-properties fo:font-size="85%" fo:font-weight="bold" 
style:font-size-asian="85%" style:font-weight-asian="bold" 
style:font-size-complex="85%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_5_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_5" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_6" style:display-name="Heading 6" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="6" 
style:class="text">
    <style:text-properties fo:font-size="75%" fo:font-weight="bold" 
style:font-size-asian="75%" style:font-weight-asian="bold" 
style:font-size-complex="75%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_6_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_6" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_7" style:display-name="Heading 7" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="7" 
style:class="text">
    <style:text-properties fo:font-size="75%" fo:font-weight="bold" 
style:font-size-asian="75%" style:font-weight-asian="bold" 
style:font-size-complex="75%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_7_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_7" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_8" style:display-name="Heading 8" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="8" 
style:class="text">
    <style:text-properties fo:font-size="75%" fo:font-weight="bold" 
style:font-size-asian="75%" style:font-weight-asian="bold" 
style:font-size-complex="75%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_8_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_8" style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_9" style:display-name="Heading 9" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="9" 
style:class="text">
    <style:text-properties fo:font-size="75%" fo:font-weight="bold" 
style:font-size-asian="75%" style:font-weight-asian="bold" 
style:font-size-complex="75%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_9_unnumbered" style:family="paragraph" 
style:parent-style-name="Heading_20_9" style:list-style-name="">
+    </style:style>
   <style:style style:name="Heading_20_10" style:display-name="Heading 10" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="10" 
style:class="text">
    <style:text-properties fo:font-size="75%" fo:font-weight="bold" 
style:font-size-asian="75%" style:font-weight-asian="bold" 
style:font-size-complex="75%" style:font-weight-complex="bold"/>
   </style:style>
+    <style:style style:name="Heading_20_10_unnumbered" 
style:family="paragraph" style:parent-style-name="Heading_20_10" 
style:list-style-name="">
+  </style:style>
   <style:style style:name="Heading_20_1.title" style:display-name="Heading 
1.title" style:family="paragraph" style:parent-style-name="Heading_20_1">
    <style:paragraph-properties fo:text-align="center" 
style:justify-single-word="false"/>
   </style:style>
diff --git a/etc/org/README b/etc/org/README
index 68905ad..d04f434 100644
--- a/etc/org/README
+++ b/etc/org/README
@@ -1,7 +1,7 @@
 The files OrgOdtContentTemplate.xml and OrgOdtStyles.xml have the
 following copyright information:
 
-Copyright (C) 2010-2017 Free Software Foundation, Inc.
+Copyright (C) 2010-2014 Free Software Foundation, Inc.
 
 These files are part of GNU Emacs.
 
diff --git a/etc/org/library-of-babel.org b/etc/org/library-of-babel.org
new file mode 100644
index 0000000..0098e72
--- /dev/null
+++ b/etc/org/library-of-babel.org
@@ -0,0 +1,584 @@
+#+title:    The Library of Babel
+#+author:     Org-mode People
+#+STARTUP:  hideblocks
+
+* Introduction
+
+The Library of Babel is an extensible collection of ready-made and
+easily-shortcut-callable source-code blocks for handling common tasks.
+Org-babel comes pre-populated with the source-code blocks located in
+this file.  It is possible to add source-code blocks from any org-mode
+file to the library by calling =(org-babel-lob-ingest
+"path/to/file.org")=.
+
+This file is included in worg mainly less for viewing through the web
+interface, and more for contribution through the worg git repository.
+If you have code snippets that you think others may find useful please
+add them to this file and 
[[file:~/src/worg/worg-git.org::contribute-to-worg][contribute them]] to worg.
+
+The raw Org-mode text of this file can be downloaded at
+[[repofile:contrib/babel/library-of-babel.org][library-of-babel.org]]
+
+* Simple
+
+A collection of simple utility functions:
+
+#+name: echo
+#+begin_src emacs-lisp :var input="echo'd"
+  input
+#+end_src
+
+* File I/O
+
+** Reading and writing files
+
+Read the contents of the file at =file=.  The =:results vector= and
+=:results scalar= header arguments can be used to read the contents of
+file as either a table or a string.
+
+#+name: read
+#+begin_src emacs-lisp :var file="" :var format=""
+  (if (string= format "csv")
+      (with-temp-buffer
+        (org-table-import (expand-file-name file) nil)
+        (org-table-to-lisp))
+    (with-temp-buffer
+      (insert-file-contents (expand-file-name file))
+      (buffer-string)))
+#+end_src
+
+Write =data= to a file at =file=.  If =data= is a list, then write it
+as a table in traditional Org-mode table syntax.
+
+#+name: write
+#+begin_src emacs-lisp :var data="" :var file="" :var ext='()
+  (flet ((echo (r) (if (stringp r) r (format "%S" r))))
+    (with-temp-file file
+      (case (and (listp data)
+                 (or ext (intern (file-name-extension file))))
+        ('tsv (insert (orgtbl-to-tsv data '(:fmt echo))))
+        ('csv (insert (orgtbl-to-csv data '(:fmt echo))))
+        (t    (org-babel-insert-result data)))))
+  nil
+#+end_src
+
+** Remote files
+
+*** json
+
+Read local or remote file in [[http://www.json.org/][json]] format into 
emacs-lisp objects.
+
+#+name: json
+#+begin_src emacs-lisp :var file='() :var url='()
+  (require 'json)
+  (cond
+   (file
+    (with-temp-filebuffer file
+      (goto-char (point-min))
+      (json-read)))
+   (url
+    (require 'w3m)
+    (with-temp-buffer
+      (w3m-retrieve url)
+      (goto-char (point-min))
+      (json-read))))
+#+end_src
+
+*** Google docs
+
+The following code blocks make use of the 
[[http://code.google.com/p/googlecl/][googlecl]] Google command line
+tool.  This tool provides functionality for accessing Google services
+from the command line, and the following code blocks use /googlecl/
+for reading from and writing to Google docs with Org-mode code blocks.
+
+**** Read a document from Google docs
+
+The =google= command seems to be throwing "Moved Temporarily" errors
+when trying to download textual documents, but this is working fine
+for spreadsheets.
+
+#+name: gdoc-read
+#+begin_src emacs-lisp :var title="example" :var format="csv"
+  (let* ((file (concat title "." format))
+         (cmd (format "google docs get --format %S --title %S" format title)))
+    (message cmd) (message (shell-command-to-string cmd))
+    (prog1 (if (string= format "csv")
+               (with-temp-buffer
+                 (org-table-import (shell-quote-argument file) '(4))
+                 (org-table-to-lisp))
+             (with-temp-buffer
+               (insert-file-contents (shell-quote-argument file))
+               (buffer-string)))
+      (delete-file file)))
+#+end_src
+
+For example, a line like the following can be used to read the
+contents of a spreadsheet named =num-cells= into a table.
+: #+call: gdoc-read(title="num-cells"")
+
+A line like the following can be used to read the contents of a
+document as a string.
+
+: #+call: gdoc-read(title="loremi", :format "txt")
+
+**** Write a document to a Google docs
+
+Write =data= to a google document named =title=.  If =data= is tabular
+it will be saved to a spreadsheet, otherwise it will be saved as a
+normal document.
+
+#+name: gdoc-write
+#+begin_src emacs-lisp :var title="babel-upload" :var data=fibs(n=10) :results 
silent
+  (let* ((format (if (listp data) "csv" "txt"))
+         (tmp-file (make-temp-file "org-babel-google-doc" nil (concat "." 
format)))
+         (cmd (format "google docs upload --title %S %S" title tmp-file)))
+    (with-temp-file tmp-file
+      (insert
+       (if (listp data)
+           (orgtbl-to-csv
+            data '(:fmt (lambda (el) (if (stringp el) el (format "%S" el)))))
+         (if (stringp data) data (format "%S" data)))))
+    (message cmd)
+    (prog1 (shell-command-to-string cmd) (delete-file tmp-file)))
+#+end_src
+
+example usage
+: #+name: fibs
+: #+begin_src emacs-lisp :var n=8
+:   (flet ((fib (m) (if (< m 2) 1 (+ (fib (- m 1)) (fib (- m 2))))))
+:     (mapcar (lambda (el) (list el (fib el))) (number-sequence 0 (- n 1))))
+: #+end_src
+:
+: #+call: gdoc-write(title="fibs", data=fibs(n=10))
+
+* Plotting code
+
+** R
+
+Plot column 2 (y axis) against column 1 (x axis). Columns 3 and
+beyond, if present, are ignored.
+
+#+name: R-plot
+#+begin_src R :var data=R-plot-example-data
+plot(data)
+#+end_src
+
+#+tblname: R-plot-example-data
+| 1 |  2 |
+| 2 |  4 |
+| 3 |  9 |
+| 4 | 16 |
+| 5 | 25 |
+
+#+call: R-plot(data=R-plot-example-data)
+
+#+resname: R-plot(data=R-plot-example-data)
+: nil
+
+** Gnuplot
+
+* Org reference
+
+** Headline references
+
+#+name: headline
+#+begin_src emacs-lisp :var headline=top :var file='()
+  (save-excursion
+    (when file (get-file-buffer file))
+    (org-open-link-from-string (org-make-link-string headline))
+    (save-restriction
+      (org-narrow-to-subtree)
+      (buffer-string)))
+#+end_src
+
+#+call: headline(headline="headline references")
+
+* Tables
+
+** LaTeX Table Export
+
+*** booktabs
+
+This source block can be used to wrap a table in the latex =booktabs=
+environment. The source block adds a =toprule= and =bottomrule= (so
+don't use =hline= at the top or bottom of the table).  The =hline=
+after the header is replaced with a =midrule=.
+
+Note that this function bypasses the Org-mode LaTeX exporter and calls
+=orgtbl-to-generic= to create the output table.  This means that the
+entries in the table are not translated from Org-mode to LaTeX.
+
+It takes the following arguments -- all but the first two are
+optional.
+
+| arg   | description                                |
+|-------+--------------------------------------------|
+| table | a reference to the table                   |
+| align | alignment string                           |
+| env   | optional environment, default to "tabular" |
+| width | optional width specification string        |
+
+#+name: booktabs
+#+begin_src emacs-lisp :var table='((:head) hline (:body)) :var align='() :var 
env="tabular" :var width='() :noweb yes :results latex
+  (flet ((to-tab (tab)
+                 (orgtbl-to-generic
+                  (mapcar (lambda (lis)
+                            (if (listp lis)
+                                (mapcar (lambda (el)
+                                          (if (stringp el)
+                                              el
+                                            (format "%S" el))) lis)
+                              lis)) tab)
+                  (list :lend " \\\\" :sep " & " :hline "\\hline"))))
+    (org-fill-template
+     "
+  \\begin{%env}%width%align
+  \\toprule
+  %table
+  \\bottomrule
+  \\end{%env}\n"
+     (list
+      (cons "env"       (or env "table"))
+      (cons "width"     (if width (format "{%s}" width) ""))
+      (cons "align"     (if align (format "{%s}" align) ""))
+      (cons "table"
+            ;; only use \midrule if it looks like there are column headers
+            (if (equal 'hline (second table))
+                (concat (to-tab (list (first table)))
+                        "\n\\midrule\n"
+                        (to-tab (cddr table)))
+              (to-tab table))))))
+#+end_src
+
+*** longtable
+
+This block can be used to wrap a table in the latex =longtable=
+environment, it takes the following arguments -- all but the first two
+are optional.
+
+| arg       | description                                                 |
+|-----------+-------------------------------------------------------------|
+| table     | a reference to the table                                    |
+| align     | optional alignment string                                   |
+| width     | optional width specification string                         |
+| hline     | the string to use as hline separator, defaults to "\\hline" |
+| head      | optional "head" string                                      |
+| firsthead | optional "firsthead" string                                 |
+| foot      | optional "foot" string                                      |
+| lastfoot  | optional "lastfoot" string                                  |
+
+#+name: longtable
+#+begin_src emacs-lisp :var table='((:table)) :var align='() :var width='() 
:var hline="\\hline" :var firsthead='() :var head='() :var foot='() :var 
lastfoot='() :noweb yes :results latex
+  (org-fill-template
+   "
+  \\begin{longtable}%width%align
+  %firsthead
+  %head
+  %foot
+  %lastfoot
+
+  %table
+  \\end{longtable}\n"
+   (list
+    (cons "width"     (if width (format "{%s}" width) ""))
+    (cons "align"     (if align (format "{%s}" align) ""))
+    (cons "firsthead" (if firsthead (concat firsthead "\n\\endfirsthead\n") 
""))
+    (cons "head"      (if head (concat head "\n\\endhead\n") ""))
+    (cons "foot"      (if foot (concat foot "\n\\endfoot\n") ""))
+    (cons "lastfoot"  (if lastfoot (concat lastfoot "\n\\endlastfoot\n") ""))
+    (cons "table" (orgtbl-to-generic
+                   (mapcar (lambda (lis)
+                             (if (listp lis)
+                                 (mapcar (lambda (el)
+                                           (if (stringp el)
+                                               el
+                                             (format "%S" el))) lis)
+                               lis)) table)
+                   (list :lend " \\\\" :sep " & " :hline hline)))))
+#+end_src
+
+*** booktabs-notes
+
+This source block builds on [[booktabs]].  It accepts two additional
+arguments, both of which are optional.
+
+#+tblname: arguments
+| arg    | description                                          |
+|--------+------------------------------------------------------|
+| notes  | an org-mode table with footnotes                     |
+| lspace | if non-nil, insert =addlinespace= after =bottomrule= |
+
+An example footnote to the =arguments= table specifies the column
+span. Note the use of LaTeX, rather than Org-mode, markup.
+
+#+tblname: arguments-notes
+| \multicolumn{2}{l}{This is a footnote to the \emph{arguments} table.} |
+
+#+name: booktabs-notes
+#+begin_src emacs-lisp :var table='((:head) hline (:body)) :var notes='() :var 
align='() :var env="tabular" :var width='() :var lspace='() :noweb yes :results 
latex
+  (flet ((to-tab (tab)
+                 (orgtbl-to-generic
+                  (mapcar (lambda (lis)
+                            (if (listp lis)
+                                (mapcar (lambda (el)
+                                          (if (stringp el)
+                                              el
+                                            (format "%S" el))) lis)
+                              lis)) tab)
+                  (list :lend " \\\\" :sep " & " :hline "\\hline"))))
+    (org-fill-template
+     "
+    \\begin{%env}%width%align
+    \\toprule
+    %table
+    \\bottomrule%spacer
+    %notes
+    \\end{%env}\n"
+     (list
+      (cons "env"       (or env "table"))
+      (cons "width"     (if width (format "{%s}" width) ""))
+      (cons "align"     (if align (format "{%s}" align) ""))
+      (cons "spacer"    (if lspace "\\addlinespace" ""))
+      (cons "table"
+            ;; only use \midrule if it looks like there are column headers
+            (if (equal 'hline (second table))
+                (concat (to-tab (list (first table)))
+                        "\n\\midrule\n"
+                        (to-tab (cddr table)))
+              (to-tab table)))
+      (cons "notes" (if notes (to-tab notes) ""))
+      )))
+#+end_src
+
+** Elegant lisp for transposing a matrix
+
+#+tblname: transpose-example
+| 1 | 2 | 3 |
+| 4 | 5 | 6 |
+
+#+name: transpose
+#+begin_src emacs-lisp :var table=transpose-example
+  (apply #'mapcar* #'list table)
+#+end_src
+
+#+resname:
+| 1 | 4 |
+| 2 | 5 |
+| 3 | 6 |
+
+** Convert every element of a table to a string
+
+#+tblname: hetero-table
+| 1 | 2 | 3 |
+| a | b | c |
+
+#+name: all-to-string
+#+begin_src emacs-lisp :var tbl='()
+  (defun all-to-string (tbl)
+    (if (listp tbl)
+        (mapcar #'all-to-string tbl)
+      (if (stringp tbl)
+          tbl
+        (format "%s" tbl))))
+  (all-to-string tbl)
+#+end_src
+
+#+begin_src emacs-lisp :var tbl=hetero-table
+  (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
+#+end_src
+
+#+name:
+| nil | nil | nil |
+| t   | t   | t   |
+
+#+begin_src emacs-lisp :var tbl=all-to-string(hetero-table)
+  (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
+#+end_src
+
+#+name:
+| t | t | t |
+| t | t | t |
+
+* Misc
+
+** File-specific Version Control logging
+   :PROPERTIES:
+   :AUTHOR: Luke Crook
+   :END:
+
+This function will attempt to retrieve the entire commit log for the
+file associated with the current buffer and insert this log into the
+export. The function uses the Emacs VC commands to interface to the
+local version control system, but has only been tested to work with
+Git. 'limit' is currently unsupported.
+
+#+name: vc-log
+#+headers: :var limit=-1
+#+headers: :var buf=(buffer-name (current-buffer))
+#+begin_src emacs-lisp
+  ;; Most of this code is copied from vc.el vc-print-log
+  (require 'vc)
+  (when (vc-find-backend-function
+         (vc-backend (buffer-file-name (get-buffer buf))) 'print-log)
+    (let ((limit -1)
+          (vc-fileset nil)
+          (backend nil)
+          (files nil))
+      (with-current-buffer (get-buffer buf)
+        (setq vc-fileset (vc-deduce-fileset t)) ; FIXME: Why t? --Stef
+        (setq backend (car vc-fileset))
+        (setq files (cadr vc-fileset)))
+      (with-temp-buffer
+        (let ((status (vc-call-backend
+                       backend 'print-log files (current-buffer))))
+          (when (and (processp status)   ; Make sure status is a process
+                     (= 0 (process-exit-status status))) ; which has not 
terminated
+            (while (not (eq 'exit (process-status status)))
+              (sit-for 1 t)))
+          (buffer-string)))))
+#+end_src
+
+** Trivial python code blocks
+
+#+name: python-identity
+#+begin_src python :var a=1
+a
+#+end_src
+
+#+name: python-add
+#+begin_src python :var a=1 :var b=2
+a + b
+#+end_src
+
+** Arithmetic
+
+#+name: lob-add
+#+begin_src emacs-lisp :var a=0 :var b=0
+  (+ a b)
+#+end_src
+
+#+name: lob-minus
+#+begin_src emacs-lisp :var a=0 :var b=0
+  (- a b)
+#+end_src
+
+#+name: lob-times
+#+begin_src emacs-lisp :var a=0 :var b=0
+  (* a b)
+#+end_src
+
+#+name: lob-div
+#+begin_src emacs-lisp :var a=0 :var b=0
+  (/ a b)
+#+end_src
+
+* GANTT Charts
+
+The =elispgantt= source block was sent to the mailing list by Eric
+Fraga.  It was modified slightly by Tom Dye.
+
+#+name: elispgantt
+#+begin_src emacs-lisp :var table=gantttest
+  (let ((dates "")
+        (entries (nthcdr 2 table))
+        (milestones "")
+        (nmilestones 0)
+        (ntasks 0)
+        (projecttime 0)
+        (tasks "")
+        (xlength 1))
+    (message "Initial: %s\n" table)
+    (message "Entries: %s\n" entries)
+    (while entries
+      (let ((entry (first entries)))
+        (if (listp entry)
+            (let ((id (first entry))
+                  (type (nth 1 entry))
+                  (label (nth 2 entry))
+                  (task (nth 3 entry))
+                  (dependencies (nth 4 entry))
+                  (start (nth 5 entry))
+                  (duration (nth 6 entry))
+                  (end (nth 7 entry))
+                  (alignment (nth 8 entry)))
+              (if (> start projecttime) (setq projecttime start))
+              (if (string= type "task")
+                  (let ((end (+ start duration))
+                        (textposition (+ start (/ duration 2)))
+                        (flush ""))
+                    (if (string= alignment "left")
+                        (progn
+                          (setq textposition start)
+                          (setq flush "[left]"))
+                      (if (string= alignment "right")
+                          (progn
+                            (setq textposition end)
+                            (setq flush "[right]"))))
+                    (setq tasks
+                          (format "%s  \\gantttask{%s}{%s}{%d}{%d}{%d}{%s}\n"
+                                  tasks label task start end textposition 
flush))
+                    (setq ntasks (+ 1 ntasks))
+                    (if (> end projecttime)
+                        (setq projecttime end)))
+                (if (string= type "milestone")
+                    (progn
+                      (setq milestones
+                            (format
+                             "%s  
\\ganttmilestone{$\\begin{array}{c}\\mbox{%s}\\\\ 
\\mbox{%s}\\end{array}$}{%d}\n"
+                             milestones label task start))
+                      (setq nmilestones (+ 1 nmilestones)))
+                  (if (string= type "date")
+                      (setq dates (format "%s  \\ganttdateline{%s}{%d}\n"
+                                          dates label start))
+                    (message "Ignoring entry with type %s\n" type)))))
+          (message "Ignoring non-list entry %s\n" entry)) ; end if list entry
+        (setq entries (cdr entries))))  ; end while entries left
+    (format "\\pgfdeclarelayer{background}
+  \\pgfdeclarelayer{foreground}
+  \\pgfsetlayers{background,foreground}
+  \\renewcommand{\\ganttprojecttime}{%d}
+  \\renewcommand{\\ganttntasks}{%d}
+  \\noindent
+  \\begin{tikzpicture}[y=-0.75cm,x=0.75\\textwidth]
+    \\begin{pgfonlayer}{background}
+      \\draw[very thin, red!10!white] (0,1+\\ganttntasks) grid 
[ystep=0.75cm,xstep=1/\\ganttprojecttime] (1,0);
+      \\draw[\\ganttdatelinecolour] (0,0) -- (1,0);
+      \\draw[\\ganttdatelinecolour] (0,1+\\ganttntasks) -- (1,1+\\ganttntasks);
+    \\end{pgfonlayer}
+  %s
+  %s
+  %s
+  \\end{tikzpicture}" projecttime ntasks tasks milestones dates))
+#+end_src
+
+* Available languages
+  :PROPERTIES:
+  :AUTHOR:   Bastien
+  :END:
+
+** From Org's core
+
+| Language   | Identifier | Language       | Identifier |
+|------------+------------+----------------+------------|
+| Asymptote  | asymptote  | Awk            | awk        |
+| Emacs Calc | calc       | C              | C          |
+| C++        | C++        | Clojure        | clojure    |
+| CSS        | css        | ditaa          | ditaa      |
+| Graphviz   | dot        | Emacs Lisp     | emacs-lisp |
+| gnuplot    | gnuplot    | Haskell        | haskell    |
+| Javascript | js         | LaTeX          | latex      |
+| Ledger     | ledger     | Lisp           | lisp       |
+| Lilypond   | lilypond   | MATLAB         | matlab     |
+| Mscgen     | mscgen     | Objective Caml | ocaml      |
+| Octave     | octave     | Org-mode       | org        |
+|            |            | Perl           | perl       |
+| Plantuml   | plantuml   | Python         | python     |
+| R          | R          | Ruby           | ruby       |
+| Sass       | sass       | Scheme         | scheme     |
+| GNU Screen | screen     | shell          | sh         |
+| SQL        | sql        | SQLite         | sqlite     |
+
+** From Org's contrib/babel/langs
+
+- ob-oz.el, by Torsten Anders and Eric Schulte
+- ob-fomus.el, by Torsten Anders
diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex
index b12ae7b..9ab6b4a 100644
--- a/etc/refcards/orgcard.tex
+++ b/etc/refcards/orgcard.tex
@@ -1,7 +1,7 @@
 % Reference Card for Org Mode
-\def\orgversionnumber{8.2}
-\def\versionyear{2014}          % latest update
-\input emacsver.tex
+\def\orgversionnumber{9.0.9}
+\def\versionyear{2017}          % latest update
+\def\year{2017}                 % latest copyright year
 
 %**start of header
 \newcount\columnsperpage
@@ -80,9 +80,6 @@
 \centerline{Released under the terms of the GNU General Public License}
 \centerline{version 3 or later.}
 
-\centerline{For more Emacs documentation, and the \TeX{} source for this card, 
see}
-\centerline{the Emacs distribution, or {\tt http://www.gnu.org/software/emacs}}
-
 \endgroup}
 
 % make \bye not \outer so that the \def\bye in the \else clause below
@@ -312,10 +309,11 @@
 \key{turn item/line into headline}{C-c *}
 \key{promote/demote heading}{M-LEFT/RIGHT}
 \metax{promote/demote current subtree}{M-S-LEFT/RIGHT}
-\metax{move subtree/list item up/down}{M-S-UP/DOWN}
+\metax{move subtree/list item up/down}{M-UP/DOWN}
+\metax{move the line at point up/down}{M-S-UP/DOWN}
 \metax{sort subtree/region/plain-list}{C-c \^{}}
 \metax{clone a subtree}{C-c C-x c}
-\metax{copy visible text}{C-c C-x v}
+\metax{copy visible parts of the region}{C-c C-x v}
 \metax{kill/copy subtree}{C-c C-x C-w/M-w}
 \metax{yank subtree}{C-c C-x C-y or C-y}
 \metax{narrow buffer to subtree / widen}{C-x n s/w}
@@ -333,7 +331,6 @@
 \key{construct a sparse tree by various criteria}{C-c /}
 \key{view TODO's in sparse tree}{C-c / t/T}
 \key{global TODO list in agenda mode}{C-c a t \noteone}
-\key{time sorted view of current org file}{C-c a L}
 
 \section{Tables}
 
@@ -375,7 +372,6 @@ Outside of tables, the same keys may have other 
functionality.
 \metax{cut/copy/paste rectangular region}{C-c C-x C-w/M-w/C-y}
 %\key{copy rectangular region}{C-c C-x M-w}
 %\key{paste rectangular region}{C-c C-x C-y}
-\key{fill paragraph across selected cells}{C-c C-q}
 
 {\bf Miscellaneous}
 
@@ -574,7 +570,6 @@ after  ``{\tt :}'', and dictionary words elsewhere.
 \key{match tags, TODO kwds, properties}{C-c a m \noteone}
 \key{match only in TODO entries}{C-c a M \noteone}
 \key{find stuck projects}{C-c a \# \noteone}
-\key{show timeline of current org file}{C-c a L \noteone}
 \key{configure custom commands}{C-c a C \noteone}
 %\key{configure stuck projects}{C-c a ! \noteone}
 \key{agenda for date at cursor}{C-c C-o}
@@ -661,8 +656,11 @@ some other place.
 
 \key{export/publish dispatcher}{C-c C-e}
 
-\key{export visible part only}{C-c C-e v}
-\key{insert template of export options}{C-c C-e t}
+\key{toggle asynchronous export}{C-c C-e C-a}
+\key{toggle body/visible only export}{C-c C-e C-b/v}
+\key{toggle subtree export}{C-c C-e C-s}
+\key{insert template of export options}{C-c C-e \#}
+
 \key{toggle fixed width for entry or region}{C-c :}
 \key{toggle pretty display of scripts, entities}{C-c C-x {\tt\char`\\}}
 
@@ -690,6 +688,5 @@ your own key as shown under ACTIVATION.
 \bye
 
 % Local variables:
-% compile-command: "tex refcard"
+% compile-command: "pdftex orgcard"
 % End:
-
diff --git a/etc/schema/od-manifest-schema-v1.2-os.rnc 
b/etc/schema/od-manifest-schema-v1.2-os.rnc
new file mode 100644
index 0000000..87f84d1
--- /dev/null
+++ b/etc/schema/od-manifest-schema-v1.2-os.rnc
@@ -0,0 +1,88 @@
+# Open Document Format for Office Applications (OpenDocument) Version 1.2
+# OASIS Standard, 29 September 2011
+# Manifest Relax-NG Schema
+# Source: http://docs.oasis-open.org/office/v1.2/os/
+# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved.
+#
+# All capitalized terms in the following text have the meanings assigned to 
them
+# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
+# full Policy may be found at the OASIS website.
+#
+# This document and translations of it may be copied and furnished to others, 
and
+# derivative works that comment on or otherwise explain it or assist in its
+# implementation may be prepared, copied, published, and distributed, in whole 
or
+# in part, without restriction of any kind, provided that the above copyright
+# notice and this section are included on all such copies and derivative works.
+# However, this document itself may not be modified in any way, including by
+# removing the copyright notice or references to OASIS, except as needed for 
the
+# purpose of developing any document or deliverable produced by an OASIS
+# Technical Committee (in which case the rules applicable to copyrights, as set
+# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
+# into languages other than English.
+#
+# The limited permissions granted above are perpetual and will not be revoked 
by
+# OASIS or its successors or assigns.
+#
+# This document and the information contained herein is provided on an "AS IS"
+# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
+# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
+# FITNESS FOR A PARTICULAR PURPOSE.
+
+namespace manifest =
+  "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
+
+start = manifest
+manifest = element manifest:manifest { manifest-attlist, file-entry+ }
+manifest-attlist = attribute manifest:version { "1.2" }
+file-entry =
+  element manifest:file-entry { file-entry-attlist, encryption-data? }
+file-entry-attlist =
+  attribute manifest:full-path { \string }
+  & attribute manifest:size { nonNegativeInteger }?
+  & attribute manifest:media-type { \string }
+  & attribute manifest:preferred-view-mode {
+      "edit" | "presentation-slide-show" | "read-only" | namespacedToken
+    }?
+  & attribute manifest:version { \string }?
+encryption-data =
+  element manifest:encryption-data {
+    encryption-data-attlist,
+    algorithm,
+    start-key-generation?,
+    key-derivation
+  }
+encryption-data-attlist =
+  attribute manifest:checksum-type { "SHA1/1K" | anyURI }
+  & attribute manifest:checksum { base64Binary }
+algorithm =
+  element manifest:algorithm { algorithm-attlist, anyElements }
+algorithm-attlist =
+  attribute manifest:algorithm-name { "Blowfish CFB" | anyURI }
+  & attribute manifest:initialisation-vector { base64Binary }
+anyAttListOrElements =
+  attribute * { text }*,
+  anyElements
+anyElements =
+  element * {
+    mixed { anyAttListOrElements }
+  }*
+key-derivation =
+  element manifest:key-derivation { key-derivation-attlist, empty }
+key-derivation-attlist =
+  attribute manifest:key-derivation-name { "PBKDF2" | anyURI }
+  & attribute manifest:salt { base64Binary }
+  & attribute manifest:iteration-count { nonNegativeInteger }
+  & attribute manifest:key-size { nonNegativeInteger }?
+start-key-generation =
+  element manifest:start-key-generation {
+    start-key-generation-attlist, empty
+  }
+start-key-generation-attlist =
+  attribute manifest:start-key-generation-name { "SHA1" | anyURI }
+  & attribute manifest:key-size { nonNegativeInteger }?
+base64Binary = xsd:base64Binary
+namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
+nonNegativeInteger = xsd:nonNegativeInteger
+\string = xsd:string
+anyURI = xsd:anyURI
diff --git a/etc/schema/od-schema-v1.2-os.rnc b/etc/schema/od-schema-v1.2-os.rnc
new file mode 100644
index 0000000..8d679d6
--- /dev/null
+++ b/etc/schema/od-schema-v1.2-os.rnc
@@ -0,0 +1,6280 @@
+# Open Document Format for Office Applications (OpenDocument) Version 1.2
+# OASIS Standard, 29 September 2011
+# Relax-NG Schema
+# Source: http://docs.oasis-open.org/office/v1.2/os/
+# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved.
+#
+# All capitalized terms in the following text have the meanings assigned to 
them
+# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
+# full Policy may be found at the OASIS website.
+#
+# This document and translations of it may be copied and furnished to others, 
and
+# derivative works that comment on or otherwise explain it or assist in its
+# implementation may be prepared, copied, published, and distributed, in whole 
or
+# in part, without restriction of any kind, provided that the above copyright
+# notice and this section are included on all such copies and derivative works.
+# However, this document itself may not be modified in any way, including by
+# removing the copyright notice or references to OASIS, except as needed for 
the
+# purpose of developing any document or deliverable produced by an OASIS
+# Technical Committee (in which case the rules applicable to copyrights, as set
+# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
+# into languages other than English.
+#
+# The limited permissions granted above are perpetual and will not be revoked 
by
+# OASIS or its successors or assigns.
+#
+# This document and the information contained herein is provided on an "AS IS"
+# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
+# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
+# FITNESS FOR A PARTICULAR PURPOSE.
+
+namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
+namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+namespace config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+namespace db = "urn:oasis:names:tc:opendocument:xmlns:database:1.0"
+namespace dc = "http://purl.org/dc/elements/1.1/";
+namespace dr3d = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+namespace draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+namespace fo =
+  "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+namespace form = "urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+namespace grddl = "http://www.w3.org/2003/g/data-view#";
+namespace math = "http://www.w3.org/1998/Math/MathML";
+namespace meta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+namespace number = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+namespace presentation =
+  "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+namespace smil =
+  "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
+namespace style = "urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+namespace svg =
+  "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+namespace table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+namespace text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+namespace xforms = "http://www.w3.org/2002/xforms";
+namespace xhtml = "http://www.w3.org/1999/xhtml";
+namespace xlink = "http://www.w3.org/1999/xlink";
+
+office-process-content = attribute office:process-content { boolean }?
+start =
+  office-document
+  | office-document-content
+  | office-document-styles
+  | office-document-meta
+  | office-document-settings
+office-document =
+  element office:document {
+    office-document-attrs,
+    office-document-common-attrs,
+    office-meta,
+    office-settings,
+    office-scripts,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles,
+    office-body
+  }
+office-document-content =
+  element office:document-content {
+    office-document-common-attrs,
+    office-scripts,
+    office-font-face-decls,
+    office-automatic-styles,
+    office-body
+  }
+office-document-styles =
+  element office:document-styles {
+    office-document-common-attrs,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles
+  }
+office-document-meta =
+  element office:document-meta {
+    office-document-common-attrs, office-meta
+  }
+office-document-settings =
+  element office:document-settings {
+    office-document-common-attrs, office-settings
+  }
+office-document-common-attrs =
+  attribute office:version { "1.2" }
+  & attribute grddl:transformation {
+      list { anyIRI* }
+    }?
+office-document-attrs = attribute office:mimetype { \string }
+office-meta = element office:meta { office-meta-content-strict }?
+office-meta-content-strict = office-meta-data*
+office-body = element office:body { office-body-content }
+office-body-content =
+  element office:text {
+    office-text-attlist,
+    office-text-content-prelude,
+    office-text-content-main,
+    office-text-content-epilogue
+  }
+  | element office:drawing {
+      office-drawing-attlist,
+      office-drawing-content-prelude,
+      office-drawing-content-main,
+      office-drawing-content-epilogue
+    }
+  | element office:presentation {
+      office-presentation-attlist,
+      office-presentation-content-prelude,
+      office-presentation-content-main,
+      office-presentation-content-epilogue
+    }
+  | element office:spreadsheet {
+      office-spreadsheet-attlist,
+      office-spreadsheet-content-prelude,
+      office-spreadsheet-content-main,
+      office-spreadsheet-content-epilogue
+    }
+  | element office:chart {
+      office-chart-attlist,
+      office-chart-content-prelude,
+      office-chart-content-main,
+      office-chart-content-epilogue
+    }
+  | element office:image {
+      office-image-attlist,
+      office-image-content-prelude,
+      office-image-content-main,
+      office-image-content-epilogue
+    }
+  | office-database
+office-text-content-prelude =
+  office-forms, text-tracked-changes, text-decls, table-decls
+office-text-content-main =
+  text-content*
+  | (text-page-sequence, (shape)*)
+text-content =
+  text-h
+  | text-p
+  | text-list
+  | text-numbered-paragraph
+  | table-table
+  | text-section
+  | text-soft-page-break
+  | text-table-of-content
+  | text-illustration-index
+  | text-table-index
+  | text-object-index
+  | text-user-index
+  | text-alphabetical-index
+  | text-bibliography
+  | shape
+  | change-marks
+office-text-content-epilogue = table-functions
+office-text-attlist =
+  attribute text:global { boolean }?
+  & attribute text:use-soft-page-breaks { boolean }?
+office-drawing-attlist = empty
+office-drawing-content-prelude = text-decls, table-decls
+office-drawing-content-main = draw-page*
+office-drawing-content-epilogue = table-functions
+office-presentation-attlist = empty
+office-presentation-content-prelude =
+  text-decls, table-decls, presentation-decls
+office-presentation-content-main = draw-page*
+office-presentation-content-epilogue =
+  presentation-settings, table-functions
+office-spreadsheet-content-prelude =
+  table-tracked-changes?, text-decls, table-decls
+table-decls =
+  table-calculation-settings?,
+  table-content-validations?,
+  table-label-ranges?
+office-spreadsheet-content-main = table-table*
+office-spreadsheet-content-epilogue = table-functions
+table-functions =
+  table-named-expressions?,
+  table-database-ranges?,
+  table-data-pilot-tables?,
+  table-consolidation?,
+  table-dde-links?
+office-chart-attlist = empty
+office-chart-content-prelude = text-decls, table-decls
+office-chart-content-main = chart-chart
+office-chart-content-epilogue = table-functions
+office-image-attlist = empty
+office-image-content-prelude = empty
+office-image-content-main = draw-frame
+office-image-content-epilogue = empty
+office-settings = element office:settings { config-config-item-set+ }?
+config-config-item-set =
+  element config:config-item-set {
+    config-config-item-set-attlist, config-items
+  }
+config-items =
+  (config-config-item
+   | config-config-item-set
+   | config-config-item-map-named
+   | config-config-item-map-indexed)+
+config-config-item-set-attlist = attribute config:name { \string }
+config-config-item =
+  element config:config-item { config-config-item-attlist, text }
+config-config-item-attlist =
+  attribute config:name { \string }
+  & attribute config:type {
+      "boolean"
+      | "short"
+      | "int"
+      | "long"
+      | "double"
+      | "string"
+      | "datetime"
+      | "base64Binary"
+    }
+config-config-item-map-indexed =
+  element config:config-item-map-indexed {
+    config-config-item-map-indexed-attlist,
+    config-config-item-map-entry+
+  }
+config-config-item-map-indexed-attlist =
+  attribute config:name { \string }
+config-config-item-map-entry =
+  element config:config-item-map-entry {
+    config-config-item-map-entry-attlist, config-items
+  }
+config-config-item-map-entry-attlist =
+  attribute config:name { \string }?
+config-config-item-map-named =
+  element config:config-item-map-named {
+    config-config-item-map-named-attlist, config-config-item-map-entry+
+  }
+config-config-item-map-named-attlist = attribute config:name { \string }
+office-scripts =
+  element office:scripts { office-script*, office-event-listeners? }?
+office-script =
+  element office:script {
+    office-script-attlist,
+    mixed { anyElements }
+  }
+office-script-attlist = attribute script:language { \string }
+office-font-face-decls =
+  element office:font-face-decls { style-font-face* }?
+office-styles =
+  element office:styles {
+    styles
+    & style-default-style*
+    & style-default-page-layout?
+    & text-outline-style?
+    & text-notes-configuration*
+    & text-bibliography-configuration?
+    & text-linenumbering-configuration?
+    & draw-gradient*
+    & svg-linearGradient*
+    & svg-radialGradient*
+    & draw-hatch*
+    & draw-fill-image*
+    & draw-marker*
+    & draw-stroke-dash*
+    & draw-opacity*
+    & style-presentation-page-layout*
+    & table-table-template*
+  }?
+office-automatic-styles =
+  element office:automatic-styles { styles & style-page-layout* }?
+office-master-styles =
+  element office:master-styles {
+    style-master-page* & style-handout-master? & draw-layer-set?
+  }?
+styles =
+  style-style*
+  & text-list-style*
+  & number-number-style*
+  & number-currency-style*
+  & number-percentage-style*
+  & number-date-style*
+  & number-time-style*
+  & number-boolean-style*
+  & number-text-style*
+office-meta-data =
+  element meta:generator { \string }
+  | element dc:title { \string }
+  | element dc:description { \string }
+  | element dc:subject { \string }
+  | element meta:keyword { \string }
+  | element meta:initial-creator { \string }
+  | dc-creator
+  | element meta:printed-by { \string }
+  | element meta:creation-date { dateTime }
+  | dc-date
+  | element meta:print-date { dateTime }
+  | element meta:template {
+      attribute xlink:type { "simple" },
+      attribute xlink:href { anyIRI },
+      attribute xlink:actuate { "onRequest" }?,
+      attribute xlink:title { \string }?,
+      attribute meta:date { dateTime }?
+    }
+  | element meta:auto-reload {
+      (attribute xlink:type { "simple" },
+       attribute xlink:href { anyIRI },
+       attribute xlink:show { "replace" }?,
+       attribute xlink:actuate { "onLoad" }?)?,
+      attribute meta:delay { duration }?
+    }
+  | element meta:hyperlink-behaviour {
+      attribute office:target-frame-name { targetFrameName }?,
+      attribute xlink:show { "new" | "replace" }?
+    }
+  | element dc:language { language }
+  | element meta:editing-cycles { nonNegativeInteger }
+  | element meta:editing-duration { duration }
+  | element meta:document-statistic {
+      attribute meta:page-count { nonNegativeInteger }?,
+      attribute meta:table-count { nonNegativeInteger }?,
+      attribute meta:draw-count { nonNegativeInteger }?,
+      attribute meta:image-count { nonNegativeInteger }?,
+      attribute meta:ole-object-count { nonNegativeInteger }?,
+      attribute meta:object-count { nonNegativeInteger }?,
+      attribute meta:paragraph-count { nonNegativeInteger }?,
+      attribute meta:word-count { nonNegativeInteger }?,
+      attribute meta:character-count { nonNegativeInteger }?,
+      attribute meta:frame-count { nonNegativeInteger }?,
+      attribute meta:sentence-count { nonNegativeInteger }?,
+      attribute meta:syllable-count { nonNegativeInteger }?,
+      attribute meta:non-whitespace-character-count {
+        nonNegativeInteger
+      }?,
+      attribute meta:row-count { nonNegativeInteger }?,
+      attribute meta:cell-count { nonNegativeInteger }?
+    }
+  | element meta:user-defined {
+      attribute meta:name { \string },
+      ((attribute meta:value-type { "float" },
+        double)
+       | (attribute meta:value-type { "date" },
+          dateOrDateTime)
+       | (attribute meta:value-type { "time" },
+          duration)
+       | (attribute meta:value-type { "boolean" },
+          boolean)
+       | (attribute meta:value-type { "string" },
+          \string)
+       | text)
+    }
+dc-creator = element dc:creator { \string }
+dc-date = element dc:date { dateTime }
+text-h =
+  element text:h {
+    heading-attrs,
+    paragraph-attrs,
+    text-number?,
+    paragraph-content-or-hyperlink*
+  }
+heading-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:restart-numbering { boolean }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & attribute text:is-list-header { boolean }?
+text-number = element text:number { \string }
+text-p =
+  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+paragraph-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:class-names { styleNameRefs }?
+  & attribute text:cond-style-name { styleNameRef }?
+  & (xml-id,
+     attribute text:id { NCName }?)?
+  & common-in-content-meta-attlist?
+text-page-sequence = element text:page-sequence { text-page+ }
+text-page = element text:page { text-page-attlist, empty }
+text-page-attlist = attribute text:master-page-name { styleNameRef }
+text-list =
+  element text:list {
+    text-list-attr, text-list-header?, text-list-item*
+  }
+text-list-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:continue-numbering { boolean }?
+  & attribute text:continue-list { IDREF }?
+  & xml-id?
+text-list-item =
+  element text:list-item { text-list-item-attr, text-list-item-content }
+text-list-item-content =
+  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
+text-list-item-attr =
+  attribute text:start-value { nonNegativeInteger }?
+  & attribute text:style-override { styleNameRef }?
+  & xml-id?
+text-list-header =
+  element text:list-header {
+    text-list-header-attr, text-list-item-content
+  }
+text-list-header-attr = xml-id?
+text-numbered-paragraph =
+  element text:numbered-paragraph {
+    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+  }
+text-numbered-paragraph-attr =
+  attribute text:list-id { NCName }
+  & attribute text:level { positiveInteger }?
+  & (attribute text:style-name { styleNameRef },
+     attribute text:continue-numbering { boolean },
+     attribute text:start-value { nonNegativeInteger })?
+  & xml-id?
+text-section =
+  element text:section {
+    text-section-attlist,
+    (text-section-source | text-section-source-dde | empty),
+    text-content*
+  }
+text-section-attlist =
+  common-section-attlist
+  & (attribute text:display { "true" | "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { \string })
+     | empty)
+common-section-attlist =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:name { \string }
+  & attribute text:protected { boolean }?
+  & attribute text:protection-key { \string }?
+  & attribute text:protection-key-digest-algorithm { anyIRI }?
+  & xml-id?
+text-section-source =
+  element text:section-source { text-section-source-attr }
+text-section-source-attr =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "embed" }?)?
+  & attribute text:section-name { \string }?
+  & attribute text:filter-name { \string }?
+text-section-source-dde = office-dde-source
+text-tracked-changes =
+  element text:tracked-changes {
+    text-tracked-changes-attr, text-changed-region*
+  }?
+text-tracked-changes-attr = attribute text:track-changes { boolean }?
+text-changed-region =
+  element text:changed-region {
+    text-changed-region-attr, text-changed-region-content
+  }
+text-changed-region-attr =
+  xml-id,
+  attribute text:id { NCName }?
+text-changed-region-content =
+  element text:insertion { office-change-info }
+  | element text:deletion { office-change-info, text-content* }
+  | element text:format-change { office-change-info }
+change-marks =
+  element text:change { change-mark-attr }
+  | element text:change-start { change-mark-attr }
+  | element text:change-end { change-mark-attr }
+change-mark-attr = attribute text:change-id { IDREF }
+text-soft-page-break = element text:soft-page-break { empty }
+text-decls =
+  element text:variable-decls { text-variable-decl* }?,
+  element text:sequence-decls { text-sequence-decl* }?,
+  element text:user-field-decls { text-user-field-decl* }?,
+  element text:dde-connection-decls { text-dde-connection-decl* }?,
+  text-alphabetical-index-auto-mark-file?
+paragraph-content-or-hyperlink = paragraph-content | text-a
+paragraph-content =
+  text
+  | element text:s {
+      attribute text:c { nonNegativeInteger }?
+    }
+  | element text:tab { text-tab-attr }
+  | element text:line-break { empty }
+  | text-soft-page-break
+  | element text:span {
+      attribute text:style-name { styleNameRef }?,
+      attribute text:class-names { styleNameRefs }?,
+      paragraph-content-or-hyperlink*
+    }
+  | element text:meta {
+      text-meta-attlist, paragraph-content-or-hyperlink*
+    }
+  | (text-bookmark | text-bookmark-start | text-bookmark-end)
+  | element text:reference-mark {
+      attribute text:name { \string }
+    }
+  | (element text:reference-mark-start {
+       attribute text:name { \string }
+     }
+     | element text:reference-mark-end {
+         attribute text:name { \string }
+       })
+  | element text:note {
+      text-note-class,
+      attribute text:id { \string }?,
+      element text:note-citation {
+        attribute text:label { \string }?,
+        text
+      },
+      element text:note-body { text-content* }
+    }
+  | element text:ruby {
+      attribute text:style-name { styleNameRef }?,
+      element text:ruby-base { paragraph-content-or-hyperlink* },
+      element text:ruby-text {
+        attribute text:style-name { styleNameRef }?,
+        text
+      }
+    }
+  | (office-annotation | office-annotation-end)
+  | change-marks
+  | shape
+  | element text:date { text-date-attlist, text }
+  | element text:time { text-time-attlist, text }
+  | element text:page-number { text-page-number-attlist, text }
+  | element text:page-continuation {
+      text-page-continuation-attlist, text
+    }
+  | element text:sender-firstname { common-field-fixed-attlist, text }
+  | element text:sender-lastname { common-field-fixed-attlist, text }
+  | element text:sender-initials { common-field-fixed-attlist, text }
+  | element text:sender-title { common-field-fixed-attlist, text }
+  | element text:sender-position { common-field-fixed-attlist, text }
+  | element text:sender-email { common-field-fixed-attlist, text }
+  | element text:sender-phone-private {
+      common-field-fixed-attlist, text
+    }
+  | element text:sender-fax { common-field-fixed-attlist, text }
+  | element text:sender-company { common-field-fixed-attlist, text }
+  | element text:sender-phone-work { common-field-fixed-attlist, text }
+  | element text:sender-street { common-field-fixed-attlist, text }
+  | element text:sender-city { common-field-fixed-attlist, text }
+  | element text:sender-postal-code { common-field-fixed-attlist, text }
+  | element text:sender-country { common-field-fixed-attlist, text }
+  | element text:sender-state-or-province {
+      common-field-fixed-attlist, text
+    }
+  | element text:author-name { common-field-fixed-attlist, text }
+  | element text:author-initials { common-field-fixed-attlist, text }
+  | element text:chapter { text-chapter-attlist, text }
+  | element text:file-name { text-file-name-attlist, text }
+  | element text:template-name { text-template-name-attlist, text }
+  | element text:sheet-name { text }
+  | element text:variable-set {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-value-and-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-value-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:sequence {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-field-num-format-attlist
+       & text-sequence-ref-name),
+      text
+    }
+  | element text:expression {
+      (common-field-formula-attlist
+       & common-value-and-type-attlist?
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:text-input { common-field-description-attlist, text }
+  | element text:initial-creator { common-field-fixed-attlist, text }
+  | element text:creation-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { dateOrDateTime }?),
+      text
+    }
+  | element text:creation-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { timeOrDateTime }?),
+      text
+    }
+  | element text:description { common-field-fixed-attlist, text }
+  | element text:user-defined {
+      (common-field-fixed-attlist
+       & attribute text:name { \string }
+       & common-field-data-style-name-attlist
+       & attribute office:value { double }?
+       & attribute office:date-value { dateOrDateTime }?
+       & attribute office:time-value { duration }?
+       & attribute office:boolean-value { boolean }?
+       & attribute office:string-value { \string }?),
+      text
+    }
+  | element text:print-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:print-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:printed-by { common-field-fixed-attlist, text }
+  | element text:title { common-field-fixed-attlist, text }
+  | element text:subject { common-field-fixed-attlist, text }
+  | element text:keywords { common-field-fixed-attlist, text }
+  | element text:editing-cycles { common-field-fixed-attlist, text }
+  | element text:editing-duration {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:duration { duration }?),
+      text
+    }
+  | element text:modification-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:modification-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:creator { common-field-fixed-attlist, text }
+  | element text:page-count
+            | text:paragraph-count
+            | text:word-count
+            | text:character-count
+            | text:table-count
+            | text:image-count
+            | text:object-count {
+      common-field-num-format-attlist, text
+    }
+  | element text:database-display {
+      text-database-display-attlist, text
+    }
+  | element text:database-next { text-database-next-attlist }
+  | element text:database-row-select {
+      text-database-row-select-attlist
+    }
+  | element text:database-row-number {
+      (common-field-database-table
+       & common-field-num-format-attlist
+       & attribute text:value { nonNegativeInteger }?),
+      text
+    }
+  | element text:database-name { common-field-database-table, text }
+  | element text:page-variable-set {
+      text-set-page-variable-attlist, text
+    }
+  | element text:page-variable-get {
+      text-get-page-variable-attlist, text
+    }
+  | element text:placeholder { text-placeholder-attlist, text }
+  | element text:conditional-text {
+      text-conditional-text-attlist, text
+    }
+  | element text:hidden-text { text-hidden-text-attlist, text }
+  | element text:reference-ref | text:bookmark-ref {
+      text-common-ref-content & text-bookmark-ref-content
+    }
+  | element text:note-ref {
+      text-common-ref-content & text-note-ref-content
+    }
+  | element text:sequence-ref {
+      text-common-ref-content & text-sequence-ref-content
+    }
+  | element text:script {
+      ((attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI })
+       | text)
+      & attribute script:language { \string }?
+    }
+  | element text:execute-macro {
+      attribute text:name { \string }?,
+      office-event-listeners?,
+      text
+    }
+  | element text:hidden-paragraph {
+      text-hidden-paragraph-attlist, text
+    }
+  | element text:dde-connection {
+      attribute text:connection-name { \string },
+      text
+    }
+  | element text:measure {
+      attribute text:kind { "value" | "unit" | "gap" },
+      text
+    }
+  | element text:table-formula {
+      (common-field-formula-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:meta-field {
+      text-meta-field-attlist, paragraph-content-or-hyperlink*
+    }
+  | element text:toc-mark-start { text-toc-mark-start-attrs }
+  | element text:toc-mark-end { text-id }
+  | element text:toc-mark {
+      attribute text:string-value { \string },
+      text-outline-level
+    }
+  | element text:user-index-mark-start {
+      text-id, text-outline-level, text-index-name
+    }
+  | element text:user-index-mark-end { text-id }
+  | element text:user-index-mark {
+      attribute text:string-value { \string },
+      text-outline-level,
+      text-index-name
+    }
+  | element text:alphabetical-index-mark-start {
+      text-id, text-alphabetical-index-mark-attrs
+    }
+  | element text:alphabetical-index-mark-end { text-id }
+  | element text:alphabetical-index-mark {
+      attribute text:string-value { \string },
+      text-alphabetical-index-mark-attrs
+    }
+  | element text:bibliography-mark {
+      attribute text:bibliography-type { text-bibliography-types },
+      attribute text:identifier
+                | text:address
+                | text:annote
+                | text:author
+                | text:booktitle
+                | text:chapter
+                | text:edition
+                | text:editor
+                | text:howpublished
+                | text:institution
+                | text:journal
+                | text:month
+                | text:note
+                | text:number
+                | text:organizations
+                | text:pages
+                | text:publisher
+                | text:school
+                | text:series
+                | text:title
+                | text:report-type
+                | text:volume
+                | text:year
+                | text:url
+                | text:custom1
+                | text:custom2
+                | text:custom3
+                | text:custom4
+                | text:custom5
+                | text:isbn
+                | text:issn { \string }*,
+      text
+    }
+  | element presentation:header { empty }
+  | element presentation:footer { empty }
+  | element presentation:date-time { empty }
+text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
+text-a =
+  element text:a {
+    text-a-attlist, office-event-listeners?, paragraph-content*
+  }
+text-a-attlist =
+  attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:visited-style-name { styleNameRef }?
+text-meta-attlist = common-in-content-meta-attlist? & xml-id?
+text-bookmark = element text:bookmark { text-bookmark-attlist, empty }
+text-bookmark-start =
+  element text:bookmark-start { text-bookmark-start-attlist, empty }
+text-bookmark-end =
+  element text:bookmark-end { text-bookmark-end-attlist, empty }
+text-bookmark-attlist =
+  attribute text:name { \string }
+  & xml-id?
+text-bookmark-start-attlist =
+  attribute text:name { \string }
+  & xml-id?
+  & common-in-content-meta-attlist?
+text-bookmark-end-attlist = attribute text:name { \string }
+text-note-class = attribute text:note-class { "footnote" | "endnote" }
+text-date-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:date-value { dateOrDateTime }?
+  & attribute text:date-adjust { duration }?
+text-time-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:time-value { timeOrDateTime }?
+  & attribute text:time-adjust { duration }?
+text-page-number-attlist =
+  (common-field-num-format-attlist & common-field-fixed-attlist)
+  & attribute text:page-adjust { integer }?
+  & attribute text:select-page { "previous" | "current" | "next" }?
+text-page-continuation-attlist =
+  attribute text:select-page { "previous" | "next" }
+  & attribute text:string-value { \string }?
+text-chapter-attlist =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number-and-name"
+    | "plain-number"
+  }
+  & attribute text:outline-level { nonNegativeInteger }
+text-file-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension"
+  }?
+  & common-field-fixed-attlist
+text-template-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  }?
+text-variable-decl =
+  element text:variable-decl {
+    common-field-name-attlist, common-value-type-attlist
+  }
+text-user-field-decl =
+  element text:user-field-decl {
+    common-field-name-attlist,
+    common-field-formula-attlist?,
+    common-value-and-type-attlist
+  }
+text-sequence-decl =
+  element text:sequence-decl { text-sequence-decl-attlist }
+text-sequence-decl-attlist =
+  common-field-name-attlist
+  & attribute text:display-outline-level { nonNegativeInteger }
+  & attribute text:separation-character { character }?
+text-sequence-ref-name = attribute text:ref-name { \string }?
+common-field-database-table =
+  common-field-database-table-attlist, common-field-database-name
+common-field-database-name =
+  attribute text:database-name { \string }?
+  | form-connection-resource
+common-field-database-table-attlist =
+  attribute text:table-name { \string }
+  & attribute text:table-type { "table" | "query" | "command" }?
+text-database-display-attlist =
+  common-field-database-table
+  & common-field-data-style-name-attlist
+  & attribute text:column-name { \string }
+text-database-next-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+text-database-row-select-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+  & attribute text:row-number { nonNegativeInteger }?
+text-set-page-variable-attlist =
+  attribute text:active { boolean }?
+  & attribute text:page-adjust { integer }?
+text-get-page-variable-attlist = common-field-num-format-attlist
+text-placeholder-attlist =
+  attribute text:placeholder-type {
+    "text" | "table" | "text-box" | "image" | "object"
+  }
+  & common-field-description-attlist
+text-conditional-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value-if-true { \string }
+  & attribute text:string-value-if-false { \string }
+  & attribute text:current-value { boolean }?
+text-hidden-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value { \string }
+  & attribute text:is-hidden { boolean }?
+text-common-ref-content =
+  text
+  & attribute text:ref-name { \string }?
+text-bookmark-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "number-no-superior"
+    | "number-all-superior"
+    | "number"
+  }?
+text-note-ref-content =
+  attribute text:reference-format { common-ref-format-values }?
+  & text-note-class
+text-sequence-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "category-and-value"
+    | "caption"
+    | "value"
+  }?
+common-ref-format-values = "page" | "chapter" | "direction" | "text"
+text-hidden-paragraph-attlist =
+  attribute text:condition { \string }
+  & attribute text:is-hidden { boolean }?
+text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
+common-value-type-attlist = attribute office:value-type { valueType }
+common-value-and-type-attlist =
+  (attribute office:value-type { "float" },
+   attribute office:value { double })
+  | (attribute office:value-type { "percentage" },
+     attribute office:value { double })
+  | (attribute office:value-type { "currency" },
+     attribute office:value { double },
+     attribute office:currency { \string }?)
+  | (attribute office:value-type { "date" },
+     attribute office:date-value { dateOrDateTime })
+  | (attribute office:value-type { "time" },
+     attribute office:time-value { duration })
+  | (attribute office:value-type { "boolean" },
+     attribute office:boolean-value { boolean })
+  | (attribute office:value-type { "string" },
+     attribute office:string-value { \string }?)
+common-field-fixed-attlist = attribute text:fixed { boolean }?
+common-field-name-attlist = attribute text:name { variableName }
+common-field-description-attlist =
+  attribute text:description { \string }?
+common-field-display-value-none-attlist =
+  attribute text:display { "value" | "none" }?
+common-field-display-value-formula-none-attlist =
+  attribute text:display { "value" | "formula" | "none" }?
+common-field-display-value-formula-attlist =
+  attribute text:display { "value" | "formula" }?
+common-field-formula-attlist = attribute text:formula { \string }?
+common-field-data-style-name-attlist =
+  attribute style:data-style-name { styleNameRef }?
+common-field-num-format-attlist = common-num-format-attlist?
+text-toc-mark-start-attrs = text-id, text-outline-level
+text-outline-level = attribute text:outline-level { positiveInteger }?
+text-id = attribute text:id { \string }
+text-index-name = attribute text:index-name { \string }
+text-alphabetical-index-mark-attrs =
+  attribute text:key1 { \string }?
+  & attribute text:key2 { \string }?
+  & attribute text:string-value-phonetic { \string }?
+  & attribute text:key1-phonetic { \string }?
+  & attribute text:key2-phonetic { \string }?
+  & attribute text:main-entry { boolean }?
+text-bibliography-types =
+  "article"
+  | "book"
+  | "booklet"
+  | "conference"
+  | "custom1"
+  | "custom2"
+  | "custom3"
+  | "custom4"
+  | "custom5"
+  | "email"
+  | "inbook"
+  | "incollection"
+  | "inproceedings"
+  | "journal"
+  | "manual"
+  | "mastersthesis"
+  | "misc"
+  | "phdthesis"
+  | "proceedings"
+  | "techreport"
+  | "unpublished"
+  | "www"
+text-index-body = element text:index-body { index-content-main* }
+index-content-main = text-content | text-index-title
+text-index-title =
+  element text:index-title {
+    common-section-attlist, index-content-main*
+  }
+text-table-of-content =
+  element text:table-of-content {
+    common-section-attlist,
+    text-table-of-content-source,
+    text-index-body
+  }
+text-table-of-content-source =
+  element text:table-of-content-source {
+    text-table-of-content-source-attlist,
+    text-index-title-template?,
+    text-table-of-content-entry-template*,
+    text-index-source-styles*
+  }
+text-table-of-content-source-attlist =
+  attribute text:outline-level { positiveInteger }?
+  & attribute text:use-outline-level { boolean }?
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:index-scope { "document" | "chapter" }?
+  & attribute text:relative-tab-stop-position { boolean }?
+text-table-of-content-entry-template =
+  element text:table-of-content-entry-template {
+    text-table-of-content-entry-template-attlist,
+    text-table-of-content-children*
+  }
+text-table-of-content-children =
+  text-index-entry-chapter
+  | text-index-entry-page-number
+  | text-index-entry-text
+  | text-index-entry-span
+  | text-index-entry-tab-stop
+  | text-index-entry-link-start
+  | text-index-entry-link-end
+text-table-of-content-entry-template-attlist =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-illustration-index =
+  element text:illustration-index {
+    common-section-attlist,
+    text-illustration-index-source,
+    text-index-body
+  }
+text-illustration-index-source =
+  element text:illustration-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-illustration-index-entry-template?
+  }
+text-illustration-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-caption { boolean }?
+  & attribute text:caption-sequence-name { \string }?
+  & attribute text:caption-sequence-format {
+      "text" | "category-and-value" | "caption"
+    }?
+text-index-scope-attr =
+  attribute text:index-scope { "document" | "chapter" }?
+text-relative-tab-stop-position-attr =
+  attribute text:relative-tab-stop-position { boolean }?
+text-illustration-index-entry-template =
+  element text:illustration-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-illustration-index-entry-content =
+  text-illustration-index-entry-template-attrs,
+  (text-index-entry-chapter
+   | text-index-entry-page-number
+   | text-index-entry-text
+   | text-index-entry-span
+   | text-index-entry-tab-stop)*
+text-illustration-index-entry-template-attrs =
+  attribute text:style-name { styleNameRef }
+text-table-index =
+  element text:table-index {
+    common-section-attlist, text-table-index-source, text-index-body
+  }
+text-table-index-source =
+  element text:table-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-table-index-entry-template?
+  }
+text-table-index-entry-template =
+  element text:table-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-object-index =
+  element text:object-index {
+    common-section-attlist, text-object-index-source, text-index-body
+  }
+text-object-index-source =
+  element text:object-index-source {
+    text-object-index-source-attrs,
+    text-index-title-template?,
+    text-object-index-entry-template?
+  }
+text-object-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-spreadsheet-objects { boolean }?
+  & attribute text:use-math-objects { boolean }?
+  & attribute text:use-draw-objects { boolean }?
+  & attribute text:use-chart-objects { boolean }?
+  & attribute text:use-other-objects { boolean }?
+text-object-index-entry-template =
+  element text:object-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-user-index =
+  element text:user-index {
+    common-section-attlist, text-user-index-source, text-index-body
+  }
+text-user-index-source =
+  element text:user-index-source {
+    text-user-index-source-attr,
+    text-index-title-template?,
+    text-user-index-entry-template*,
+    text-index-source-styles*
+  }
+text-user-index-source-attr =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:use-graphics { boolean }?
+  & attribute text:use-tables { boolean }?
+  & attribute text:use-floating-frames { boolean }?
+  & attribute text:use-objects { boolean }?
+  & attribute text:copy-outline-levels { boolean }?
+  & attribute text:index-name { \string }
+text-user-index-entry-template =
+  element text:user-index-entry-template {
+    text-user-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop)*
+  }
+text-user-index-entry-template-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-alphabetical-index =
+  element text:alphabetical-index {
+    common-section-attlist,
+    text-alphabetical-index-source,
+    text-index-body
+  }
+text-alphabetical-index-source =
+  element text:alphabetical-index-source {
+    text-alphabetical-index-source-attrs,
+    text-index-title-template?,
+    text-alphabetical-index-entry-template*
+  }
+text-alphabetical-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:ignore-case { boolean }?
+  & attribute text:main-entry-style-name { styleNameRef }?
+  & attribute text:alphabetical-separators { boolean }?
+  & attribute text:combine-entries { boolean }?
+  & attribute text:combine-entries-with-dash { boolean }?
+  & attribute text:combine-entries-with-pp { boolean }?
+  & attribute text:use-keys-as-entries { boolean }?
+  & attribute text:capitalize-entries { boolean }?
+  & attribute text:comma-separated { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-alphabetical-index-auto-mark-file =
+  element text:alphabetical-index-auto-mark-file {
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI }
+  }
+text-alphabetical-index-entry-template =
+  element text:alphabetical-index-entry-template {
+    text-alphabetical-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop)*
+  }
+text-alphabetical-index-entry-template-attrs =
+  attribute text:outline-level { "1" | "2" | "3" | "separator" }
+  & attribute text:style-name { styleNameRef }
+text-bibliography =
+  element text:bibliography {
+    common-section-attlist, text-bibliography-source, text-index-body
+  }
+text-bibliography-source =
+  element text:bibliography-source {
+    text-index-title-template?, text-bibliography-entry-template*
+  }
+text-bibliography-entry-template =
+  element text:bibliography-entry-template {
+    text-bibliography-entry-template-attrs,
+    (text-index-entry-span
+     | text-index-entry-tab-stop
+     | text-index-entry-bibliography)*
+  }
+text-bibliography-entry-template-attrs =
+  attribute text:bibliography-type { text-bibliography-types }
+  & attribute text:style-name { styleNameRef }
+text-index-source-styles =
+  element text:index-source-styles {
+    attribute text:outline-level { positiveInteger },
+    text-index-source-style*
+  }
+text-index-source-style =
+  element text:index-source-style {
+    attribute text:style-name { styleName },
+    empty
+  }
+text-index-title-template =
+  element text:index-title-template {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-index-entry-chapter =
+  element text:index-entry-chapter {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-chapter-attrs
+  }
+text-index-entry-chapter-attrs =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number"
+    | "plain-number-and-name"
+  }?
+  & attribute text:outline-level { positiveInteger }?
+text-index-entry-text =
+  element text:index-entry-text {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-entry-page-number =
+  element text:index-entry-page-number {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-entry-span =
+  element text:index-entry-span {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-index-entry-bibliography =
+  element text:index-entry-bibliography {
+    text-index-entry-bibliography-attrs
+  }
+text-index-entry-bibliography-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bibliography-data-field {
+      "address"
+      | "annote"
+      | "author"
+      | "bibliography-type"
+      | "booktitle"
+      | "chapter"
+      | "custom1"
+      | "custom2"
+      | "custom3"
+      | "custom4"
+      | "custom5"
+      | "edition"
+      | "editor"
+      | "howpublished"
+      | "identifier"
+      | "institution"
+      | "isbn"
+      | "issn"
+      | "journal"
+      | "month"
+      | "note"
+      | "number"
+      | "organizations"
+      | "pages"
+      | "publisher"
+      | "report-type"
+      | "school"
+      | "series"
+      | "title"
+      | "url"
+      | "volume"
+      | "year"
+    }
+text-index-entry-tab-stop =
+  element text:index-entry-tab-stop {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-tab-stop-attrs
+  }
+text-index-entry-tab-stop-attrs =
+  attribute style:leader-char { character }?
+  & (attribute style:type { "right" }
+     | (attribute style:type { "left" },
+        attribute style:position { length }))
+text-index-entry-link-start =
+  element text:index-entry-link-start {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-entry-link-end =
+  element text:index-entry-link-end {
+    attribute text:style-name { styleNameRef }?
+  }
+table-table =
+  element table:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    table-columns-and-groups,
+    table-rows-and-groups,
+    table-named-expressions?
+  }
+table-columns-and-groups =
+  (table-table-column-group | table-columns-no-group)+
+table-columns-no-group =
+  (table-columns, (table-table-header-columns, table-columns?)?)
+  | (table-table-header-columns, table-columns?)
+table-columns = table-table-columns | table-table-column+
+table-rows-and-groups = (table-table-row-group | table-rows-no-group)+
+table-rows-no-group =
+  (table-rows, (table-table-header-rows, table-rows?)?)
+  | (table-table-header-rows, table-rows?)
+table-rows =
+  table-table-rows | (text-soft-page-break?, table-table-row)+
+table-table-attlist =
+  attribute table:name { \string }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:template-name { \string }?
+  & attribute table:use-first-row-styles { boolean }?
+  & attribute table:use-last-row-styles { boolean }?
+  & attribute table:use-first-column-styles { boolean }?
+  & attribute table:use-last-column-styles { boolean }?
+  & attribute table:use-banding-rows-styles { boolean }?
+  & attribute table:use-banding-columns-styles { boolean }?
+  & attribute table:protected { boolean }?
+  & attribute table:protection-key { \string }?
+  & attribute table:protection-key-digest-algorithm { anyIRI }?
+  & attribute table:print { boolean }?
+  & attribute table:print-ranges { cellRangeAddressList }?
+  & xml-id?
+  & attribute table:is-sub-table { boolean }?
+table-title = element table:title { text }
+table-desc = element table:desc { text }
+table-table-row =
+  element table:table-row {
+    table-table-row-attlist,
+    (table-table-cell | table-covered-table-cell)+
+  }
+table-table-row-attlist =
+  attribute table:number-rows-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & xml-id?
+table-visibility-value = "visible" | "collapse" | "filter"
+table-table-cell =
+  element table:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+table-covered-table-cell =
+  element table:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+table-table-cell-content =
+  table-cell-range-source?,
+  office-annotation?,
+  table-detective?,
+  text-content*
+table-table-cell-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:content-validation-name { \string }?
+  & attribute table:formula { \string }?
+  & common-value-and-type-attlist?
+  & attribute table:protect { boolean }?
+  & attribute table:protected { boolean }?
+  & xml-id?
+  & common-in-content-meta-attlist?
+table-table-cell-attlist-extra =
+  attribute table:number-columns-spanned { positiveInteger }?
+  & attribute table:number-rows-spanned { positiveInteger }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+table-table-column =
+  element table:table-column { table-table-column-attlist, empty }
+table-table-column-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & xml-id?
+table-table-header-columns =
+  element table:table-header-columns { table-table-column+ }
+table-table-columns =
+  element table:table-columns { table-table-column+ }
+table-table-column-group =
+  element table:table-column-group {
+    table-table-column-group-attlist, table-columns-and-groups
+  }
+table-table-column-group-attlist = attribute table:display { boolean }?
+table-table-header-rows =
+  element table:table-header-rows {
+    (text-soft-page-break?, table-table-row)+
+  }
+table-table-rows =
+  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
+table-table-row-group =
+  element table:table-row-group {
+    table-table-row-group-attlist, table-rows-and-groups
+  }
+table-table-row-group-attlist = attribute table:display { boolean }?
+cellAddress =
+  xsd:string {
+    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
+  }
+cellRangeAddress =
+  xsd:string {
+    pattern =
+      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
+  }
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[0-9]+"
+    }
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+"
+    }
+cellRangeAddressList =
+  xsd:string
+  >> dc:description [
+       'Value is a space separated list of "cellRangeAddress" patterns'
+     ]
+table-table-source =
+  element table:table-source {
+    table-table-source-attlist, table-linked-source-attlist, empty
+  }
+table-table-source-attlist =
+  attribute table:mode { "copy-all" | "copy-results-only" }?
+  & attribute table:table-name { \string }?
+table-linked-source-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute table:filter-name { \string }?
+  & attribute table:filter-options { \string }?
+  & attribute table:refresh-delay { duration }?
+table-scenario =
+  element table:scenario { table-scenario-attlist, empty }
+table-scenario-attlist =
+  attribute table:scenario-ranges { cellRangeAddressList }
+  & attribute table:is-active { boolean }
+  & attribute table:display-border { boolean }?
+  & attribute table:border-color { color }?
+  & attribute table:copy-back { boolean }?
+  & attribute table:copy-styles { boolean }?
+  & attribute table:copy-formulas { boolean }?
+  & attribute table:comment { \string }?
+  & attribute table:protected { boolean }?
+table-shapes = element table:shapes { shape+ }
+table-cell-range-source =
+  element table:cell-range-source {
+    table-table-cell-range-source-attlist,
+    table-linked-source-attlist,
+    empty
+  }
+table-table-cell-range-source-attlist =
+  attribute table:name { \string }
+  & attribute table:last-column-spanned { positiveInteger }
+  & attribute table:last-row-spanned { positiveInteger }
+table-detective =
+  element table:detective { table-highlighted-range*, table-operation* }
+table-operation =
+  element table:operation { table-operation-attlist, empty }
+table-operation-attlist =
+  attribute table:name {
+    "trace-dependents"
+    | "remove-dependents"
+    | "trace-precedents"
+    | "remove-precedents"
+    | "trace-errors"
+  }
+  & attribute table:index { nonNegativeInteger }
+table-highlighted-range =
+  element table:highlighted-range {
+    (table-highlighted-range-attlist
+     | table-highlighted-range-attlist-invalid),
+    empty
+  }
+table-highlighted-range-attlist =
+  attribute table:cell-range-address { cellRangeAddress }?
+  & attribute table:direction {
+      "from-another-table" | "to-another-table" | "from-same-table"
+    }
+  & attribute table:contains-error { boolean }?
+table-highlighted-range-attlist-invalid =
+  attribute table:marked-invalid { boolean }
+office-spreadsheet-attlist =
+  attribute table:structure-protected { boolean }?,
+  attribute table:protection-key { \string }?,
+  attribute table:protection-key-digest-algorithm { anyIRI }?
+table-calculation-settings =
+  element table:calculation-settings {
+    table-calculation-setting-attlist,
+    table-null-date?,
+    table-iteration?
+  }
+table-calculation-setting-attlist =
+  attribute table:case-sensitive { boolean }?
+  & attribute table:precision-as-shown { boolean }?
+  & attribute table:search-criteria-must-apply-to-whole-cell {
+      boolean
+    }?
+  & attribute table:automatic-find-labels { boolean }?
+  & attribute table:use-regular-expressions { boolean }?
+  & attribute table:use-wildcards { boolean }?
+  & attribute table:null-year { positiveInteger }?
+table-null-date =
+  element table:null-date {
+    attribute table:value-type { "date" }?,
+    attribute table:date-value { date }?,
+    empty
+  }
+table-iteration =
+  element table:iteration {
+    attribute table:status { "enable" | "disable" }?,
+    attribute table:steps { positiveInteger }?,
+    attribute table:maximum-difference { double }?,
+    empty
+  }
+table-content-validations =
+  element table:content-validations { table-content-validation+ }
+table-content-validation =
+  element table:content-validation {
+    table-validation-attlist,
+    table-help-message?,
+    (table-error-message | (table-error-macro, office-event-listeners))?
+  }
+table-validation-attlist =
+  attribute table:name { \string }
+  & attribute table:condition { \string }?
+  & attribute table:base-cell-address { cellAddress }?
+  & attribute table:allow-empty-cell { boolean }?
+  & attribute table:display-list {
+      "none" | "unsorted" | "sort-ascending"
+    }?
+table-help-message =
+  element table:help-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    text-p*
+  }
+table-error-message =
+  element table:error-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    attribute table:message-type {
+      "stop" | "warning" | "information"
+    }?,
+    text-p*
+  }
+table-error-macro =
+  element table:error-macro {
+    attribute table:execute { boolean }?
+  }
+table-label-ranges = element table:label-ranges { table-label-range* }
+table-label-range =
+  element table:label-range { table-label-range-attlist, empty }
+table-label-range-attlist =
+  attribute table:label-cell-range-address { cellRangeAddress }
+  & attribute table:data-cell-range-address { cellRangeAddress }
+  & attribute table:orientation { "column" | "row" }
+table-named-expressions =
+  element table:named-expressions {
+    (table-named-range | table-named-expression)*
+  }
+table-named-range =
+  element table:named-range { table-named-range-attlist, empty }
+table-named-range-attlist =
+  attribute table:name { \string },
+  attribute table:cell-range-address { cellRangeAddress },
+  attribute table:base-cell-address { cellAddress }?,
+  attribute table:range-usable-as {
+    "none"
+    | list {
+        ("print-range" | "filter" | "repeat-row" | "repeat-column")+
+      }
+  }?
+table-named-expression =
+  element table:named-expression {
+    table-named-expression-attlist, empty
+  }
+table-named-expression-attlist =
+  attribute table:name { \string },
+  attribute table:expression { \string },
+  attribute table:base-cell-address { cellAddress }?
+table-database-ranges =
+  element table:database-ranges { table-database-range* }
+table-database-range =
+  element table:database-range {
+    table-database-range-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query)?,
+    table-filter?,
+    table-sort?,
+    table-subtotal-rules?
+  }
+table-database-range-attlist =
+  attribute table:name { \string }?
+  & attribute table:is-selection { boolean }?
+  & attribute table:on-update-keep-styles { boolean }?
+  & attribute table:on-update-keep-size { boolean }?
+  & attribute table:has-persistent-data { boolean }?
+  & attribute table:orientation { "column" | "row" }?
+  & attribute table:contains-header { boolean }?
+  & attribute table:display-filter-buttons { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:refresh-delay { boolean }?
+table-database-source-sql =
+  element table:database-source-sql {
+    table-database-source-sql-attlist, empty
+  }
+table-database-source-sql-attlist =
+  attribute table:database-name { \string }
+  & attribute table:sql-statement { \string }
+  & attribute table:parse-sql-statement { boolean }?
+table-database-source-query =
+  element table:database-source-table {
+    table-database-source-table-attlist, empty
+  }
+table-database-source-table-attlist =
+  attribute table:database-name { \string }
+  & attribute table:database-table-name { \string }
+table-database-source-table =
+  element table:database-source-query {
+    table-database-source-query-attlist, empty
+  }
+table-database-source-query-attlist =
+  attribute table:database-name { \string }
+  & attribute table:query-name { \string }
+table-sort = element table:sort { table-sort-attlist, table-sort-by+ }
+table-sort-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:language { languageCode }?
+  & attribute table:country { countryCode }?
+  & attribute table:script { scriptCode }?
+  & attribute table:rfc-language-tag { language }?
+  & attribute table:algorithm { \string }?
+  & attribute table:embedded-number-behavior {
+      "alpha-numeric" | "integer" | "double"
+    }?
+table-sort-by = element table:sort-by { table-sort-by-attlist, empty }
+table-sort-by-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:data-type {
+      "text" | "number" | "automatic" | \string
+    }?
+  & attribute table:order { "ascending" | "descending" }?
+table-subtotal-rules =
+  element table:subtotal-rules {
+    table-subtotal-rules-attlist,
+    table-sort-groups?,
+    table-subtotal-rule*
+  }
+table-subtotal-rules-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:page-breaks-on-group-change { boolean }?
+table-sort-groups =
+  element table:sort-groups { table-sort-groups-attlist, empty }
+table-sort-groups-attlist =
+  attribute table:data-type {
+    "text" | "number" | "automatic" | \string
+  }?
+  & attribute table:order { "ascending" | "descending" }?
+table-subtotal-rule =
+  element table:subtotal-rule {
+    table-subtotal-rule-attlist, table-subtotal-field*
+  }
+table-subtotal-rule-attlist =
+  attribute table:group-by-field-number { nonNegativeInteger }
+table-subtotal-field =
+  element table:subtotal-field { table-subtotal-field-attlist, empty }
+table-subtotal-field-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:function {
+      "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
+    }
+table-filter =
+  element table:filter {
+    table-filter-attlist,
+    (table-filter-condition | table-filter-and | table-filter-or)
+  }
+table-filter-attlist =
+  attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:condition-source { "self" | "cell-range" }?
+  & attribute table:condition-source-range-address { cellRangeAddress }?
+  & attribute table:display-duplicates { boolean }?
+table-filter-and =
+  element table:filter-and {
+    (table-filter-or | table-filter-condition)+
+  }
+table-filter-or =
+  element table:filter-or {
+    (table-filter-and | table-filter-condition)+
+  }
+table-filter-condition =
+  element table:filter-condition {
+    table-filter-condition-attlist, table-filter-set-item*
+  }
+table-filter-condition-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:value { \string | double }
+  & attribute table:operator { \string }
+  & attribute table:case-sensitive { \string }?
+  & attribute table:data-type { "text" | "number" }?
+table-filter-set-item =
+  element table:filter-set-item {
+    attribute table:value { \string },
+    empty
+  }
+table-data-pilot-tables =
+  element table:data-pilot-tables { table-data-pilot-table* }
+table-data-pilot-table =
+  element table:data-pilot-table {
+    table-data-pilot-table-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query
+     | table-source-service
+     | table-source-cell-range)?,
+    table-data-pilot-field+
+  }
+table-data-pilot-table-attlist =
+  attribute table:name { \string }
+  & attribute table:application-data { \string }?
+  & attribute table:grand-total { "none" | "row" | "column" | "both" }?
+  & attribute table:ignore-empty-rows { boolean }?
+  & attribute table:identify-categories { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:buttons { cellRangeAddressList }?
+  & attribute table:show-filter-button { boolean }?
+  & attribute table:drill-down-on-double-click { boolean }?
+table-source-cell-range =
+  element table:source-cell-range {
+    table-source-cell-range-attlist, table-filter?
+  }
+table-source-cell-range-attlist =
+  attribute table:cell-range-address { cellRangeAddress }
+table-source-service =
+  element table:source-service { table-source-service-attlist, empty }
+table-source-service-attlist =
+  attribute table:name { \string }
+  & attribute table:source-name { \string }
+  & attribute table:object-name { \string }
+  & attribute table:user-name { \string }?
+  & attribute table:password { \string }?
+table-data-pilot-field =
+  element table:data-pilot-field {
+    table-data-pilot-field-attlist,
+    table-data-pilot-level?,
+    table-data-pilot-field-reference?,
+    table-data-pilot-groups?
+  }
+table-data-pilot-field-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:orientation {
+       "row" | "column" | "data" | "hidden"
+     }
+     | (attribute table:orientation { "page" },
+        attribute table:selected-page { \string }))
+  & attribute table:is-data-layout-field { \string }?
+  & attribute table:function {
+      "auto"
+      | "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
+    }?
+  & attribute table:used-hierarchy { integer }?
+table-data-pilot-level =
+  element table:data-pilot-level {
+    table-data-pilot-level-attlist,
+    table-data-pilot-subtotals?,
+    table-data-pilot-members?,
+    table-data-pilot-display-info?,
+    table-data-pilot-sort-info?,
+    table-data-pilot-layout-info?
+  }
+table-data-pilot-level-attlist = attribute table:show-empty { boolean }?
+table-data-pilot-subtotals =
+  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
+table-data-pilot-subtotal =
+  element table:data-pilot-subtotal {
+    table-data-pilot-subtotal-attlist, empty
+  }
+table-data-pilot-subtotal-attlist =
+  attribute table:function {
+    "auto"
+    | "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+table-data-pilot-members =
+  element table:data-pilot-members { table-data-pilot-member* }
+table-data-pilot-member =
+  element table:data-pilot-member {
+    table-data-pilot-member-attlist, empty
+  }
+table-data-pilot-member-attlist =
+  attribute table:name { \string }
+  & attribute table:display { boolean }?
+  & attribute table:show-details { boolean }?
+table-data-pilot-display-info =
+  element table:data-pilot-display-info {
+    table-data-pilot-display-info-attlist, empty
+  }
+table-data-pilot-display-info-attlist =
+  attribute table:enabled { boolean }
+  & attribute table:data-field { \string }
+  & attribute table:member-count { nonNegativeInteger }
+  & attribute table:display-member-mode { "from-top" | "from-bottom" }
+table-data-pilot-sort-info =
+  element table:data-pilot-sort-info {
+    table-data-pilot-sort-info-attlist, empty
+  }
+table-data-pilot-sort-info-attlist =
+  ((attribute table:sort-mode { "data" },
+    attribute table:data-field { \string })
+   | attribute table:sort-mode { "none" | "manual" | "name" })
+  & attribute table:order { "ascending" | "descending" }
+table-data-pilot-layout-info =
+  element table:data-pilot-layout-info {
+    table-data-pilot-layout-info-attlist, empty
+  }
+table-data-pilot-layout-info-attlist =
+  attribute table:layout-mode {
+    "tabular-layout"
+    | "outline-subtotals-top"
+    | "outline-subtotals-bottom"
+  }
+  & attribute table:add-empty-lines { boolean }
+table-data-pilot-field-reference =
+  element table:data-pilot-field-reference {
+    table-data-pilot-field-reference-attlist
+  }
+table-data-pilot-field-reference-attlist =
+  attribute table:field-name { \string }
+  & ((attribute table:member-type { "named" },
+      attribute table:member-name { \string })
+     | attribute table:member-type { "previous" | "next" })
+  & attribute table:type {
+      "none"
+      | "member-difference"
+      | "member-percentage"
+      | "member-percentage-difference"
+      | "running-total"
+      | "row-percentage"
+      | "column-percentage"
+      | "total-percentage"
+      | "index"
+    }
+table-data-pilot-groups =
+  element table:data-pilot-groups {
+    table-data-pilot-groups-attlist, table-data-pilot-group+
+  }
+table-data-pilot-groups-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:date-start { dateOrDateTime | "auto" }
+     | attribute table:start { double | "auto" })
+  & (attribute table:date-end { dateOrDateTime | "auto" }
+     | attribute table:end { double | "auto" })
+  & attribute table:step { double }
+  & attribute table:grouped-by {
+      "seconds"
+      | "minutes"
+      | "hours"
+      | "days"
+      | "months"
+      | "quarters"
+      | "years"
+    }
+table-data-pilot-group =
+  element table:data-pilot-group {
+    table-data-pilot-group-attlist, table-data-pilot-group-member+
+  }
+table-data-pilot-group-attlist = attribute table:name { \string }
+table-data-pilot-group-member =
+  element table:data-pilot-group-member {
+    table-data-pilot-group-member-attlist
+  }
+table-data-pilot-group-member-attlist = attribute table:name { \string }
+table-consolidation =
+  element table:consolidation { table-consolidation-attlist, empty }
+table-consolidation-attlist =
+  attribute table:function {
+    "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+  & attribute table:source-cell-range-addresses { cellRangeAddressList }
+  & attribute table:target-cell-address { cellAddress }
+  & attribute table:use-labels { "none" | "row" | "column" | "both" }?
+  & attribute table:link-to-source-data { boolean }?
+table-dde-links = element table:dde-links { table-dde-link+ }
+table-tracked-changes =
+  element table:tracked-changes {
+    table-tracked-changes-attlist,
+    (table-cell-content-change
+     | table-insertion
+     | table-deletion
+     | table-movement)*
+  }
+table-tracked-changes-attlist =
+  attribute table:track-changes { boolean }?
+table-insertion =
+  element table:insertion {
+    table-insertion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-insertion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:count { positiveInteger }?
+  & attribute table:table { integer }?
+table-dependencies = element table:dependencies { table-dependency+ }
+table-dependency =
+  element table:dependency {
+    attribute table:id { \string },
+    empty
+  }
+table-deletions =
+  element table:deletions {
+    (table-cell-content-deletion | table-change-deletion)+
+  }
+table-cell-content-deletion =
+  element table:cell-content-deletion {
+    attribute table:id { \string }?,
+    table-cell-address?,
+    table-change-track-table-cell?
+  }
+table-change-deletion =
+  element table:change-deletion {
+    attribute table:id { \string }?,
+    empty
+  }
+table-deletion =
+  element table:deletion {
+    table-deletion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-cut-offs?
+  }
+table-deletion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:table { integer }?
+  & attribute table:multi-deletion-spanned { integer }?
+table-cut-offs =
+  element table:cut-offs {
+    table-movement-cut-off+
+    | (table-insertion-cut-off, table-movement-cut-off*)
+  }
+table-insertion-cut-off =
+  element table:insertion-cut-off {
+    table-insertion-cut-off-attlist, empty
+  }
+table-insertion-cut-off-attlist =
+  attribute table:id { \string }
+  & attribute table:position { integer }
+table-movement-cut-off =
+  element table:movement-cut-off {
+    table-movement-cut-off-attlist, empty
+  }
+table-movement-cut-off-attlist =
+  attribute table:position { integer }
+  | (attribute table:start-position { integer },
+     attribute table:end-position { integer })
+table-movement =
+  element table:movement {
+    common-table-change-attlist,
+    table-source-range-address,
+    table-target-range-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-source-range-address =
+  element table:source-range-address {
+    common-table-range-attlist, empty
+  }
+table-target-range-address =
+  element table:target-range-address {
+    common-table-range-attlist, empty
+  }
+common-table-range-attlist =
+  common-table-cell-address-attlist
+  | common-table-cell-range-address-attlist
+common-table-cell-address-attlist =
+  attribute table:column { integer },
+  attribute table:row { integer },
+  attribute table:table { integer }
+common-table-cell-range-address-attlist =
+  attribute table:start-column { integer },
+  attribute table:start-row { integer },
+  attribute table:start-table { integer },
+  attribute table:end-column { integer },
+  attribute table:end-row { integer },
+  attribute table:end-table { integer }
+table-change-track-table-cell =
+  element table:change-track-table-cell {
+    table-change-track-table-cell-attlist, text-p*
+  }
+table-change-track-table-cell-attlist =
+  attribute table:cell-address { cellAddress }?
+  & attribute table:matrix-covered { boolean }?
+  & attribute table:formula { \string }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+  & common-value-and-type-attlist?
+table-cell-content-change =
+  element table:cell-content-change {
+    common-table-change-attlist,
+    table-cell-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-previous
+  }
+table-cell-address =
+  element table:cell-address {
+    common-table-cell-address-attlist, empty
+  }
+table-previous =
+  element table:previous {
+    attribute table:id { \string }?,
+    table-change-track-table-cell
+  }
+common-table-change-attlist =
+  attribute table:id { \string }
+  & attribute table:acceptance-state {
+      "accepted" | "rejected" | "pending"
+    }?
+  & attribute table:rejecting-change-id { \string }?
+style-handout-master =
+  element style:handout-master {
+    common-presentation-header-footer-attlist,
+    style-handout-master-attlist,
+    shape*
+  }
+style-handout-master-attlist =
+  attribute presentation:presentation-page-layout-name { styleNameRef }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+draw-layer-set = element draw:layer-set { draw-layer* }
+draw-layer =
+  element draw:layer { draw-layer-attlist, svg-title?, svg-desc? }
+draw-layer-attlist =
+  attribute draw:name { \string }
+  & attribute draw:protected { boolean }?
+  & attribute draw:display { "always" | "screen" | "printer" | "none" }?
+draw-page =
+  element draw:page {
+    common-presentation-header-footer-attlist,
+    draw-page-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    (presentation-animations | animation-element)?,
+    presentation-notes?
+  }
+draw-page-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:style-name { styleNameRef }?
+  & attribute draw:master-page-name { styleNameRef }
+  & attribute presentation:presentation-page-layout-name {
+      styleNameRef
+    }?
+  & (xml-id,
+     attribute draw:id { NCName }?)?
+  & attribute draw:nav-order { IDREFS }?
+common-presentation-header-footer-attlist =
+  attribute presentation:use-header-name { \string }?
+  & attribute presentation:use-footer-name { \string }?
+  & attribute presentation:use-date-time-name { \string }?
+shape = shape-instance | draw-a
+shape-instance =
+  draw-rect
+  | draw-line
+  | draw-polyline
+  | draw-polygon
+  | draw-regular-polygon
+  | draw-path
+  | draw-circle
+  | draw-ellipse
+  | draw-g
+  | draw-page-thumbnail
+  | draw-frame
+  | draw-measure
+  | draw-caption
+  | draw-connector
+  | draw-control
+  | dr3d-scene
+  | draw-custom-shape
+draw-rect =
+  element draw:rect {
+    draw-rect-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-rect-attlist =
+  attribute draw:corner-radius { nonNegativeLength }?
+  | (attribute svg:rx { nonNegativeLength }?,
+     attribute svg:ry { nonNegativeLength }?)
+draw-line =
+  element draw:line {
+    draw-line-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-line-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-polyline =
+  element draw:polyline {
+    common-draw-points-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+common-draw-points-attlist = attribute draw:points { points }
+draw-polygon =
+  element draw:polygon {
+    common-draw-points-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-regular-polygon =
+  element draw:regular-polygon {
+    draw-regular-polygon-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-regular-polygon-attlist =
+  (attribute draw:concave { "false" }
+   | (attribute draw:concave { "true" },
+      draw-regular-polygon-sharpness-attlist))
+  & attribute draw:corners { positiveInteger }
+draw-regular-polygon-sharpness-attlist =
+  attribute draw:sharpness { percent }
+draw-path =
+  element draw:path {
+    common-draw-path-data-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+common-draw-path-data-attlist = attribute svg:d { pathData }
+draw-circle =
+  element draw:circle {
+    ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+common-draw-circle-ellipse-pos-attlist =
+  attribute svg:cx { coordinate },
+  attribute svg:cy { coordinate }
+draw-circle-attlist = attribute svg:r { length }
+common-draw-circle-ellipse-attlist =
+  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
+  & attribute draw:start-angle { angle }?
+  & attribute draw:end-angle { angle }?
+draw-ellipse =
+  element draw:ellipse {
+    ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-ellipse-attlist =
+  attribute svg:rx { length },
+  attribute svg:ry { length }
+draw-connector =
+  element draw:connector {
+    draw-connector-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    common-draw-viewbox-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-connector-attlist =
+  attribute draw:type { "standard" | "lines" | "line" | "curve" }?
+  & (attribute svg:x1 { coordinate },
+     attribute svg:y1 { coordinate })?
+  & attribute draw:start-shape { IDREF }?
+  & attribute draw:start-glue-point { nonNegativeInteger }?
+  & (attribute svg:x2 { coordinate },
+     attribute svg:y2 { coordinate })?
+  & attribute draw:end-shape { IDREF }?
+  & attribute draw:end-glue-point { nonNegativeInteger }?
+  & attribute draw:line-skew {
+      list { length, (length, length?)? }
+    }?
+  & attribute svg:d { pathData }?
+draw-caption =
+  element draw:caption {
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-caption-attlist =
+  (attribute draw:caption-point-x { coordinate },
+   attribute draw:caption-point-y { coordinate })?
+  & attribute draw:corner-radius { nonNegativeLength }?
+draw-measure =
+  element draw:measure {
+    draw-measure-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
+  }
+draw-measure-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-control =
+  element draw:control {
+    draw-control-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-glue-point*
+  }
+draw-control-attlist = attribute draw:control { IDREF }
+draw-page-thumbnail =
+  element draw:page-thumbnail {
+    draw-page-thumbnail-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    presentation-shape-attlist,
+    common-draw-shape-with-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?
+  }
+draw-page-thumbnail-attlist =
+  attribute draw:page-number { positiveInteger }?
+draw-g =
+  element draw:g {
+    draw-g-attlist,
+    common-draw-z-index-attlist,
+    common-draw-name-attlist,
+    common-draw-id-attlist,
+    common-draw-style-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    shape*
+  }
+draw-g-attlist = attribute svg:y { coordinate }?
+common-draw-name-attlist = attribute draw:name { \string }?
+common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
+common-draw-position-attlist =
+  attribute svg:x { coordinate }?,
+  attribute svg:y { coordinate }?
+common-draw-size-attlist =
+  attribute svg:width { length }?,
+  attribute svg:height { length }?
+common-draw-transform-attlist = attribute draw:transform { \string }?
+common-draw-viewbox-attlist =
+  attribute svg:viewBox {
+    list { integer, integer, integer, integer }
+  }
+common-draw-style-name-attlist =
+  (attribute draw:style-name { styleNameRef }?,
+   attribute draw:class-names { styleNameRefs }?)
+  | (attribute presentation:style-name { styleNameRef }?,
+     attribute presentation:class-names { styleNameRefs }?)
+common-draw-text-style-name-attlist =
+  attribute draw:text-style-name { styleNameRef }?
+common-draw-layer-name-attlist = attribute draw:layer { \string }?
+common-draw-id-attlist =
+  (xml-id,
+   attribute draw:id { NCName }?)?
+common-draw-z-index-attlist =
+  attribute draw:z-index { nonNegativeInteger }?
+common-text-spreadsheet-shape-attlist =
+  attribute table:end-cell-address { cellAddress }?
+  & attribute table:end-x { coordinate }?
+  & attribute table:end-y { coordinate }?
+  & attribute table:table-background { boolean }?
+  & common-text-anchor-attlist
+common-text-anchor-attlist =
+  attribute text:anchor-type {
+    "page" | "frame" | "paragraph" | "char" | "as-char"
+  }?
+  & attribute text:anchor-page-number { positiveInteger }?
+draw-text = (text-p | text-list)*
+common-draw-shape-with-styles-attlist =
+  common-draw-z-index-attlist,
+  common-draw-id-attlist,
+  common-draw-layer-name-attlist,
+  common-draw-style-name-attlist,
+  common-draw-transform-attlist,
+  common-draw-name-attlist,
+  common-text-spreadsheet-shape-attlist
+common-draw-shape-with-text-and-styles-attlist =
+  common-draw-shape-with-styles-attlist,
+  common-draw-text-style-name-attlist
+draw-glue-point =
+  element draw:glue-point { draw-glue-point-attlist, empty }
+draw-glue-point-attlist =
+  attribute draw:id { nonNegativeInteger }
+  & attribute svg:x { distance | percent }
+  & attribute svg:y { distance | percent }
+  & attribute draw:align {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom-right"
+    }?
+  & attribute draw:escape-direction {
+      "auto"
+      | "left"
+      | "right"
+      | "up"
+      | "down"
+      | "horizontal"
+      | "vertical"
+    }
+svg-title = element svg:title { text }
+svg-desc = element svg:desc { text }
+draw-frame =
+  element draw:frame {
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-position-attlist,
+    common-draw-rel-size-attlist,
+    common-draw-caption-id-attlist,
+    presentation-shape-attlist,
+    draw-frame-attlist,
+    (draw-text-box
+     | draw-image
+     | draw-object
+     | draw-object-ole
+     | draw-applet
+     | draw-floating-frame
+     | draw-plugin
+     | table-table)*,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-image-map?,
+    svg-title?,
+    svg-desc?,
+    (draw-contour-polygon | draw-contour-path)?
+  }
+common-draw-rel-size-attlist =
+  common-draw-size-attlist,
+  attribute style:rel-width { percent | "scale" | "scale-min" }?,
+  attribute style:rel-height { percent | "scale" | "scale-min" }?
+draw-frame-attlist = attribute draw:copy-of { \string }?
+draw-text-box =
+  element draw:text-box { draw-text-box-attlist, text-content* }
+draw-text-box-attlist =
+  attribute draw:chain-next-name { \string }?
+  & attribute draw:corner-radius { nonNegativeLength }?
+  & attribute fo:min-height { length | percent }?
+  & attribute fo:min-width { length | percent }?
+  & attribute fo:max-height { length | percent }?
+  & attribute fo:max-width { length | percent }?
+  & (xml-id,
+     attribute text:id { NCName }?)?
+draw-image =
+  element draw:image {
+    draw-image-attlist,
+    (common-draw-data-attlist | office-binary-data),
+    draw-text
+  }
+common-draw-data-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "embed" }?,
+  attribute xlink:actuate { "onLoad" }?
+office-binary-data = element office:binary-data { base64Binary }
+draw-image-attlist =
+  attribute draw:filter-name { \string }?
+  & xml-id?
+draw-object =
+  element draw:object {
+    draw-object-attlist,
+    (common-draw-data-attlist | office-document | math-math)
+  }
+draw-object-ole =
+  element draw:object-ole {
+    draw-object-ole-attlist,
+    (common-draw-data-attlist | office-binary-data)
+  }
+draw-object-attlist =
+  attribute draw:notify-on-update-of-ranges {
+    cellRangeAddressList | \string
+  }?
+  & xml-id?
+draw-object-ole-attlist =
+  attribute draw:class-id { \string }?
+  & xml-id?
+draw-applet =
+  element draw:applet {
+    draw-applet-attlist, common-draw-data-attlist?, draw-param*
+  }
+draw-applet-attlist =
+  attribute draw:code { \string }?
+  & attribute draw:object { \string }?
+  & attribute draw:archive { \string }?
+  & attribute draw:may-script { boolean }?
+  & xml-id?
+draw-plugin =
+  element draw:plugin {
+    draw-plugin-attlist, common-draw-data-attlist, draw-param*
+  }
+draw-plugin-attlist =
+  attribute draw:mime-type { \string }?
+  & xml-id?
+draw-param = element draw:param { draw-param-attlist, empty }
+draw-param-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:value { \string }?
+draw-floating-frame =
+  element draw:floating-frame {
+    draw-floating-frame-attlist, common-draw-data-attlist
+  }
+draw-floating-frame-attlist =
+  attribute draw:frame-name { \string }?
+  & xml-id?
+draw-contour-polygon =
+  element draw:contour-polygon {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    empty
+  }
+draw-contour-path =
+  element draw:contour-path {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    empty
+  }
+common-contour-attlist = attribute draw:recreate-on-edit { boolean }
+draw-a = element draw:a { draw-a-attlist, shape-instance }
+draw-a-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute office:server-map { boolean }?
+  & xml-id?
+draw-image-map =
+  element draw:image-map {
+    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
+  }
+draw-area-rectangle =
+  element draw:area-rectangle {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
+  }
+draw-area-circle =
+  element draw:area-circle {
+    common-draw-area-attlist,
+    attribute svg:cx { coordinate },
+    attribute svg:cy { coordinate },
+    attribute svg:r { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
+  }
+draw-area-polygon =
+  element draw:area-polygon {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
+  }
+common-draw-area-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute office:target-frame-name { targetFrameName }?,
+   attribute xlink:show { "new" | "replace" }?)?
+  & attribute office:name { \string }?
+  & attribute draw:nohref { "nohref" }?
+dr3d-scene =
+  element dr3d:scene {
+    dr3d-scene-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-style-name-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-dr3d-transform-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    dr3d-light*,
+    shapes3d*,
+    draw-glue-point*
+  }
+shapes3d =
+  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
+dr3d-scene-attlist =
+  attribute dr3d:vrp { vector3D }?
+  & attribute dr3d:vpn { vector3D }?
+  & attribute dr3d:vup { vector3D }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute dr3d:distance { length }?
+  & attribute dr3d:focal-length { length }?
+  & attribute dr3d:shadow-slant { angle }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
+    }?
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:lighting-mode { boolean }?
+common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
+dr3d-light = element dr3d:light { dr3d-light-attlist, empty }
+dr3d-light-attlist =
+  attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:direction { vector3D }
+  & attribute dr3d:enabled { boolean }?
+  & attribute dr3d:specular { boolean }?
+dr3d-cube =
+  element dr3d:cube {
+    dr3d-cube-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
+  }
+dr3d-cube-attlist =
+  attribute dr3d:min-edge { vector3D }?,
+  attribute dr3d:max-edge { vector3D }?
+dr3d-sphere =
+  element dr3d:sphere {
+    dr3d-sphere-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
+  }
+dr3d-sphere-attlist =
+  attribute dr3d:center { vector3D }?
+  & attribute dr3d:size { vector3D }?
+dr3d-extrude =
+  element dr3d:extrude {
+    common-draw-path-data-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-id-attlist,
+    common-draw-z-index-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
+  }
+dr3d-rotate =
+  element dr3d:rotate {
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
+  }
+draw-custom-shape =
+  element draw:custom-shape {
+    draw-custom-shape-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text,
+    draw-enhanced-geometry?
+  }
+draw-custom-shape-attlist =
+  attribute draw:engine { namespacedToken }?
+  & attribute draw:data { \string }?
+draw-enhanced-geometry =
+  element draw:enhanced-geometry {
+    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
+  }
+draw-enhanced-geometry-attlist =
+  attribute draw:type { custom-shape-type }?
+  & attribute svg:viewBox {
+      list { integer, integer, integer, integer }
+    }?
+  & attribute draw:mirror-vertical { boolean }?
+  & attribute draw:mirror-horizontal { boolean }?
+  & attribute draw:text-rotate-angle { angle }?
+  & attribute draw:extrusion-allowed { boolean }?
+  & attribute draw:text-path-allowed { boolean }?
+  & attribute draw:concentric-gradient-fill-allowed { boolean }?
+  & attribute draw:extrusion { boolean }?
+  & attribute draw:extrusion-brightness { zeroToHundredPercent }?
+  & attribute draw:extrusion-depth {
+      list { length, double }
+    }?
+  & attribute draw:extrusion-diffusion { percent }?
+  & attribute draw:extrusion-number-of-line-segments { integer }?
+  & attribute draw:extrusion-light-face { boolean }?
+  & attribute draw:extrusion-first-light-harsh { boolean }?
+  & attribute draw:extrusion-second-light-harsh { boolean }?
+  & attribute draw:extrusion-first-light-level { zeroToHundredPercent }?
+  & attribute draw:extrusion-second-light-level {
+      zeroToHundredPercent
+    }?
+  & attribute draw:extrusion-first-light-direction { vector3D }?
+  & attribute draw:extrusion-second-light-direction { vector3D }?
+  & attribute draw:extrusion-metal { boolean }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
+    }?
+  & attribute draw:extrusion-rotation-angle {
+      list { angle, angle }
+    }?
+  & attribute draw:extrusion-rotation-center { vector3D }?
+  & attribute draw:extrusion-shininess { zeroToHundredPercent }?
+  & attribute draw:extrusion-skew {
+      list { double, angle }
+    }?
+  & attribute draw:extrusion-specularity { zeroToHundredPercent }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute draw:extrusion-viewpoint { point3D }?
+  & attribute draw:extrusion-origin {
+      list { extrusionOrigin, extrusionOrigin }
+    }?
+  & attribute draw:extrusion-color { boolean }?
+  & attribute draw:enhanced-path { \string }?
+  & attribute draw:path-stretchpoint-x { double }?
+  & attribute draw:path-stretchpoint-y { double }?
+  & attribute draw:text-areas { \string }?
+  & attribute draw:glue-points { \string }?
+  & attribute draw:glue-point-type {
+      "none" | "segments" | "rectangle"
+    }?
+  & attribute draw:glue-point-leaving-directions { \string }?
+  & attribute draw:text-path { boolean }?
+  & attribute draw:text-path-mode { "normal" | "path" | "shape" }?
+  & attribute draw:text-path-scale { "path" | "shape" }?
+  & attribute draw:text-path-same-letter-heights { boolean }?
+  & attribute draw:modifiers { \string }?
+custom-shape-type = "non-primitive" | \string
+point3D =
+  xsd:string {
+    pattern =
+      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)"
+  }
+extrusionOrigin =
+  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
+draw-equation = element draw:equation { draw-equation-attlist, empty }
+draw-equation-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:formula { \string }?
+draw-handle = element draw:handle { draw-handle-attlist, empty }
+draw-handle-attlist =
+  attribute draw:handle-mirror-vertical { boolean }?
+  & attribute draw:handle-mirror-horizontal { boolean }?
+  & attribute draw:handle-switched { boolean }?
+  & attribute draw:handle-position { \string }
+  & attribute draw:handle-range-x-minimum { \string }?
+  & attribute draw:handle-range-x-maximum { \string }?
+  & attribute draw:handle-range-y-minimum { \string }?
+  & attribute draw:handle-range-y-maximum { \string }?
+  & attribute draw:handle-polar { \string }?
+  & attribute draw:handle-radius-range-minimum { \string }?
+  & attribute draw:handle-radius-range-maximum { \string }?
+presentation-shape-attlist =
+  attribute presentation:class { presentation-classes }?
+  & attribute presentation:placeholder { boolean }?
+  & attribute presentation:user-transformed { boolean }?
+presentation-classes =
+  "title"
+  | "outline"
+  | "subtitle"
+  | "text"
+  | "graphic"
+  | "object"
+  | "chart"
+  | "table"
+  | "orgchart"
+  | "page"
+  | "notes"
+  | "handout"
+  | "header"
+  | "footer"
+  | "date-time"
+  | "page-number"
+presentation-animations =
+  element presentation:animations {
+    (presentation-animation-elements | presentation-animation-group)*
+  }
+presentation-animation-elements =
+  presentation-show-shape
+  | presentation-show-text
+  | presentation-hide-shape
+  | presentation-hide-text
+  | presentation-dim
+  | presentation-play
+presentation-sound =
+  element presentation:sound {
+    presentation-sound-attlist,
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI },
+    attribute xlink:actuate { "onRequest" }?,
+    attribute xlink:show { "new" | "replace" }?,
+    empty
+  }
+presentation-sound-attlist =
+  attribute presentation:play-full { boolean }?
+  & xml-id?
+presentation-show-shape =
+  element presentation:show-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+common-presentation-effect-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:delay { duration }?
+  & attribute presentation:start-scale { percent }?
+  & attribute presentation:path-id { \string }?
+presentationEffects =
+  "none"
+  | "fade"
+  | "move"
+  | "stripes"
+  | "open"
+  | "close"
+  | "dissolve"
+  | "wavyline"
+  | "random"
+  | "lines"
+  | "laser"
+  | "appear"
+  | "hide"
+  | "move-short"
+  | "checkerboard"
+  | "rotate"
+  | "stretch"
+presentationEffectDirections =
+  "none"
+  | "from-left"
+  | "from-top"
+  | "from-right"
+  | "from-bottom"
+  | "from-center"
+  | "from-upper-left"
+  | "from-upper-right"
+  | "from-lower-left"
+  | "from-lower-right"
+  | "to-left"
+  | "to-top"
+  | "to-right"
+  | "to-bottom"
+  | "to-upper-left"
+  | "to-upper-right"
+  | "to-lower-right"
+  | "to-lower-left"
+  | "path"
+  | "spiral-inward-left"
+  | "spiral-inward-right"
+  | "spiral-outward-left"
+  | "spiral-outward-right"
+  | "vertical"
+  | "horizontal"
+  | "to-center"
+  | "clockwise"
+  | "counter-clockwise"
+presentationSpeeds = "slow" | "medium" | "fast"
+presentation-show-text =
+  element presentation:show-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-hide-shape =
+  element presentation:hide-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-hide-text =
+  element presentation:hide-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-dim =
+  element presentation:dim {
+    presentation-dim-attlist, presentation-sound?
+  }
+presentation-dim-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute draw:color { color }
+presentation-play =
+  element presentation:play { presentation-play-attlist, empty }
+presentation-play-attlist =
+  attribute draw:shape-id { IDREF },
+  attribute presentation:speed { presentationSpeeds }?
+presentation-animation-group =
+  element presentation:animation-group {
+    presentation-animation-elements*
+  }
+common-anim-attlist =
+  attribute presentation:node-type {
+    "default"
+    | "on-click"
+    | "with-previous"
+    | "after-previous"
+    | "timing-root"
+    | "main-sequence"
+    | "interactive-sequence"
+  }?
+  & attribute presentation:preset-id { \string }?
+  & attribute presentation:preset-sub-type { \string }?
+  & attribute presentation:preset-class {
+      "custom"
+      | "entrance"
+      | "exit"
+      | "emphasis"
+      | "motion-path"
+      | "ole-action"
+      | "media-call"
+    }?
+  & attribute presentation:master-element { IDREF }?
+  & attribute presentation:group-id { \string }?
+  & (xml-id,
+     attribute anim:id { NCName }?)?
+presentation-event-listener =
+  element presentation:event-listener {
+    presentation-event-listener-attlist, presentation-sound?
+  }
+presentation-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute presentation:action {
+      "none"
+      | "previous-page"
+      | "next-page"
+      | "first-page"
+      | "last-page"
+      | "hide"
+      | "stop"
+      | "execute"
+      | "show"
+      | "verb"
+      | "fade-out"
+      | "sound"
+      | "last-visited-page"
+    }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:start-scale { percent }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI },
+     attribute xlink:show { "embed" }?,
+     attribute xlink:actuate { "onRequest" }?)?
+  & attribute presentation:verb { nonNegativeInteger }?
+presentation-decls = presentation-decl*
+presentation-decl =
+  element presentation:header-decl {
+    presentation-header-decl-attlist, text
+  }
+  | element presentation:footer-decl {
+      presentation-footer-decl-attlist, text
+    }
+  | element presentation:date-time-decl {
+      presentation-date-time-decl-attlist, text
+    }
+presentation-header-decl-attlist =
+  attribute presentation:name { \string }
+presentation-footer-decl-attlist =
+  attribute presentation:name { \string }
+presentation-date-time-decl-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:source { "fixed" | "current-date" }
+  & attribute style:data-style-name { styleNameRef }?
+presentation-settings =
+  element presentation:settings {
+    presentation-settings-attlist, presentation-show*
+  }?
+presentation-settings-attlist =
+  attribute presentation:start-page { \string }?
+  & attribute presentation:show { \string }?
+  & attribute presentation:full-screen { boolean }?
+  & attribute presentation:endless { boolean }?
+  & attribute presentation:pause { duration }?
+  & attribute presentation:show-logo { boolean }?
+  & attribute presentation:force-manual { boolean }?
+  & attribute presentation:mouse-visible { boolean }?
+  & attribute presentation:mouse-as-pen { boolean }?
+  & attribute presentation:start-with-navigator { boolean }?
+  & attribute presentation:animations { "enabled" | "disabled" }?
+  & attribute presentation:transition-on-click {
+      "enabled" | "disabled"
+    }?
+  & attribute presentation:stay-on-top { boolean }?
+  & attribute presentation:show-end-of-presentation-slide { boolean }?
+presentation-show =
+  element presentation:show { presentation-show-attlist, empty }
+presentation-show-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:pages { \string }
+chart-chart =
+  element chart:chart {
+    chart-chart-attlist,
+    chart-title?,
+    chart-subtitle?,
+    chart-footer?,
+    chart-legend?,
+    chart-plot-area,
+    table-table?
+  }
+chart-chart-attlist =
+  attribute chart:class { namespacedToken }
+  & common-draw-size-attlist
+  & attribute chart:column-mapping { \string }?
+  & attribute chart:row-mapping { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI })?
+  & xml-id?
+chart-title = element chart:title { chart-title-attlist, text-p? }
+chart-title-attlist =
+  attribute table:cell-range { cellRangeAddressList }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
+chart-footer = element chart:footer { chart-title-attlist, text-p? }
+chart-legend = element chart:legend { chart-legend-attlist, text-p? }
+chart-legend-attlist =
+  ((attribute chart:legend-position {
+      "start" | "end" | "top" | "bottom"
+    },
+    attribute chart:legend-align { "start" | "center" | "end" }?)
+   | attribute chart:legend-position {
+       "top-start" | "bottom-start" | "top-end" | "bottom-end"
+     }
+   | empty)
+  & common-draw-position-attlist
+  & (attribute style:legend-expansion { "wide" | "high" | "balanced" }
+     | (attribute style:legend-expansion { "custom" },
+        attribute style:legend-expansion-aspect-ratio { double })
+     | empty)
+  & attribute chart:style-name { styleNameRef }?
+chart-plot-area =
+  element chart:plot-area {
+    chart-plot-area-attlist,
+    dr3d-light*,
+    chart-axis*,
+    chart-series*,
+    chart-stock-gain-marker?,
+    chart-stock-loss-marker?,
+    chart-stock-range-line?,
+    chart-wall?,
+    chart-floor?
+  }
+chart-plot-area-attlist =
+  common-draw-position-attlist
+  & common-draw-size-attlist
+  & attribute chart:style-name { styleNameRef }?
+  & attribute table:cell-range-address { cellRangeAddressList }?
+  & attribute chart:data-source-has-labels {
+      "none" | "row" | "column" | "both"
+    }?
+  & dr3d-scene-attlist
+  & common-dr3d-transform-attlist
+  & xml-id?
+chart-wall = element chart:wall { chart-wall-attlist, empty }
+chart-wall-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+chart-floor = element chart:floor { chart-floor-attlist, empty }
+chart-floor-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+chart-axis =
+  element chart:axis {
+    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
+  }
+chart-axis-attlist =
+  attribute chart:dimension { chart-dimension }
+  & attribute chart:name { \string }?
+  & attribute chart:style-name { styleNameRef }?
+chart-dimension = "x" | "y" | "z"
+chart-categories =
+  element chart:categories {
+    attribute table:cell-range-address { cellRangeAddressList }?
+  }
+chart-grid = element chart:grid { chart-grid-attlist }
+chart-grid-attlist =
+  attribute chart:class { "major" | "minor" }?
+  & attribute chart:style-name { styleNameRef }?
+chart-series =
+  element chart:series {
+    chart-series-attlist,
+    chart-domain*,
+    chart-mean-value?,
+    chart-regression-curve*,
+    chart-error-indicator*,
+    chart-data-point*,
+    chart-data-label?
+  }
+chart-series-attlist =
+  attribute chart:values-cell-range-address { cellRangeAddressList }?
+  & attribute chart:label-cell-address { cellRangeAddressList }?
+  & attribute chart:class { namespacedToken }?
+  & attribute chart:attached-axis { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-domain =
+  element chart:domain {
+    attribute table:cell-range-address { cellRangeAddressList }?
+  }
+chart-data-point =
+  element chart:data-point {
+    chart-data-point-attlist, chart-data-label?
+  }
+chart-data-point-attlist =
+  attribute chart:repeated { positiveInteger }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-data-label =
+  element chart:data-label { chart-data-label-attlist, text-p? }
+chart-data-label-attlist =
+  common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-mean-value =
+  element chart:mean-value { chart-mean-value-attlist, empty }
+chart-mean-value-attlist = attribute chart:style-name { styleNameRef }?
+chart-error-indicator =
+  element chart:error-indicator { chart-error-indicator-attlist, empty }
+chart-error-indicator-attlist =
+  attribute chart:style-name { styleNameRef }?
+  & attribute chart:dimension { chart-dimension }
+chart-regression-curve =
+  element chart:regression-curve {
+    chart-regression-curve-attlist, chart-equation?
+  }
+chart-regression-curve-attlist =
+  attribute chart:style-name { styleNameRef }?
+chart-equation =
+  element chart:equation { chart-equation-attlist, text-p? }
+chart-equation-attlist =
+  attribute chart:automatic-content { boolean }?
+  & attribute chart:display-r-square { boolean }?
+  & attribute chart:display-equation { boolean }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-stock-gain-marker =
+  element chart:stock-gain-marker { common-stock-marker-attlist }
+chart-stock-loss-marker =
+  element chart:stock-loss-marker { common-stock-marker-attlist }
+chart-stock-range-line =
+  element chart:stock-range-line { common-stock-marker-attlist }
+common-stock-marker-attlist =
+  attribute chart:style-name { styleNameRef }?
+office-database =
+  element office:database {
+    db-data-source,
+    db-forms?,
+    db-reports?,
+    db-queries?,
+    db-table-presentations?,
+    db-schema-definition?
+  }
+db-data-source =
+  element db:data-source {
+    db-data-source-attlist,
+    db-connection-data,
+    db-driver-settings?,
+    db-application-connection-settings?
+  }
+db-data-source-attlist = empty
+db-connection-data =
+  element db:connection-data {
+    db-connection-data-attlist,
+    (db-database-description | db-connection-resource),
+    db-login?
+  }
+db-connection-data-attlist = empty
+db-database-description =
+  element db:database-description {
+    db-database-description-attlist,
+    (db-file-based-database | db-server-database)
+  }
+db-database-description-attlist = empty
+db-file-based-database =
+  element db:file-based-database { db-file-based-database-attlist }
+db-file-based-database-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute db:media-type { \string }
+  & attribute db:extension { \string }?
+db-server-database =
+  element db:server-database { db-server-database-attlist, empty }
+db-server-database-attlist =
+  attribute db:type { namespacedToken }
+  & (db-host-and-port | db-local-socket-name)
+  & attribute db:database-name { \string }?
+db-host-and-port =
+  attribute db:hostname { \string },
+  attribute db:port { positiveInteger }?
+db-local-socket-name = attribute db:local-socket { \string }?
+db-connection-resource =
+  element db:connection-resource {
+    db-connection-resource-attlist, empty
+  }
+db-connection-resource-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "none" }?,
+  attribute xlink:actuate { "onRequest" }?
+db-login = element db:login { db-login-attlist, empty }
+db-login-attlist =
+  (attribute db:user-name { \string }
+   | attribute db:use-system-user { boolean })?
+  & attribute db:is-password-required { boolean }?
+  & attribute db:login-timeout { positiveInteger }?
+db-driver-settings =
+  element db:driver-settings {
+    db-driver-settings-attlist,
+    db-auto-increment?,
+    db-delimiter?,
+    db-character-set?,
+    db-table-settings?
+  }
+db-driver-settings-attlist =
+  db-show-deleted
+  & attribute db:system-driver-settings { \string }?
+  & attribute db:base-dn { \string }?
+  & db-is-first-row-header-line
+  & attribute db:parameter-name-substitution { boolean }?
+db-show-deleted = attribute db:show-deleted { boolean }?
+db-is-first-row-header-line =
+  attribute db:is-first-row-header-line { boolean }?
+db-auto-increment =
+  element db:auto-increment { db-auto-increment-attlist, empty }
+db-auto-increment-attlist =
+  attribute db:additional-column-statement { \string }?
+  & attribute db:row-retrieving-statement { \string }?
+db-delimiter = element db:delimiter { db-delimiter-attlist, empty }
+db-delimiter-attlist =
+  attribute db:field { \string }?
+  & attribute db:string { \string }?
+  & attribute db:decimal { \string }?
+  & attribute db:thousand { \string }?
+db-character-set =
+  element db:character-set { db-character-set-attlist, empty }
+db-character-set-attlist = attribute db:encoding { textEncoding }?
+db-table-settings = element db:table-settings { db-table-setting* }
+db-table-setting =
+  element db:table-setting {
+    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
+  }
+db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
+db-application-connection-settings =
+  element db:application-connection-settings {
+    db-application-connection-settings-attlist,
+    db-table-filter?,
+    db-table-type-filter?,
+    db-data-source-settings?
+  }
+db-application-connection-settings-attlist =
+  attribute db:is-table-name-length-limited { boolean }?
+  & attribute db:enable-sql92-check { boolean }?
+  & attribute db:append-table-alias-name { boolean }?
+  & attribute db:ignore-driver-privileges { boolean }?
+  & attribute db:boolean-comparison-mode {
+      "equal-integer"
+      | "is-boolean"
+      | "equal-boolean"
+      | "equal-use-only-zero"
+    }?
+  & attribute db:use-catalog { boolean }?
+  & attribute db:max-row-count { integer }?
+  & attribute db:suppress-version-columns { boolean }?
+db-table-filter =
+  element db:table-filter {
+    db-table-filter-attlist,
+    db-table-include-filter?,
+    db-table-exclude-filter?
+  }
+db-table-filter-attlist = empty
+db-table-include-filter =
+  element db:table-include-filter {
+    db-table-include-filter-attlist, db-table-filter-pattern+
+  }
+db-table-include-filter-attlist = empty
+db-table-exclude-filter =
+  element db:table-exclude-filter {
+    db-table-exclude-filter-attlist, db-table-filter-pattern+
+  }
+db-table-exclude-filter-attlist = empty
+db-table-filter-pattern =
+  element db:table-filter-pattern {
+    db-table-filter-pattern-attlist, \string
+  }
+db-table-filter-pattern-attlist = empty
+db-table-type-filter =
+  element db:table-type-filter {
+    db-table-type-filter-attlist, db-table-type*
+  }
+db-table-type-filter-attlist = empty
+db-table-type = element db:table-type { db-table-type-attlist, \string }
+db-table-type-attlist = empty
+db-data-source-settings =
+  element db:data-source-settings {
+    db-data-source-settings-attlist, db-data-source-setting+
+  }
+db-data-source-settings-attlist = empty
+db-data-source-setting =
+  element db:data-source-setting {
+    db-data-source-setting-attlist, db-data-source-setting-value+
+  }
+db-data-source-setting-attlist =
+  attribute db:data-source-setting-is-list { boolean }?
+  & attribute db:data-source-setting-name { \string }
+  & attribute db:data-source-setting-type {
+      db-data-source-setting-types
+    }
+db-data-source-setting-types =
+  "boolean" | "short" | "int" | "long" | "double" | "string"
+db-data-source-setting-value =
+  element db:data-source-setting-value {
+    db-data-source-setting-value-attlist, \string
+  }
+db-data-source-setting-value-attlist = empty
+db-forms =
+  element db:forms {
+    db-forms-attlist, (db-component | db-component-collection)*
+  }
+db-forms-attlist = empty
+db-reports =
+  element db:reports {
+    db-reports-attlist, (db-component | db-component-collection)*
+  }
+db-reports-attlist = empty
+db-component-collection =
+  element db:component-collection {
+    db-component-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-component | db-component-collection)*
+  }
+db-component-collection-attlist = empty
+db-component =
+  element db:component {
+    db-component-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (office-document | math-math)?
+  }
+db-component-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "none" }?,
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute db:as-template { boolean }?
+db-queries =
+  element db:queries {
+    db-queries-attlist, (db-query | db-query-collection)*
+  }
+db-queries-attlist = empty
+db-query-collection =
+  element db:query-collection {
+    db-query-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-query | db-query-collection)*
+  }
+db-query-collection-attlist = empty
+db-query =
+  element db:query {
+    db-query-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?,
+    db-update-table?
+  }
+db-query-attlist =
+  attribute db:command { \string }
+  & attribute db:escape-processing { boolean }?
+db-order-statement =
+  element db:order-statement { db-command, db-apply-command, empty }
+db-filter-statement =
+  element db:filter-statement { db-command, db-apply-command, empty }
+db-update-table =
+  element db:update-table { common-db-table-name-attlist }
+db-table-presentations =
+  element db:table-representations {
+    db-table-presentations-attlist, db-table-presentation*
+  }
+db-table-presentations-attlist = empty
+db-table-presentation =
+  element db:table-representation {
+    db-table-presentation-attlist,
+    common-db-table-name-attlist,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?
+  }
+db-table-presentation-attlist = empty
+db-columns = element db:columns { db-columns-attlist, db-column+ }
+db-columns-attlist = empty
+db-column =
+  element db:column {
+    db-column-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-default-value
+  }
+db-column-attlist =
+  attribute db:visible { boolean }?
+  & attribute db:style-name { styleNameRef }?
+  & attribute db:default-cell-style-name { styleNameRef }?
+db-command = attribute db:command { \string }
+db-apply-command = attribute db:apply-command { boolean }?
+common-db-table-name-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:schema-name { \string }?
+common-db-object-name = attribute db:name { \string }
+common-db-object-title = attribute db:title { \string }?
+common-db-object-description = attribute db:description { \string }?
+common-db-table-style-name =
+  attribute db:style-name { styleNameRef }?
+  & attribute db:default-row-style-name { styleNameRef }?
+common-db-default-value = common-value-and-type-attlist?
+db-schema-definition =
+  element db:schema-definition {
+    db-schema-definition-attlist, db-table-definitions
+  }
+db-schema-definition-attlist = empty
+db-table-definitions =
+  element db:table-definitions {
+    db-table-definitions-attlist, db-table-definition*
+  }
+db-table-definitions-attlist = empty
+db-table-definition =
+  element db:table-definition {
+    common-db-table-name-attlist,
+    db-table-definition-attlist,
+    db-column-definitions,
+    db-keys?,
+    db-indices?
+  }
+db-table-definition-attlist = attribute db:type { \string }?
+db-column-definitions =
+  element db:column-definitions {
+    db-column-definitions-attlist, db-column-definition+
+  }
+db-column-definitions-attlist = empty
+db-column-definition =
+  element db:column-definition {
+    db-column-definition-attlist, common-db-default-value
+  }
+db-column-definition-attlist =
+  attribute db:name { \string }
+  & attribute db:data-type { db-data-types }?
+  & attribute db:type-name { \string }?
+  & attribute db:precision { positiveInteger }?
+  & attribute db:scale { positiveInteger }?
+  & attribute db:is-nullable { "no-nulls" | "nullable" }?
+  & attribute db:is-empty-allowed { boolean }?
+  & attribute db:is-autoincrement { boolean }?
+db-data-types =
+  "bit"
+  | "boolean"
+  | "tinyint"
+  | "smallint"
+  | "integer"
+  | "bigint"
+  | "float"
+  | "real"
+  | "double"
+  | "numeric"
+  | "decimal"
+  | "char"
+  | "varchar"
+  | "longvarchar"
+  | "date"
+  | "time"
+  | "timestmp"
+  | "binary"
+  | "varbinary"
+  | "longvarbinary"
+  | "sqlnull"
+  | "other"
+  | "object"
+  | "distinct"
+  | "struct"
+  | "array"
+  | "blob"
+  | "clob"
+  | "ref"
+db-keys = element db:keys { db-keys-attlist, db-key+ }
+db-keys-attlist = empty
+db-key = element db:key { db-key-attlist, db-key-columns+ }
+db-key-attlist =
+  attribute db:name { \string }?
+  & attribute db:type { "primary" | "unique" | "foreign" }
+  & attribute db:referenced-table-name { \string }?
+  & attribute db:update-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+  & attribute db:delete-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+db-key-columns =
+  element db:key-columns { db-key-columns-attlist, db-key-column+ }
+db-key-columns-attlist = empty
+db-key-column = element db:key-column { db-key-column-attlist, empty }
+db-key-column-attlist =
+  attribute db:name { \string }?
+  & attribute db:related-column-name { \string }?
+db-indices = element db:indices { db-indices-attlist, db-index+ }
+db-indices-attlist = empty
+db-index = element db:index { db-index-attlist, db-index-columns+ }
+db-index-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:is-unique { boolean }?
+  & attribute db:is-clustered { boolean }?
+db-index-columns = element db:index-columns { db-index-column+ }
+db-index-column =
+  element db:index-column { db-index-column-attlist, empty }
+db-index-column-attlist =
+  attribute db:name { \string }
+  & attribute db:is-ascending { boolean }?
+office-forms =
+  element office:forms {
+    office-forms-attlist, (form-form | xforms-model)*
+  }?
+office-forms-attlist =
+  attribute form:automatic-focus { boolean }?
+  & attribute form:apply-design-mode { boolean }?
+form-form =
+  element form:form {
+    common-form-control-attlist,
+    form-form-attlist,
+    form-properties?,
+    office-event-listeners?,
+    (controls | form-form)*,
+    form-connection-resource?
+  }
+form-form-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute office:target-frame { targetFrameName }?
+  & attribute form:method { "get" | "post" | \string }?
+  & attribute form:enctype { \string }?
+  & attribute form:allow-deletes { boolean }?
+  & attribute form:allow-inserts { boolean }?
+  & attribute form:allow-updates { boolean }?
+  & attribute form:apply-filter { boolean }?
+  & attribute form:command-type { "table" | "query" | "command" }?
+  & attribute form:command { \string }?
+  & attribute form:datasource { anyIRI | \string }?
+  & attribute form:master-fields { \string }?
+  & attribute form:detail-fields { \string }?
+  & attribute form:escape-processing { boolean }?
+  & attribute form:filter { \string }?
+  & attribute form:ignore-result { boolean }?
+  & attribute form:navigation-mode { navigation }?
+  & attribute form:order { \string }?
+  & attribute form:tab-cycle { tab-cycles }?
+navigation = "none" | "current" | "parent"
+tab-cycles = "records" | "current" | "page"
+form-connection-resource =
+  element form:connection-resource {
+    attribute xlink:href { anyIRI },
+    empty
+  }
+xforms-model = element xforms:model { anyAttListOrElements }
+column-controls =
+  element form:text { form-text-attlist, common-form-control-content }
+  | element form:textarea {
+      form-textarea-attlist, common-form-control-content, text-p*
+    }
+  | element form:formatted-text {
+      form-formatted-text-attlist, common-form-control-content
+    }
+  | element form:number {
+      form-number-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
+    }
+  | element form:date {
+      form-date-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
+    }
+  | element form:time {
+      form-time-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
+    }
+  | element form:combobox {
+      form-combobox-attlist, common-form-control-content, form-item*
+    }
+  | element form:listbox {
+      form-listbox-attlist, common-form-control-content, form-option*
+    }
+  | element form:checkbox {
+      form-checkbox-attlist, common-form-control-content
+    }
+controls =
+  column-controls
+  | element form:password {
+      form-password-attlist, common-form-control-content
+    }
+  | element form:file { form-file-attlist, common-form-control-content }
+  | element form:fixed-text {
+      form-fixed-text-attlist, common-form-control-content
+    }
+  | element form:button {
+      form-button-attlist, common-form-control-content
+    }
+  | element form:image {
+      form-image-attlist, common-form-control-content
+    }
+  | element form:radio {
+      form-radio-attlist, common-form-control-content
+    }
+  | element form:frame {
+      form-frame-attlist, common-form-control-content
+    }
+  | element form:image-frame {
+      form-image-frame-attlist, common-form-control-content
+    }
+  | element form:hidden {
+      form-hidden-attlist, common-form-control-content
+    }
+  | element form:grid {
+      form-grid-attlist, common-form-control-content, form-column*
+    }
+  | element form:value-range {
+      form-value-range-attlist, common-form-control-content
+    }
+  | element form:generic-control {
+      form-generic-control-attlist, common-form-control-content
+    }
+form-text-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-control-attlist =
+  common-form-control-attlist,
+  common-control-id-attlist,
+  xforms-bind-attlist
+common-form-control-content = form-properties?, office-event-listeners?
+form-textarea-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-password-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-linked-cell
+  & attribute form:echo-char { character }?
+form-file-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-linked-cell
+form-formatted-text-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & common-linked-cell
+  & common-spin-button
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { \string }?
+  & attribute form:min-value { \string }?
+  & attribute form:validation { boolean }?
+common-numeric-control-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist
+form-number-attlist =
+  attribute form:value { double }?
+  & attribute form:current-value { double }?
+  & attribute form:min-value { double }?
+  & attribute form:max-value { double }?
+form-date-attlist =
+  attribute form:value { date }?
+  & attribute form:current-value { date }?
+  & attribute form:min-value { date }?
+  & attribute form:max-value { date }?
+form-time-attlist =
+  attribute form:value { time }?
+  & attribute form:current-value { time }?
+  & attribute form:min-value { time }?
+  & attribute form:max-value { time }?
+form-fixed-text-attlist =
+  form-control-attlist
+  & for
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-title-attlist
+  & attribute form:multi-line { boolean }?
+form-combobox-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & common-source-cell-range
+  & attribute form:auto-complete { boolean }?
+form-item = element form:item { form-item-attlist, text }
+form-item-attlist = label
+form-listbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-printable-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & bound-column
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & list-linkage-type
+  & common-source-cell-range
+  & attribute form:multiple { boolean }?
+  & attribute form:xforms-list-source { \string }?
+list-linkage-type =
+  attribute form:list-linkage-type {
+    "selection" | "selection-indices"
+  }?
+form-option = element form:option { form-option-attlist, text }
+form-option-attlist =
+  current-selected, selected, label, common-value-attlist
+form-button-attlist =
+  form-control-attlist
+  & button-type
+  & common-disabled-attlist
+  & label
+  & image-data
+  & common-printable-attlist
+  & common-tab-attlist
+  & target-frame
+  & target-location
+  & common-title-attlist
+  & common-value-attlist
+  & common-form-relative-image-position-attlist
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:default-button { boolean }?
+  & attribute form:toggle { boolean }?
+  & attribute form:focus-on-click { boolean }?
+  & attribute form:xforms-submission { \string }?
+form-image-attlist =
+  form-control-attlist,
+  button-type,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-tab-attlist,
+  target-frame,
+  target-location,
+  common-title-attlist,
+  common-value-attlist
+form-checkbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-data-field-attlist
+  & common-form-visual-effect-attlist
+  & common-form-relative-image-position-attlist
+  & common-linked-cell
+  & attribute form:current-state { states }?
+  & attribute form:is-tristate { boolean }?
+  & attribute form:state { states }?
+states = "unchecked" | "checked" | "unknown"
+form-radio-attlist =
+  form-control-attlist,
+  current-selected,
+  common-disabled-attlist,
+  label,
+  common-printable-attlist,
+  selected,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-data-field-attlist,
+  common-form-visual-effect-attlist,
+  common-form-relative-image-position-attlist,
+  common-linked-cell
+form-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  for,
+  label,
+  common-printable-attlist,
+  common-title-attlist
+form-image-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-title-attlist,
+  common-data-field-attlist
+form-hidden-attlist = form-control-attlist, common-value-attlist
+form-grid-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-printable-attlist,
+  common-tab-attlist,
+  common-title-attlist
+form-column =
+  element form:column { form-column-attlist, column-controls+ }
+form-column-attlist =
+  common-form-control-attlist, label, text-style-name
+text-style-name = attribute form:text-style-name { styleNameRef }?
+form-value-range-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-linked-cell
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { integer }?
+  & attribute form:min-value { integer }?
+  & attribute form:step-size { positiveInteger }?
+  & attribute form:page-step-size { positiveInteger }?
+  & attribute form:orientation { "horizontal" | "vertical" }?
+form-generic-control-attlist = form-control-attlist
+common-form-control-attlist =
+  attribute form:name { \string }?
+  & attribute form:control-implementation { namespacedToken }?
+xforms-bind-attlist = attribute xforms:bind { \string }?
+types = "submit" | "reset" | "push" | "url"
+button-type = attribute form:button-type { types }?
+common-control-id-attlist =
+  xml-id,
+  attribute form:id { NCName }?
+current-selected = attribute form:current-selected { boolean }?
+common-value-attlist = attribute form:value { \string }?
+common-current-value-attlist = attribute form:current-value { \string }?
+common-disabled-attlist = attribute form:disabled { boolean }?
+dropdown = attribute form:dropdown { boolean }?
+for = attribute form:for { \string }?
+image-data = attribute form:image-data { anyIRI }?
+label = attribute form:label { \string }?
+common-maxlength-attlist =
+  attribute form:max-length { nonNegativeInteger }?
+common-printable-attlist = attribute form:printable { boolean }?
+common-readonly-attlist = attribute form:readonly { boolean }?
+selected = attribute form:selected { boolean }?
+size = attribute form:size { nonNegativeInteger }?
+common-tab-attlist =
+  attribute form:tab-index { nonNegativeInteger }?
+  & attribute form:tab-stop { boolean }?
+target-frame = attribute office:target-frame { targetFrameName }?
+target-location = attribute xlink:href { anyIRI }?
+common-title-attlist = attribute form:title { \string }?
+common-form-visual-effect-attlist =
+  attribute form:visual-effect { "flat" | "3d" }?
+common-form-relative-image-position-attlist =
+  attribute form:image-position { "center" }?
+  | (attribute form:image-position {
+       "start" | "end" | "top" | "bottom"
+     },
+     attribute form:image-align { "start" | "center" | "end" }?)
+bound-column = attribute form:bound-column { \string }?
+common-convert-empty-attlist =
+  attribute form:convert-empty-to-null { boolean }?
+common-data-field-attlist = attribute form:data-field { \string }?
+list-source = attribute form:list-source { \string }?
+list-source-type =
+  attribute form:list-source-type {
+    "table"
+    | "query"
+    | "sql"
+    | "sql-pass-through"
+    | "value-list"
+    | "table-fields"
+  }?
+common-linked-cell =
+  attribute form:linked-cell { cellAddress | \string }?
+common-source-cell-range =
+  attribute form:source-cell-range { cellRangeAddress | \string }?
+common-spin-button = attribute form:spin-button { boolean }?
+common-repeat = attribute form:repeat { boolean }?
+common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
+form-properties = element form:properties { form-property+ }
+form-property =
+  element form:property {
+    form-property-name, form-property-value-and-type-attlist
+  }
+  | element form:list-property {
+      form-property-name, form-property-type-and-value-list
+    }
+form-property-name = attribute form:property-name { \string }
+form-property-value-and-type-attlist =
+  common-value-and-type-attlist
+  | attribute office:value-type { "void" }
+form-property-type-and-value-list =
+  (attribute office:value-type { "float" },
+   element form:list-value {
+     attribute office:value { double }
+   }*)
+  | (attribute office:value-type { "percentage" },
+     element form:list-value {
+       attribute office:value { double }
+     }*)
+  | (attribute office:value-type { "currency" },
+     element form:list-value {
+       attribute office:value { double },
+       attribute office:currency { \string }?
+     }*)
+  | (attribute office:value-type { "date" },
+     element form:list-value {
+       attribute office:date-value { dateOrDateTime }
+     }*)
+  | (attribute office:value-type { "time" },
+     element form:list-value {
+       attribute office:time-value { duration }
+     }*)
+  | (attribute office:value-type { "boolean" },
+     element form:list-value {
+       attribute office:boolean-value { boolean }
+     }*)
+  | (attribute office:value-type { "string" },
+     element form:list-value {
+       attribute office:string-value { \string }
+     }*)
+  | attribute office:value-type { "void" }
+office-annotation =
+  element office:annotation {
+    office-annotation-attlist,
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    dc-creator?,
+    dc-date?,
+    meta-date-string?,
+    (text-p | text-list)*
+  }
+office-annotation-end =
+  element office:annotation-end { office-annotation-end-attlist }
+office-annotation-attlist =
+  attribute office:display { boolean }?
+  & common-office-annotation-name-attlist?
+office-annotation-end-attlist = common-office-annotation-name-attlist
+common-office-annotation-name-attlist =
+  attribute office:name { \string }
+meta-date-string = element meta:date-string { \string }
+common-num-format-prefix-suffix-attlist =
+  attribute style:num-prefix { \string }?,
+  attribute style:num-suffix { \string }?
+common-num-format-attlist =
+  attribute style:num-format { "1" | "i" | "I" | \string | empty }
+  | (attribute style:num-format { "a" | "A" },
+     style-num-letter-sync-attlist)
+  | empty
+style-num-letter-sync-attlist =
+  attribute style:num-letter-sync { boolean }?
+office-change-info =
+  element office:change-info { dc-creator, dc-date, text-p* }
+office-event-listeners =
+  element office:event-listeners {
+    (script-event-listener | presentation-event-listener)*
+  }
+script-event-listener =
+  element script:event-listener { script-event-listener-attlist, empty }
+script-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute script:language { \string }
+  & (attribute script:macro-name { \string }
+     | (attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI },
+        attribute xlink:actuate { "onRequest" }?))
+math-math = element math:math { mathMarkup }
+[
+  dc:description [
+    "To avoid inclusion of the complete MathML schema, anything is allowed 
within a math:math top-level element"
+  ]
+]
+mathMarkup =
+  (attribute * { text }
+   | text
+   | element * { mathMarkup })*
+text-dde-connection-decl =
+  element text:dde-connection-decl {
+    text-dde-connection-decl-attlist, common-dde-connection-decl-attlist
+  }
+text-dde-connection-decl-attlist = attribute office:name { \string }
+common-dde-connection-decl-attlist =
+  attribute office:dde-application { \string }
+  & attribute office:dde-topic { \string }
+  & attribute office:dde-item { \string }
+  & attribute office:automatic-update { boolean }?
+table-dde-link =
+  element table:dde-link { office-dde-source, table-table }
+office-dde-source =
+  element office:dde-source {
+    office-dde-source-attlist, common-dde-connection-decl-attlist
+  }
+office-dde-source-attlist =
+  attribute office:name { \string }?
+  & attribute office:conversion-mode {
+      "into-default-style-data-style"
+      | "into-english-number"
+      | "keep-text"
+    }?
+animation-element =
+  element anim:animate {
+    common-anim-target-attlist,
+    common-anim-named-target-attlist,
+    common-anim-values-attlist,
+    common-anim-spline-mode-attlist,
+    common-spline-anim-value-attlist,
+    common-timing-attlist,
+    common-anim-add-accum-attlist
+  }
+  | element anim:set {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-set-values-attlist,
+      common-timing-attlist,
+      common-anim-add-accum-attlist
+    }
+  | element anim:animateMotion {
+      anim-animate-motion-attlist,
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-timing-attlist,
+      common-spline-anim-value-attlist
+    }
+  | element anim:animateColor {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      common-spline-anim-value-attlist,
+      anim-animate-color-attlist,
+      common-timing-attlist
+    }
+  | element anim:animateTransform {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      anim-animate-transform-attlist,
+      common-timing-attlist
+    }
+  | element anim:transitionFilter {
+      common-anim-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      anim-transition-filter-attlist,
+      common-timing-attlist
+    }
+  | element anim:par {
+      common-anim-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
+    }
+  | element anim:seq {
+      common-anim-attlist,
+      common-endsync-timing-attlist,
+      common-timing-attlist,
+      animation-element*
+    }
+  | element anim:iterate {
+      common-anim-attlist,
+      anim-iterate-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
+    }
+  | element anim:audio {
+      common-anim-attlist,
+      anim-audio-attlist,
+      common-basic-timing-attlist
+    }
+  | element anim:command {
+      common-anim-attlist,
+      anim-command-attlist,
+      common-begin-end-timing-attlist,
+      common-anim-target-attlist,
+      element anim:param {
+        attribute anim:name { \string },
+        attribute anim:value { \string }
+      }*
+    }
+anim-animate-motion-attlist =
+  attribute svg:path { pathData }?
+  & attribute svg:origin { \string }?
+  & attribute smil:calcMode {
+      "discrete" | "linear" | "paced" | "spline"
+    }?
+anim-animate-color-attlist =
+  attribute anim:color-interpolation { "rgb" | "hsl" }?
+  & attribute anim:color-interpolation-direction {
+      "clockwise" | "counter-clockwise"
+    }?
+anim-animate-transform-attlist =
+  attribute svg:type {
+    "translate" | "scale" | "rotate" | "skewX" | "skewY"
+  }
+anim-transition-filter-attlist =
+  attribute smil:type { \string }
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute smil:mode { "in" | "out" }?
+common-anim-target-attlist =
+  attribute smil:targetElement { IDREF }?
+  & attribute anim:sub-item { \string }?
+common-anim-named-target-attlist =
+  attribute smil:attributeName { \string }
+common-anim-values-attlist =
+  attribute smil:values { \string }?
+  & attribute anim:formula { \string }?
+  & common-anim-set-values-attlist
+  & attribute smil:from { \string }?
+  & attribute smil:by { \string }?
+common-anim-spline-mode-attlist =
+  attribute smil:calcMode {
+    "discrete" | "linear" | "paced" | "spline"
+  }?
+common-spline-anim-value-attlist =
+  attribute smil:keyTimes { \string }?
+  & attribute smil:keySplines { \string }?
+common-anim-add-accum-attlist =
+  attribute smil:accumulate { "none" | "sum" }?
+  & attribute smil:additive { "replace" | "sum" }?
+common-anim-set-values-attlist = attribute smil:to { \string }?
+common-begin-end-timing-attlist =
+  attribute smil:begin { \string }?
+  & attribute smil:end { \string }?
+common-dur-timing-attlist = attribute smil:dur { \string }?
+common-endsync-timing-attlist =
+  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
+common-repeat-timing-attlist =
+  attribute smil:repeatDur { \string }?,
+  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
+nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
+common-fill-timing-attlist =
+  attribute smil:fill {
+    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
+  }?
+common-fill-default-attlist =
+  attribute smil:fillDefault {
+    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
+  }?
+common-restart-timing-attlist =
+  attribute smil:restart {
+    "never" | "always" | "whenNotActive" | "default"
+  }?
+common-restart-default-attlist =
+  attribute smil:restartDefault {
+    "never" | "always" | "whenNotActive" | "inherit"
+  }?
+common-time-manip-attlist =
+  attribute smil:accelerate { zeroToOneDecimal }?
+  & attribute smil:decelerate { zeroToOneDecimal }?
+  & attribute smil:autoReverse { boolean }?
+zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
+common-basic-timing-attlist =
+  common-begin-end-timing-attlist,
+  common-dur-timing-attlist,
+  common-repeat-timing-attlist,
+  common-restart-timing-attlist,
+  common-restart-default-attlist,
+  common-fill-timing-attlist,
+  common-fill-default-attlist
+common-timing-attlist =
+  common-basic-timing-attlist, common-time-manip-attlist
+anim-iterate-attlist =
+  common-anim-target-attlist
+  & attribute anim:iterate-type { \string }?
+  & attribute anim:iterate-interval { duration }?
+anim-audio-attlist =
+  attribute xlink:href { anyIRI }?
+  & attribute anim:audio-level { double }?
+anim-command-attlist = attribute anim:command { \string }
+style-style =
+  element style:style {
+    style-style-attlist, style-style-content, style-map*
+  }
+common-in-content-meta-attlist =
+  attribute xhtml:about { URIorSafeCURIE },
+  attribute xhtml:property { CURIEs },
+  common-meta-literal-attlist
+common-meta-literal-attlist =
+  attribute xhtml:datatype { CURIE }?,
+  attribute xhtml:content { \string }?
+xml-id = attribute xml:id { ID }
+style-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:parent-style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+  & attribute style:list-level { positiveInteger | empty }?
+  & attribute style:list-style-name { styleName | empty }?
+  & attribute style:master-page-name { styleNameRef }?
+  & attribute style:auto-update { boolean }?
+  & attribute style:data-style-name { styleNameRef }?
+  & attribute style:percentage-data-style-name { styleNameRef }?
+  & attribute style:class { \string }?
+  & attribute style:default-outline-level { positiveInteger | empty }?
+style-map = element style:map { style-map-attlist, empty }
+style-map-attlist =
+  attribute style:condition { \string }
+  & attribute style:apply-style-name { styleNameRef }
+  & attribute style:base-cell-address { cellAddress }?
+style-default-style =
+  element style:default-style { style-style-content }
+style-page-layout =
+  element style:page-layout {
+    style-page-layout-attlist, style-page-layout-content
+  }
+style-page-layout-content =
+  style-page-layout-properties?,
+  style-header-style?,
+  style-footer-style?
+style-page-layout-attlist =
+  attribute style:name { styleName }
+  & attribute style:page-usage {
+      "all" | "left" | "right" | "mirrored"
+    }?
+style-header-style =
+  element style:header-style { style-header-footer-properties? }
+style-footer-style =
+  element style:footer-style { style-header-footer-properties? }
+style-default-page-layout =
+  element style:default-page-layout { style-page-layout-content }
+style-master-page =
+  element style:master-page {
+    style-master-page-attlist,
+    (style-header, style-header-left?)?,
+    (style-footer, style-footer-left?)?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    animation-element?,
+    presentation-notes?
+  }
+style-master-page-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+style-header =
+  element style:header {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-footer =
+  element style:footer {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-left =
+  element style:header-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-footer-left =
+  element style:footer-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+header-footer-content =
+  (text-tracked-changes,
+   text-decls,
+   (text-h
+    | text-p
+    | text-list
+    | table-table
+    | text-section
+    | text-table-of-content
+    | text-illustration-index
+    | text-table-index
+    | text-object-index
+    | text-user-index
+    | text-alphabetical-index
+    | text-bibliography
+    | text-index-title
+    | change-marks)*)
+  | (style-region-left?, style-region-center?, style-region-right?)
+common-style-header-footer-attlist =
+  attribute style:display { boolean }?
+style-region-left = element style:region-left { region-content }
+style-region-center = element style:region-center { region-content }
+style-region-right = element style:region-right { region-content }
+region-content = text-p*
+presentation-notes =
+  element presentation:notes {
+    common-presentation-header-footer-attlist,
+    presentation-notes-attlist,
+    office-forms,
+    shape*
+  }
+presentation-notes-attlist =
+  attribute style:page-layout-name { styleNameRef }?
+  & attribute draw:style-name { styleNameRef }?
+table-table-template =
+  element table:table-template {
+    table-table-template-attlist,
+    table-first-row?,
+    table-last-row?,
+    table-first-column?,
+    table-last-column?,
+    table-body,
+    table-even-rows?,
+    table-odd-rows?,
+    table-even-columns?,
+    table-odd-columns?,
+    table-background?
+  }
+table-table-template-attlist =
+  attribute table:name { \string }
+  & attribute table:first-row-start-column { rowOrCol }
+  & attribute table:first-row-end-column { rowOrCol }
+  & attribute table:last-row-start-column { rowOrCol }
+  & attribute table:last-row-end-column { rowOrCol }
+rowOrCol = "row" | "column"
+table-first-row =
+  element table:first-row { common-table-template-attlist, empty }
+table-last-row =
+  element table:last-row { common-table-template-attlist, empty }
+table-first-column =
+  element table:first-column { common-table-template-attlist, empty }
+table-last-column =
+  element table:last-column { common-table-template-attlist, empty }
+table-body = element table:body { common-table-template-attlist, empty }
+table-even-rows =
+  element table:even-rows { common-table-template-attlist, empty }
+table-odd-rows =
+  element table:odd-rows { common-table-template-attlist, empty }
+table-even-columns =
+  element table:even-columns { common-table-template-attlist, empty }
+table-odd-columns =
+  element table:odd-columns { common-table-template-attlist, empty }
+common-table-template-attlist =
+  attribute table:style-name { styleNameRef },
+  attribute table:paragraph-style-name { styleNameRef }?
+table-background =
+  element table:background { table-background-attlist, empty }
+table-background-attlist = attribute table:style-name { styleNameRef }
+style-font-face =
+  element style:font-face {
+    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
+  }
+style-font-face-attlist =
+  attribute svg:font-family { \string }?
+  & attribute svg:font-style { fontStyle }?
+  & attribute svg:font-variant { fontVariant }?
+  & attribute svg:font-weight { fontWeight }?
+  & attribute svg:font-stretch {
+      "normal"
+      | "ultra-condensed"
+      | "extra-condensed"
+      | "condensed"
+      | "semi-condensed"
+      | "semi-expanded"
+      | "expanded"
+      | "extra-expanded"
+      | "ultra-expanded"
+    }?
+  & attribute svg:font-size { positiveLength }?
+  & attribute svg:unicode-range { \string }?
+  & attribute svg:units-per-em { integer }?
+  & attribute svg:panose-1 { \string }?
+  & attribute svg:stemv { integer }?
+  & attribute svg:stemh { integer }?
+  & attribute svg:slope { integer }?
+  & attribute svg:cap-height { integer }?
+  & attribute svg:x-height { integer }?
+  & attribute svg:accent-height { integer }?
+  & attribute svg:ascent { integer }?
+  & attribute svg:descent { integer }?
+  & attribute svg:widths { \string }?
+  & attribute svg:bbox { \string }?
+  & attribute svg:ideographic { integer }?
+  & attribute svg:alphabetic { integer }?
+  & attribute svg:mathematical { integer }?
+  & attribute svg:hanging { integer }?
+  & attribute svg:v-ideographic { integer }?
+  & attribute svg:v-alphabetic { integer }?
+  & attribute svg:v-mathematical { integer }?
+  & attribute svg:v-hanging { integer }?
+  & attribute svg:underline-position { integer }?
+  & attribute svg:underline-thickness { integer }?
+  & attribute svg:strikethrough-position { integer }?
+  & attribute svg:strikethrough-thickness { integer }?
+  & attribute svg:overline-position { integer }?
+  & attribute svg:overline-thickness { integer }?
+  & attribute style:name { \string }
+  & attribute style:font-adornments { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+svg-font-face-src =
+  element svg:font-face-src {
+    (svg-font-face-uri | svg-font-face-name)+
+  }
+svg-font-face-uri =
+  element svg:font-face-uri {
+    common-svg-font-face-xlink-attlist, svg-font-face-format*
+  }
+svg-font-face-format =
+  element svg:font-face-format {
+    attribute svg:string { \string }?,
+    empty
+  }
+svg-font-face-name =
+  element svg:font-face-name {
+    attribute svg:name { \string }?,
+    empty
+  }
+svg-definition-src =
+  element svg:definition-src {
+    common-svg-font-face-xlink-attlist, empty
+  }
+common-svg-font-face-xlink-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:actuate { "onRequest" }?
+number-number-style =
+  element number:number-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text?,
+    (any-number, number-text?)?,
+    style-map*
+  }
+any-number = number-number | number-scientific-number | number-fraction
+number-number =
+  element number:number {
+    number-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    number-embedded-text*
+  }
+number-number-attlist =
+  attribute number:decimal-replacement { \string }?
+  & attribute number:display-factor { double }?
+number-embedded-text =
+  element number:embedded-text { number-embedded-text-attlist, text }
+number-embedded-text-attlist = attribute number:position { integer }
+number-scientific-number =
+  element number:scientific-number {
+    number-scientific-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    empty
+  }
+number-scientific-number-attlist =
+  attribute number:min-exponent-digits { integer }?
+number-fraction =
+  element number:fraction {
+    number-fraction-attlist, common-number-attlist, empty
+  }
+number-fraction-attlist =
+  attribute number:min-numerator-digits { integer }?
+  & attribute number:min-denominator-digits { integer }?
+  & attribute number:denominator-value { integer }?
+number-currency-style =
+  element number:currency-style {
+    common-data-style-attlist,
+    common-auto-reorder-attlist,
+    style-text-properties?,
+    number-text?,
+    ((number-and-text, currency-symbol-and-text?)
+     | (currency-symbol-and-text, number-and-text?))?,
+    style-map*
+  }
+currency-symbol-and-text = number-currency-symbol, number-text?
+number-and-text = number-number, number-text?
+number-currency-symbol =
+  element number:currency-symbol {
+    number-currency-symbol-attlist, text
+  }
+number-currency-symbol-attlist =
+  attribute number:language { languageCode }?,
+  attribute number:country { countryCode }?,
+  attribute number:script { scriptCode }?,
+  attribute number:rfc-language-tag { language }?
+number-percentage-style =
+  element number:percentage-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text?,
+    number-and-text?,
+    style-map*
+  }
+number-date-style =
+  element number:date-style {
+    common-data-style-attlist,
+    common-auto-reorder-attlist,
+    common-format-source-attlist,
+    style-text-properties?,
+    number-text?,
+    (any-date, number-text?)+,
+    style-map*
+  }
+any-date =
+  number-day
+  | number-month
+  | number-year
+  | number-era
+  | number-day-of-week
+  | number-week-of-year
+  | number-quarter
+  | number-hours
+  | number-am-pm
+  | number-minutes
+  | number-seconds
+number-day =
+  element number:day {
+    number-day-attlist, common-calendar-attlist, empty
+  }
+number-day-attlist = attribute number:style { "short" | "long" }?
+number-month =
+  element number:month {
+    number-month-attlist, common-calendar-attlist, empty
+  }
+number-month-attlist =
+  attribute number:textual { boolean }?
+  & attribute number:possessive-form { boolean }?
+  & attribute number:style { "short" | "long" }?
+number-year =
+  element number:year {
+    number-year-attlist, common-calendar-attlist, empty
+  }
+number-year-attlist = attribute number:style { "short" | "long" }?
+number-era =
+  element number:era {
+    number-era-attlist, common-calendar-attlist, empty
+  }
+number-era-attlist = attribute number:style { "short" | "long" }?
+number-day-of-week =
+  element number:day-of-week {
+    number-day-of-week-attlist, common-calendar-attlist, empty
+  }
+number-day-of-week-attlist =
+  attribute number:style { "short" | "long" }?
+number-week-of-year =
+  element number:week-of-year { common-calendar-attlist, empty }
+number-quarter =
+  element number:quarter {
+    number-quarter-attlist, common-calendar-attlist, empty
+  }
+number-quarter-attlist = attribute number:style { "short" | "long" }?
+number-time-style =
+  element number:time-style {
+    number-time-style-attlist,
+    common-data-style-attlist,
+    common-format-source-attlist,
+    style-text-properties?,
+    number-text?,
+    (any-time, number-text?)+,
+    style-map*
+  }
+any-time = number-hours | number-am-pm | number-minutes | number-seconds
+number-time-style-attlist =
+  attribute number:truncate-on-overflow { boolean }?
+number-hours = element number:hours { number-hours-attlist, empty }
+number-hours-attlist = attribute number:style { "short" | "long" }?
+number-minutes =
+  element number:minutes { number-minutes-attlist, empty }
+number-minutes-attlist = attribute number:style { "short" | "long" }?
+number-seconds =
+  element number:seconds { number-seconds-attlist, empty }
+number-seconds-attlist =
+  attribute number:style { "short" | "long" }?
+  & attribute number:decimal-places { integer }?
+number-am-pm = element number:am-pm { empty }
+number-boolean-style =
+  element number:boolean-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text?,
+    (number-boolean, number-text?)?,
+    style-map*
+  }
+number-boolean = element number:boolean { empty }
+number-text-style =
+  element number:text-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text?,
+    (number-text-content, number-text?)*,
+    style-map*
+  }
+number-text = element number:text { text }
+number-text-content = element number:text-content { empty }
+common-data-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute number:language { languageCode }?
+  & attribute number:country { countryCode }?
+  & attribute number:script { scriptCode }?
+  & attribute number:rfc-language-tag { language }?
+  & attribute number:title { \string }?
+  & attribute style:volatile { boolean }?
+  & attribute number:transliteration-format { \string }?
+  & attribute number:transliteration-language { countryCode }?
+  & attribute number:transliteration-country { countryCode }?
+  & attribute number:transliteration-style {
+      "short" | "medium" | "long"
+    }?
+common-auto-reorder-attlist =
+  attribute number:automatic-order { boolean }?
+common-format-source-attlist =
+  attribute number:format-source { "fixed" | "language" }?
+common-decimal-places-attlist =
+  attribute number:decimal-places { integer }?
+common-number-attlist =
+  attribute number:min-integer-digits { integer }?
+  & attribute number:grouping { boolean }?
+common-calendar-attlist =
+  attribute number:calendar {
+    "gregorian"
+    | "gengou"
+    | "ROC"
+    | "hanja_yoil"
+    | "hanja"
+    | "hijri"
+    | "jewish"
+    | "buddhist"
+    | \string
+  }?
+style-style-content =
+  (attribute style:family { "text" },
+   style-text-properties?)
+  | (attribute style:family { "paragraph" },
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "section" },
+     style-section-properties?)
+  | (attribute style:family { "ruby" },
+     style-ruby-properties?)
+  | (attribute style:family { "table" },
+     style-table-properties?)
+  | (attribute style:family { "table-column" },
+     style-table-column-properties?)
+  | (attribute style:family { "table-row" },
+     style-table-row-properties?)
+  | (attribute style:family { "table-cell" },
+     style-table-cell-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "graphic" | "presentation" },
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "drawing-page" },
+     style-drawing-page-properties?)
+  | (attribute style:family { "chart" },
+     style-chart-properties?,
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+text-linenumbering-configuration =
+  element text:linenumbering-configuration {
+    text-linenumbering-configuration-attlist,
+    text-linenumbering-separator?
+  }
+text-linenumbering-configuration-attlist =
+  attribute text:number-lines { boolean }?
+  & common-num-format-attlist?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:increment { nonNegativeInteger }?
+  & attribute text:number-position {
+      "left" | "right" | "inner" | "outer"
+    }?
+  & attribute text:offset { nonNegativeLength }?
+  & attribute text:count-empty-lines { boolean }?
+  & attribute text:count-in-text-boxes { boolean }?
+  & attribute text:restart-on-page { boolean }?
+text-linenumbering-separator =
+  element text:linenumbering-separator {
+    attribute text:increment { nonNegativeInteger }?,
+    text
+  }
+text-notes-configuration =
+  element text:notes-configuration { text-notes-configuration-content }
+text-notes-configuration-content =
+  text-note-class
+  & attribute text:citation-style-name { styleNameRef }?
+  & attribute text:citation-body-style-name { styleNameRef }?
+  & attribute text:default-style-name { styleNameRef }?
+  & attribute text:master-page-name { styleNameRef }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & common-num-format-prefix-suffix-attlist
+  & common-num-format-attlist?
+  & attribute text:start-numbering-at {
+      "document" | "chapter" | "page"
+    }?
+  & attribute text:footnotes-position {
+      "text" | "page" | "section" | "document"
+    }?
+  & element text:note-continuation-notice-forward { text }?
+  & element text:note-continuation-notice-backward { text }?
+text-bibliography-configuration =
+  element text:bibliography-configuration {
+    text-bibliography-configuration-attlist, text-sort-key*
+  }
+text-bibliography-configuration-attlist =
+  attribute text:prefix { \string }?
+  & attribute text:suffix { \string }?
+  & attribute text:numbered-entries { boolean }?
+  & attribute text:sort-by-position { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-sort-key = element text:sort-key { text-sort-key-attlist, empty }
+text-sort-key-attlist =
+  attribute text:key {
+    "address"
+    | "annote"
+    | "author"
+    | "bibliography-type"
+    | "booktitle"
+    | "chapter"
+    | "custom1"
+    | "custom2"
+    | "custom3"
+    | "custom4"
+    | "custom5"
+    | "edition"
+    | "editor"
+    | "howpublished"
+    | "identifier"
+    | "institution"
+    | "isbn"
+    | "issn"
+    | "journal"
+    | "month"
+    | "note"
+    | "number"
+    | "organizations"
+    | "pages"
+    | "publisher"
+    | "report-type"
+    | "school"
+    | "series"
+    | "title"
+    | "url"
+    | "volume"
+    | "year"
+  },
+  attribute text:sort-ascending { boolean }?
+text-list-style =
+  element text:list-style {
+    text-list-style-attr, text-list-style-content*
+  }
+text-list-style-attr =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute text:consecutive-numbering { boolean }?
+text-list-style-content =
+  element text:list-level-style-number {
+    text-list-level-style-attr,
+    text-list-level-style-number-attr,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+  | element text:list-level-style-bullet {
+      text-list-level-style-attr,
+      text-list-level-style-bullet-attr,
+      style-list-level-properties?,
+      style-text-properties?
+    }
+  | element text:list-level-style-image {
+      text-list-level-style-attr,
+      text-list-level-style-image-attr,
+      style-list-level-properties?
+    }
+text-list-level-style-number-attr =
+  attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+text-list-level-style-bullet-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bullet-char { character }
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:bullet-relative-size { percent }?
+text-list-level-style-image-attr =
+  common-draw-data-attlist | office-binary-data
+text-list-level-style-attr = attribute text:level { positiveInteger }
+text-outline-style =
+  element text:outline-style {
+    text-outline-style-attr, text-outline-level-style+
+  }
+text-outline-style-attr = attribute style:name { styleName }
+text-outline-level-style =
+  element text:outline-level-style {
+    text-outline-level-style-attlist,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+text-outline-level-style-attlist =
+  attribute text:level { positiveInteger }
+  & attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+style-graphic-properties =
+  element style:graphic-properties {
+    style-graphic-properties-content-strict
+  }
+style-graphic-properties-content-strict =
+  style-graphic-properties-attlist,
+  style-graphic-fill-properties-attlist,
+  style-graphic-properties-elements
+style-drawing-page-properties =
+  element style:drawing-page-properties {
+    style-drawing-page-properties-content-strict
+  }
+style-drawing-page-properties-content-strict =
+  style-graphic-fill-properties-attlist,
+  style-drawing-page-properties-attlist,
+  style-drawing-page-properties-elements
+draw-gradient =
+  element draw:gradient {
+    common-draw-gradient-attlist, draw-gradient-attlist, empty
+  }
+common-draw-gradient-attlist =
+  attribute draw:name { styleName }?
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { gradient-style }
+  & attribute draw:cx { percent }?
+  & attribute draw:cy { percent }?
+  & attribute draw:angle { angle }?
+  & attribute draw:border { percent }?
+gradient-style =
+  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
+draw-gradient-attlist =
+  attribute draw:start-color { color }?
+  & attribute draw:end-color { color }?
+  & attribute draw:start-intensity { zeroToHundredPercent }?
+  & attribute draw:end-intensity { zeroToHundredPercent }?
+svg-linearGradient =
+  element svg:linearGradient {
+    common-svg-gradient-attlist,
+    attribute svg:x1 { coordinate | percent }?,
+    attribute svg:y1 { coordinate | percent }?,
+    attribute svg:x2 { coordinate | percent }?,
+    attribute svg:y2 { coordinate | percent }?,
+    svg-stop*
+  }
+svg-radialGradient =
+  element svg:radialGradient {
+    common-svg-gradient-attlist,
+    attribute svg:cx { coordinate | percent }?,
+    attribute svg:cy { coordinate | percent }?,
+    attribute svg:r { coordinate | percent }?,
+    attribute svg:fx { coordinate | percent }?,
+    attribute svg:fy { coordinate | percent }?,
+    svg-stop*
+  }
+svg-stop =
+  element svg:stop {
+    attribute svg:offset { double | percent },
+    attribute svg:stop-color { color }?,
+    attribute svg:stop-opacity { double }?
+  }
+common-svg-gradient-attlist =
+  attribute svg:gradientUnits { "objectBoundingBox" }?
+  & attribute svg:gradientTransform { \string }?
+  & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }?
+  & attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+draw-hatch = element draw:hatch { draw-hatch-attlist, empty }
+draw-hatch-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "single" | "double" | "triple" }
+  & attribute draw:color { color }?
+  & attribute draw:distance { length }?
+  & attribute draw:rotation { angle }?
+draw-fill-image =
+  element draw:fill-image {
+    draw-fill-image-attlist,
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI },
+    attribute xlink:show { "embed" }?,
+    attribute xlink:actuate { "onLoad" }?,
+    empty
+  }
+draw-fill-image-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute svg:width { length }?
+  & attribute svg:height { length }?
+draw-opacity =
+  element draw:opacity {
+    common-draw-gradient-attlist, draw-opacity-attlist, empty
+  }
+draw-opacity-attlist =
+  attribute draw:start { zeroToHundredPercent }?,
+  attribute draw:end { zeroToHundredPercent }?
+draw-marker =
+  element draw:marker {
+    draw-marker-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    empty
+  }
+draw-marker-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+draw-stroke-dash =
+  element draw:stroke-dash { draw-stroke-dash-attlist, empty }
+draw-stroke-dash-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "rect" | "round" }?
+  & attribute draw:dots1 { integer }?
+  & attribute draw:dots1-length { length | percent }?
+  & attribute draw:dots2 { integer }?
+  & attribute draw:dots2-length { length | percent }?
+  & attribute draw:distance { length | percent }?
+style-presentation-page-layout =
+  element style:presentation-page-layout {
+    attribute style:name { styleName },
+    attribute style:display-name { \string }?,
+    presentation-placeholder*
+  }
+presentation-placeholder =
+  element presentation:placeholder {
+    attribute presentation:object { presentation-classes },
+    attribute svg:x { coordinate | percent },
+    attribute svg:y { coordinate | percent },
+    attribute svg:width { length | percent },
+    attribute svg:height { length | percent },
+    empty
+  }
+style-page-layout-properties =
+  element style:page-layout-properties {
+    style-page-layout-properties-content-strict
+  }
+style-page-layout-properties-content-strict =
+  style-page-layout-properties-attlist,
+  style-page-layout-properties-elements
+style-page-layout-properties-attlist =
+  attribute fo:page-width { length }?
+  & attribute fo:page-height { length }?
+  & common-num-format-attlist?
+  & common-num-format-prefix-suffix-attlist
+  & attribute style:paper-tray-name { "default" | \string }?
+  & attribute style:print-orientation { "portrait" | "landscape" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & attribute style:register-truth-ref-style-name { styleNameRef }?
+  & attribute style:print {
+      list {
+        ("headers"
+         | "grid"
+         | "annotations"
+         | "objects"
+         | "charts"
+         | "drawings"
+         | "formulas"
+         | "zero-values")*
+      }
+    }?
+  & attribute style:print-page-order { "ttb" | "ltr" }?
+  & attribute style:first-page-number { positiveInteger | "continue" }?
+  & attribute style:scale-to { percent }?
+  & attribute style:scale-to-pages { positiveInteger }?
+  & attribute style:table-centering {
+      "horizontal" | "vertical" | "both" | "none"
+    }?
+  & attribute style:footnote-max-height { length }?
+  & common-writing-mode-attlist
+  & attribute style:layout-grid-mode { "none" | "line" | "both" }?
+  & attribute style:layout-grid-standard-mode { boolean }?
+  & attribute style:layout-grid-base-height { length }?
+  & attribute style:layout-grid-ruby-height { length }?
+  & attribute style:layout-grid-lines { positiveInteger }?
+  & attribute style:layout-grid-base-width { length }?
+  & attribute style:layout-grid-color { color }?
+  & attribute style:layout-grid-ruby-below { boolean }?
+  & attribute style:layout-grid-print { boolean }?
+  & attribute style:layout-grid-display { boolean }?
+  & attribute style:layout-grid-snap-to { boolean }?
+style-page-layout-properties-elements =
+  style-background-image & style-columns & style-footnote-sep
+style-footnote-sep =
+  element style:footnote-sep { style-footnote-sep-attlist, empty }?
+style-footnote-sep-attlist =
+  attribute style:width { length }?,
+  attribute style:rel-width { percent }?,
+  attribute style:color { color }?,
+  attribute style:line-style { lineStyle }?,
+  attribute style:adjustment { "left" | "center" | "right" }?,
+  attribute style:distance-before-sep { length }?,
+  attribute style:distance-after-sep { length }?
+style-header-footer-properties =
+  element style:header-footer-properties {
+    style-header-footer-properties-content-strict
+  }
+style-header-footer-properties-content-strict =
+  style-header-footer-properties-attlist,
+  style-header-footer-properties-elements
+style-header-footer-properties-attlist =
+  attribute svg:height { length }?
+  & attribute fo:min-height { length }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-background-color-attlist
+  & common-shadow-attlist
+  & attribute style:dynamic-spacing { boolean }?
+style-header-footer-properties-elements = style-background-image
+style-text-properties =
+  element style:text-properties { style-text-properties-content-strict }
+style-text-properties-content-strict =
+  style-text-properties-attlist, style-text-properties-elements
+style-text-properties-elements = empty
+style-text-properties-attlist =
+  attribute fo:font-variant { fontVariant }?
+  & attribute fo:text-transform {
+      "none" | "lowercase" | "uppercase" | "capitalize"
+    }?
+  & attribute fo:color { color }?
+  & attribute style:use-window-font-color { boolean }?
+  & attribute style:text-outline { boolean }?
+  & attribute style:text-line-through-type { lineType }?
+  & attribute style:text-line-through-style { lineStyle }?
+  & attribute style:text-line-through-width { lineWidth }?
+  & attribute style:text-line-through-color { "font-color" | color }?
+  & attribute style:text-line-through-text { \string }?
+  & attribute style:text-line-through-text-style { styleNameRef }?
+  & attribute style:text-position {
+      list { (percent | "super" | "sub"), percent? }
+    }?
+  & attribute style:font-name { \string }?
+  & attribute style:font-name-asian { \string }?
+  & attribute style:font-name-complex { \string }?
+  & attribute fo:font-family { \string }?
+  & attribute style:font-family-asian { \string }?
+  & attribute style:font-family-complex { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-family-generic-asian { fontFamilyGeneric }?
+  & attribute style:font-family-generic-complex { fontFamilyGeneric }?
+  & attribute style:font-style-name { \string }?
+  & attribute style:font-style-name-asian { \string }?
+  & attribute style:font-style-name-complex { \string }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-pitch-asian { fontPitch }?
+  & attribute style:font-pitch-complex { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+  & attribute style:font-charset-asian { textEncoding }?
+  & attribute style:font-charset-complex { textEncoding }?
+  & attribute fo:font-size { positiveLength | percent }?
+  & attribute style:font-size-asian { positiveLength | percent }?
+  & attribute style:font-size-complex { positiveLength | percent }?
+  & attribute style:font-size-rel { length }?
+  & attribute style:font-size-rel-asian { length }?
+  & attribute style:font-size-rel-complex { length }?
+  & attribute style:script-type {
+      "latin" | "asian" | "complex" | "ignore"
+    }?
+  & attribute fo:letter-spacing { length | "normal" }?
+  & attribute fo:language { languageCode }?
+  & attribute style:language-asian { languageCode }?
+  & attribute style:language-complex { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute style:country-asian { countryCode }?
+  & attribute style:country-complex { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:script-asian { scriptCode }?
+  & attribute style:script-complex { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute style:rfc-language-tag-asian { language }?
+  & attribute style:rfc-language-tag-complex { language }?
+  & attribute fo:font-style { fontStyle }?
+  & attribute style:font-style-asian { fontStyle }?
+  & attribute style:font-style-complex { fontStyle }?
+  & attribute style:font-relief { "none" | "embossed" | "engraved" }?
+  & attribute fo:text-shadow { shadowType }?
+  & attribute style:text-underline-type { lineType }?
+  & attribute style:text-underline-style { lineStyle }?
+  & attribute style:text-underline-width { lineWidth }?
+  & attribute style:text-underline-color { "font-color" | color }?
+  & attribute style:text-overline-type { lineType }?
+  & attribute style:text-overline-style { lineStyle }?
+  & attribute style:text-overline-width { lineWidth }?
+  & attribute style:text-overline-color { "font-color" | color }?
+  & attribute style:text-overline-mode { lineMode }?
+  & attribute fo:font-weight { fontWeight }?
+  & attribute style:font-weight-asian { fontWeight }?
+  & attribute style:font-weight-complex { fontWeight }?
+  & attribute style:text-underline-mode { lineMode }?
+  & attribute style:text-line-through-mode { lineMode }?
+  & attribute style:letter-kerning { boolean }?
+  & attribute style:text-blinking { boolean }?
+  & common-background-color-attlist
+  & attribute style:text-combine { "none" | "letters" | "lines" }?
+  & attribute style:text-combine-start-char { character }?
+  & attribute style:text-combine-end-char { character }?
+  & attribute style:text-emphasize {
+      "none"
+      | list {
+          ("none" | "accent" | "dot" | "circle" | "disc"),
+          ("above" | "below")
+        }
+    }?
+  & attribute style:text-scale { percent }?
+  & attribute style:text-rotation-angle { angle }?
+  & attribute style:text-rotation-scale { "fixed" | "line-height" }?
+  & attribute fo:hyphenate { boolean }?
+  & attribute fo:hyphenation-remain-char-count { positiveInteger }?
+  & attribute fo:hyphenation-push-char-count { positiveInteger }?
+  & (attribute text:display { "true" }
+     | attribute text:display { "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { "none" })
+     | empty)
+fontVariant = "normal" | "small-caps"
+fontFamilyGeneric =
+  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
+fontPitch = "fixed" | "variable"
+textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
+fontStyle = "normal" | "italic" | "oblique"
+shadowType = "none" | \string
+lineType = "none" | "single" | "double"
+lineStyle =
+  "none"
+  | "solid"
+  | "dotted"
+  | "dash"
+  | "long-dash"
+  | "dot-dash"
+  | "dot-dot-dash"
+  | "wave"
+lineWidth =
+  "auto"
+  | "normal"
+  | "bold"
+  | "thin"
+  | "medium"
+  | "thick"
+  | positiveInteger
+  | percent
+  | positiveLength
+fontWeight =
+  "normal"
+  | "bold"
+  | "100"
+  | "200"
+  | "300"
+  | "400"
+  | "500"
+  | "600"
+  | "700"
+  | "800"
+  | "900"
+lineMode = "continuous" | "skip-white-space"
+style-paragraph-properties =
+  element style:paragraph-properties {
+    style-paragraph-properties-content-strict
+  }
+style-paragraph-properties-content-strict =
+  style-paragraph-properties-attlist,
+  style-paragraph-properties-elements
+style-paragraph-properties-attlist =
+  attribute fo:line-height { "normal" | nonNegativeLength | percent }?
+  & attribute style:line-height-at-least { nonNegativeLength }?
+  & attribute style:line-spacing { length }?
+  & attribute style:font-independent-line-spacing { boolean }?
+  & common-text-align
+  & attribute fo:text-align-last { "start" | "center" | "justify" }?
+  & attribute style:justify-single-word { boolean }?
+  & attribute fo:keep-together { "auto" | "always" }?
+  & attribute fo:widows { nonNegativeInteger }?
+  & attribute fo:orphans { nonNegativeInteger }?
+  & attribute style:tab-stop-distance { nonNegativeLength }?
+  & attribute fo:hyphenation-keep { "auto" | "page" }?
+  & attribute fo:hyphenation-ladder-count {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:register-true { boolean }?
+  & common-horizontal-margin-attlist
+  & attribute fo:text-indent { length | percent }?
+  & attribute style:auto-text-indent { boolean }?
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-break-attlist
+  & common-background-color-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & attribute style:join-border { boolean }?
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute text:number-lines { boolean }?
+  & attribute text:line-number { nonNegativeInteger }?
+  & attribute style:text-autospace { "none" | "ideograph-alpha" }?
+  & attribute style:punctuation-wrap { "simple" | "hanging" }?
+  & attribute style:line-break { "normal" | "strict" }?
+  & attribute style:vertical-align {
+      "top" | "middle" | "bottom" | "auto" | "baseline"
+    }?
+  & common-writing-mode-attlist
+  & attribute style:writing-mode-automatic { boolean }?
+  & attribute style:snap-to-layout-grid { boolean }?
+  & common-page-number-attlist
+  & common-background-transparency-attlist
+common-text-align =
+  attribute fo:text-align {
+    "start" | "end" | "left" | "right" | "center" | "justify"
+  }?
+style-paragraph-properties-elements =
+  style-tab-stops & style-drop-cap & style-background-image
+style-tab-stops = element style:tab-stops { style-tab-stop* }?
+style-tab-stop =
+  element style:tab-stop { style-tab-stop-attlist, empty }
+style-tab-stop-attlist =
+  attribute style:position { length }
+  & (attribute style:type { "left" | "center" | "right" }?
+     | (attribute style:type { "char" },
+        style-tab-stop-char-attlist))
+  & attribute style:leader-type { lineType }?
+  & attribute style:leader-style { lineStyle }?
+  & attribute style:leader-width { lineWidth }?
+  & attribute style:leader-color { "font-color" | color }?
+  & attribute style:leader-text { character }?
+  & attribute style:leader-text-style { styleNameRef }?
+style-tab-stop-char-attlist = attribute style:char { character }
+style-drop-cap =
+  element style:drop-cap { style-drop-cap-attlist, empty }?
+style-drop-cap-attlist =
+  attribute style:length { "word" | positiveInteger }?
+  & attribute style:lines { positiveInteger }?
+  & attribute style:distance { length }?
+  & attribute style:style-name { styleNameRef }?
+common-horizontal-margin-attlist =
+  attribute fo:margin-left { length | percent }?,
+  attribute fo:margin-right { length | percent }?
+common-vertical-margin-attlist =
+  attribute fo:margin-top { nonNegativeLength | percent }?,
+  attribute fo:margin-bottom { nonNegativeLength | percent }?
+common-margin-attlist =
+  attribute fo:margin { nonNegativeLength | percent }?
+common-break-attlist =
+  attribute fo:break-before { "auto" | "column" | "page" }?,
+  attribute fo:break-after { "auto" | "column" | "page" }?
+common-background-color-attlist =
+  attribute fo:background-color { "transparent" | color }?
+style-background-image =
+  element style:background-image {
+    style-background-image-attlist,
+    (common-draw-data-attlist | office-binary-data | empty)
+  }?
+style-background-image-attlist =
+  attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
+  & attribute style:position {
+      "left"
+      | "center"
+      | "right"
+      | "top"
+      | "bottom"
+      | list { horiBackPos, vertBackPos }
+      | list { vertBackPos, horiBackPos }
+    }?
+  & attribute style:filter-name { \string }?
+  & attribute draw:opacity { zeroToHundredPercent }?
+horiBackPos = "left" | "center" | "right"
+vertBackPos = "top" | "center" | "bottom"
+common-border-attlist =
+  attribute fo:border { \string }?,
+  attribute fo:border-top { \string }?,
+  attribute fo:border-bottom { \string }?,
+  attribute fo:border-left { \string }?,
+  attribute fo:border-right { \string }?
+common-border-line-width-attlist =
+  attribute style:border-line-width { borderWidths }?,
+  attribute style:border-line-width-top { borderWidths }?,
+  attribute style:border-line-width-bottom { borderWidths }?,
+  attribute style:border-line-width-left { borderWidths }?,
+  attribute style:border-line-width-right { borderWidths }?
+borderWidths = list { positiveLength, positiveLength, positiveLength }
+common-padding-attlist =
+  attribute fo:padding { nonNegativeLength }?,
+  attribute fo:padding-top { nonNegativeLength }?,
+  attribute fo:padding-bottom { nonNegativeLength }?,
+  attribute fo:padding-left { nonNegativeLength }?,
+  attribute fo:padding-right { nonNegativeLength }?
+common-shadow-attlist = attribute style:shadow { shadowType }?
+common-keep-with-next-attlist =
+  attribute fo:keep-with-next { "auto" | "always" }?
+common-writing-mode-attlist =
+  attribute style:writing-mode {
+    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
+  }?
+common-page-number-attlist =
+  attribute style:page-number { positiveInteger | "auto" }?
+common-background-transparency-attlist =
+  attribute style:background-transparency { zeroToHundredPercent }?
+style-ruby-properties =
+  element style:ruby-properties { style-ruby-properties-content-strict }
+style-ruby-properties-content-strict =
+  style-ruby-properties-attlist, style-ruby-properties-elements
+style-ruby-properties-elements = empty
+style-ruby-properties-attlist =
+  attribute style:ruby-position { "above" | "below" }?
+  & attribute style:ruby-align {
+      "left"
+      | "center"
+      | "right"
+      | "distribute-letter"
+      | "distribute-space"
+    }?
+style-section-properties =
+  element style:section-properties {
+    style-section-properties-content-strict
+  }
+style-section-properties-content-strict =
+  style-section-properties-attlist, style-section-properties-elements
+style-section-properties-attlist =
+  common-background-color-attlist
+  & common-horizontal-margin-attlist
+  & attribute style:protect { boolean }?
+  & common-editable-attlist
+  & attribute text:dont-balance-text-columns { boolean }?
+  & common-writing-mode-attlist
+style-section-properties-elements =
+  style-background-image & style-columns & text-notes-configuration*
+style-columns =
+  element style:columns {
+    style-columns-attlist, style-column-sep?, style-column*
+  }?
+style-columns-attlist =
+  attribute fo:column-count { positiveInteger }
+  & attribute fo:column-gap { length }?
+style-column = element style:column { style-column-attlist }
+style-column-attlist =
+  attribute style:rel-width { relativeLength }
+  & attribute fo:start-indent { length }?
+  & attribute fo:end-indent { length }?
+  & attribute fo:space-before { length }?
+  & attribute fo:space-after { length }?
+style-column-sep = element style:column-sep { style-column-sep-attlist }
+style-column-sep-attlist =
+  attribute style:style {
+    "none" | "solid" | "dotted" | "dashed" | "dot-dashed"
+  }?
+  & attribute style:width { length }
+  & attribute style:height { zeroToHundredPercent }?
+  & attribute style:vertical-align { "top" | "middle" | "bottom" }?
+  & attribute style:color { color }?
+style-table-properties =
+  element style:table-properties {
+    style-table-properties-content-strict
+  }
+style-table-properties-content-strict =
+  style-table-properties-attlist, style-table-properties-elements
+style-table-properties-attlist =
+  attribute style:width { positiveLength }?
+  & attribute style:rel-width { percent }?
+  & attribute table:align { "left" | "center" | "right" | "margins" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-page-number-attlist
+  & common-break-attlist
+  & common-background-color-attlist
+  & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute style:may-break-between-rows { boolean }?
+  & attribute table:border-model { "collapsing" | "separating" }?
+  & common-writing-mode-attlist
+  & attribute table:display { boolean }?
+style-table-properties-elements = style-background-image
+style-table-column-properties =
+  element style:table-column-properties {
+    style-table-column-properties-content-strict
+  }
+style-table-column-properties-content-strict =
+  style-table-column-properties-attlist,
+  style-table-column-properties-elements
+style-table-column-properties-elements = empty
+style-table-column-properties-attlist =
+  attribute style:column-width { positiveLength }?
+  & attribute style:rel-column-width { relativeLength }?
+  & attribute style:use-optimal-column-width { boolean }?
+  & common-break-attlist
+style-table-row-properties =
+  element style:table-row-properties {
+    style-table-row-properties-content-strict
+  }
+style-table-row-properties-content-strict =
+  style-table-row-properties-attlist,
+  style-table-row-properties-elements
+style-table-row-properties-attlist =
+  attribute style:row-height { positiveLength }?
+  & attribute style:min-row-height { nonNegativeLength }?
+  & attribute style:use-optimal-row-height { boolean }?
+  & common-background-color-attlist
+  & common-break-attlist
+  & attribute fo:keep-together { "auto" | "always" }?
+style-table-row-properties-elements = style-background-image
+style-table-cell-properties =
+  element style:table-cell-properties {
+    style-table-cell-properties-content-strict
+  }
+style-table-cell-properties-content-strict =
+  style-table-cell-properties-attlist,
+  style-table-cell-properties-elements
+style-table-cell-properties-attlist =
+  attribute style:vertical-align {
+    "top" | "middle" | "bottom" | "automatic"
+  }?
+  & attribute style:text-align-source { "fix" | "value-type" }?
+  & common-style-direction-attlist
+  & attribute style:glyph-orientation-vertical {
+      "auto" | "0" | "0deg" | "0rad" | "0grad"
+    }?
+  & common-writing-mode-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & common-border-attlist
+  & attribute style:diagonal-tl-br { \string }?
+  & attribute style:diagonal-tl-br-widths { borderWidths }?
+  & attribute style:diagonal-bl-tr { \string }?
+  & attribute style:diagonal-bl-tr-widths { borderWidths }?
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+  & common-rotation-angle-attlist
+  & attribute style:rotation-align {
+      "none" | "bottom" | "top" | "center"
+    }?
+  & attribute style:cell-protect {
+      "none"
+      | "hidden-and-protected"
+      | list { ("protected" | "formula-hidden")+ }
+    }?
+  & attribute style:print-content { boolean }?
+  & attribute style:decimal-places { nonNegativeInteger }?
+  & attribute style:repeat-content { boolean }?
+  & attribute style:shrink-to-fit { boolean }?
+common-style-direction-attlist =
+  attribute style:direction { "ltr" | "ttb" }?
+style-table-cell-properties-elements = style-background-image
+common-rotation-angle-attlist =
+  attribute style:rotation-angle { angle }?
+style-list-level-properties =
+  element style:list-level-properties {
+    style-list-level-properties-content-strict
+  }
+style-list-level-properties-content-strict =
+  style-list-level-properties-attlist,
+  style-list-level-properties-elements
+style-list-level-properties-attlist =
+  common-text-align
+  & attribute text:space-before { length }?
+  & attribute text:min-label-width { nonNegativeLength }?
+  & attribute text:min-label-distance { nonNegativeLength }?
+  & attribute style:font-name { \string }?
+  & attribute fo:width { positiveLength }?
+  & attribute fo:height { positiveLength }?
+  & common-vertical-rel-attlist
+  & common-vertical-pos-attlist
+  & attribute text:list-level-position-and-space-mode {
+      "label-width-and-position" | "label-alignment"
+    }?
+style-list-level-properties-elements = style-list-level-label-alignment
+style-list-level-label-alignment =
+  element style:list-level-label-alignment {
+    style-list-level-label-alignment-attlist, empty
+  }?
+style-list-level-label-alignment-attlist =
+  attribute text:label-followed-by { "listtab" | "space" | "nothing" }
+  & attribute text:list-tab-stop-position { length }?
+  & attribute fo:text-indent { length }?
+  & attribute fo:margin-left { length }?
+style-graphic-properties-attlist =
+  attribute draw:stroke { "none" | "dash" | "solid" }?
+  & attribute draw:stroke-dash { styleNameRef }?
+  & attribute draw:stroke-dash-names { styleNameRefs }?
+  & attribute svg:stroke-width { length }?
+  & attribute svg:stroke-color { color }?
+  & attribute draw:marker-start { styleNameRef }?
+  & attribute draw:marker-end { styleNameRef }?
+  & attribute draw:marker-start-width { length }?
+  & attribute draw:marker-end-width { length }?
+  & attribute draw:marker-start-center { boolean }?
+  & attribute draw:marker-end-center { boolean }?
+  & attribute svg:stroke-opacity {
+      xsd:double { minInclusive = "0" maxInclusive = "1" }
+      | zeroToHundredPercent
+    }?
+  & attribute draw:stroke-linejoin {
+      "miter" | "round" | "bevel" | "middle" | "none"
+    }?
+  & attribute svg:stroke-linecap { "butt" | "square" | "round" }?
+  & attribute draw:symbol-color { color }?
+  & attribute text:animation {
+      "none" | "scroll" | "alternate" | "slide"
+    }?
+  & attribute text:animation-direction {
+      "left" | "right" | "up" | "down"
+    }?
+  & attribute text:animation-start-inside { boolean }?
+  & attribute text:animation-stop-inside { boolean }?
+  & attribute text:animation-repeat { nonNegativeInteger }?
+  & attribute text:animation-delay { duration }?
+  & attribute text:animation-steps { length }?
+  & attribute draw:auto-grow-width { boolean }?
+  & attribute draw:auto-grow-height { boolean }?
+  & attribute draw:fit-to-size { boolean }?
+  & attribute draw:fit-to-contour { boolean }?
+  & attribute draw:textarea-vertical-align {
+      "top" | "middle" | "bottom" | "justify"
+    }?
+  & attribute draw:textarea-horizontal-align {
+      "left" | "center" | "right" | "justify"
+    }?
+  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+  & attribute style:shrink-to-fit { boolean }?
+  & attribute draw:color-mode {
+      "greyscale" | "mono" | "watermark" | "standard"
+    }?
+  & attribute draw:color-inversion { boolean }?
+  & attribute draw:luminance { zeroToHundredPercent }?
+  & attribute draw:contrast { percent }?
+  & attribute draw:gamma { percent }?
+  & attribute draw:red { signedZeroToHundredPercent }?
+  & attribute draw:green { signedZeroToHundredPercent }?
+  & attribute draw:blue { signedZeroToHundredPercent }?
+  & attribute draw:image-opacity { zeroToHundredPercent }?
+  & attribute draw:shadow { "visible" | "hidden" }?
+  & attribute draw:shadow-offset-x { length }?
+  & attribute draw:shadow-offset-y { length }?
+  & attribute draw:shadow-color { color }?
+  & attribute draw:shadow-opacity { zeroToHundredPercent }?
+  & attribute draw:start-line-spacing-horizontal { distance }?
+  & attribute draw:start-line-spacing-vertical { distance }?
+  & attribute draw:end-line-spacing-horizontal { distance }?
+  & attribute draw:end-line-spacing-vertical { distance }?
+  & attribute draw:line-distance { distance }?
+  & attribute draw:guide-overhang { length }?
+  & attribute draw:guide-distance { distance }?
+  & attribute draw:start-guide { length }?
+  & attribute draw:end-guide { length }?
+  & attribute draw:placing { "below" | "above" }?
+  & attribute draw:parallel { boolean }?
+  & attribute draw:measure-align {
+      "automatic" | "left-outside" | "inside" | "right-outside"
+    }?
+  & attribute draw:measure-vertical-align {
+      "automatic" | "above" | "below" | "center"
+    }?
+  & attribute draw:unit {
+      "automatic"
+      | "mm"
+      | "cm"
+      | "m"
+      | "km"
+      | "pt"
+      | "pc"
+      | "inch"
+      | "ft"
+      | "mi"
+    }?
+  & attribute draw:show-unit { boolean }?
+  & attribute draw:decimal-places { nonNegativeInteger }?
+  & attribute draw:caption-type {
+      "straight-line" | "angled-line" | "angled-connector-line"
+    }?
+  & attribute draw:caption-angle-type { "fixed" | "free" }?
+  & attribute draw:caption-angle { angle }?
+  & attribute draw:caption-gap { distance }?
+  & attribute draw:caption-escape-direction {
+      "horizontal" | "vertical" | "auto"
+    }?
+  & attribute draw:caption-escape { length | percent }?
+  & attribute draw:caption-line-length { length }?
+  & attribute draw:caption-fit-line-length { boolean }?
+  & attribute dr3d:horizontal-segments { nonNegativeInteger }?
+  & attribute dr3d:vertical-segments { nonNegativeInteger }?
+  & attribute dr3d:edge-rounding { percent }?
+  & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
+  & attribute dr3d:back-scale { percent }?
+  & attribute dr3d:depth { length }?
+  & attribute dr3d:backface-culling { "enabled" | "disabled" }?
+  & attribute dr3d:end-angle { angle }?
+  & attribute dr3d:close-front { boolean }?
+  & attribute dr3d:close-back { boolean }?
+  & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
+  & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
+  & attribute dr3d:normals-direction { "normal" | "inverse" }?
+  & attribute dr3d:texture-generation-mode-x {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-generation-mode-y {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }?
+  & attribute dr3d:texture-filter { "enabled" | "disabled" }?
+  & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:emissive-color { color }?
+  & attribute dr3d:specular-color { color }?
+  & attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:shininess { percent }?
+  & attribute dr3d:shadow { "visible" | "hidden" }?
+  & common-draw-rel-size-attlist
+  & attribute fo:min-width { length | percent }?
+  & attribute fo:min-height { length | percent }?
+  & attribute fo:max-height { length | percent }?
+  & attribute fo:max-width { length | percent }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & attribute style:print-content { boolean }?
+  & attribute style:protect {
+      "none"
+      | list { ("content" | "position" | "size")+ }
+    }?
+  & attribute style:horizontal-pos {
+      "left"
+      | "center"
+      | "right"
+      | "from-left"
+      | "inside"
+      | "outside"
+      | "from-inside"
+    }?
+  & attribute svg:x { coordinate }?
+  & attribute style:horizontal-rel {
+      "page"
+      | "page-content"
+      | "page-start-margin"
+      | "page-end-margin"
+      | "frame"
+      | "frame-content"
+      | "frame-start-margin"
+      | "frame-end-margin"
+      | "paragraph"
+      | "paragraph-content"
+      | "paragraph-start-margin"
+      | "paragraph-end-margin"
+      | "char"
+    }?
+  & common-vertical-pos-attlist
+  & common-vertical-rel-attlist
+  & common-text-anchor-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & common-background-transparency-attlist
+  & common-editable-attlist
+  & attribute style:wrap {
+      "none"
+      | "left"
+      | "right"
+      | "parallel"
+      | "dynamic"
+      | "run-through"
+      | "biggest"
+    }?
+  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
+  & attribute style:number-wrapped-paragraphs {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:wrap-contour { boolean }?
+  & attribute style:wrap-contour-mode { "full" | "outside" }?
+  & attribute style:run-through { "foreground" | "background" }?
+  & attribute style:flow-with-text { boolean }?
+  & attribute style:overflow-behavior {
+      "clip" | "auto-create-new-frame"
+    }?
+  & attribute style:mirror {
+      "none"
+      | "vertical"
+      | horizontal-mirror
+      | list { "vertical", horizontal-mirror }
+      | list { horizontal-mirror, "vertical" }
+    }?
+  & attribute fo:clip { "auto" | clipShape }?
+  & attribute draw:wrap-influence-on-position {
+      "iterative" | "once-concurrent" | "once-successive"
+    }?
+  & common-writing-mode-attlist
+  & attribute draw:frame-display-scrollbar { boolean }?
+  & attribute draw:frame-display-border { boolean }?
+  & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
+  & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
+  & attribute draw:visible-area-left { nonNegativeLength }?
+  & attribute draw:visible-area-top { nonNegativeLength }?
+  & attribute draw:visible-area-width { positiveLength }?
+  & attribute draw:visible-area-height { positiveLength }?
+  & attribute draw:draw-aspect {
+      "content" | "thumbnail" | "icon" | "print-view"
+    }?
+  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
+style-graphic-fill-properties-attlist =
+  attribute draw:fill {
+    "none" | "solid" | "bitmap" | "gradient" | "hatch"
+  }?
+  & attribute draw:fill-color { color }?
+  & attribute draw:secondary-fill-color { color }?
+  & attribute draw:fill-gradient-name { styleNameRef }?
+  & attribute draw:gradient-step-count { nonNegativeInteger }?
+  & attribute draw:fill-hatch-name { styleNameRef }?
+  & attribute draw:fill-hatch-solid { boolean }?
+  & attribute draw:fill-image-name { styleNameRef }?
+  & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
+  & attribute draw:fill-image-width { length | percent }?
+  & attribute draw:fill-image-height { length | percent }?
+  & attribute draw:fill-image-ref-point-x { percent }?
+  & attribute draw:fill-image-ref-point-y { percent }?
+  & attribute draw:fill-image-ref-point {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom"
+      | "bottom-right"
+    }?
+  & attribute draw:tile-repeat-offset {
+      list { zeroToHundredPercent, ("horizontal" | "vertical") }
+    }?
+  & attribute draw:opacity { zeroToHundredPercent }?
+  & attribute draw:opacity-name { styleNameRef }?
+  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
+style-graphic-properties-elements =
+  text-list-style? & style-background-image & style-columns
+common-vertical-pos-attlist =
+  attribute style:vertical-pos {
+    "top" | "middle" | "bottom" | "from-top" | "below"
+  }?,
+  attribute svg:y { coordinate }?
+common-vertical-rel-attlist =
+  attribute style:vertical-rel {
+    "page"
+    | "page-content"
+    | "frame"
+    | "frame-content"
+    | "paragraph"
+    | "paragraph-content"
+    | "char"
+    | "line"
+    | "baseline"
+    | "text"
+  }?
+common-editable-attlist = attribute style:editable { boolean }?
+horizontal-mirror =
+  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
+clipShape =
+  xsd:string {
+    pattern =
+      "rect\([ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)"
+  }
+nonNegativePixelLength =
+  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
+style-chart-properties =
+  element style:chart-properties {
+    style-chart-properties-content-strict
+  }
+style-chart-properties-content-strict =
+  style-chart-properties-attlist, style-chart-properties-elements
+style-chart-properties-elements = empty
+style-chart-properties-attlist =
+  attribute chart:scale-text { boolean }?
+  & attribute chart:three-dimensional { boolean }?
+  & attribute chart:deep { boolean }?
+  & attribute chart:right-angled-axes { boolean }?
+  & (attribute chart:symbol-type { "none" }
+     | attribute chart:symbol-type { "automatic" }
+     | (attribute chart:symbol-type { "named-symbol" },
+        attribute chart:symbol-name {
+          "square"
+          | "diamond"
+          | "arrow-down"
+          | "arrow-up"
+          | "arrow-right"
+          | "arrow-left"
+          | "bow-tie"
+          | "hourglass"
+          | "circle"
+          | "star"
+          | "x"
+          | "plus"
+          | "asterisk"
+          | "horizontal-bar"
+          | "vertical-bar"
+        })
+     | (attribute chart:symbol-type { "image" },
+        element chart:symbol-image {
+          attribute xlink:href { anyIRI }
+        })
+     | empty)
+  & attribute chart:symbol-width { nonNegativeLength }?
+  & attribute chart:symbol-height { nonNegativeLength }?
+  & attribute chart:sort-by-x-values { boolean }?
+  & attribute chart:vertical { boolean }?
+  & attribute chart:connect-bars { boolean }?
+  & attribute chart:gap-width { integer }?
+  & attribute chart:overlap { integer }?
+  & attribute chart:group-bars-per-axis { boolean }?
+  & attribute chart:japanese-candle-stick { boolean }?
+  & attribute chart:interpolation {
+      "none" | "cubic-spline" | "b-spline"
+    }?
+  & attribute chart:spline-order { positiveInteger }?
+  & attribute chart:spline-resolution { positiveInteger }?
+  & attribute chart:pie-offset { nonNegativeInteger }?
+  & attribute chart:angle-offset { angle }?
+  & attribute chart:hole-size { percent }?
+  & attribute chart:lines { boolean }?
+  & attribute chart:solid-type {
+      "cuboid" | "cylinder" | "cone" | "pyramid"
+    }?
+  & attribute chart:stacked { boolean }?
+  & attribute chart:percentage { boolean }?
+  & attribute chart:treat-empty-cells {
+      "use-zero" | "leave-gap" | "ignore"
+    }?
+  & attribute chart:link-data-style-to-source { boolean }?
+  & attribute chart:logarithmic { boolean }?
+  & attribute chart:maximum { double }?
+  & attribute chart:minimum { double }?
+  & attribute chart:origin { double }?
+  & attribute chart:interval-major { double }?
+  & attribute chart:interval-minor-divisor { positiveInteger }?
+  & attribute chart:tick-marks-major-inner { boolean }?
+  & attribute chart:tick-marks-major-outer { boolean }?
+  & attribute chart:tick-marks-minor-inner { boolean }?
+  & attribute chart:tick-marks-minor-outer { boolean }?
+  & attribute chart:reverse-direction { boolean }?
+  & attribute chart:display-label { boolean }?
+  & attribute chart:text-overlap { boolean }?
+  & attribute text:line-break { boolean }?
+  & attribute chart:label-arrangement {
+      "side-by-side" | "stagger-even" | "stagger-odd"
+    }?
+  & common-style-direction-attlist
+  & common-rotation-angle-attlist
+  & attribute chart:data-label-number {
+      "none" | "value" | "percentage" | "value-and-percentage"
+    }?
+  & attribute chart:data-label-text { boolean }?
+  & attribute chart:data-label-symbol { boolean }?
+  & element chart:label-separator { text-p }?
+  & attribute chart:label-position { labelPositions }?
+  & attribute chart:label-position-negative { labelPositions }?
+  & attribute chart:visible { boolean }?
+  & attribute chart:auto-position { boolean }?
+  & attribute chart:auto-size { boolean }?
+  & attribute chart:mean-value { boolean }?
+  & attribute chart:error-category {
+      "none"
+      | "variance"
+      | "standard-deviation"
+      | "percentage"
+      | "error-margin"
+      | "constant"
+      | "standard-error"
+      | "cell-range"
+    }?
+  & attribute chart:error-percentage { double }?
+  & attribute chart:error-margin { double }?
+  & attribute chart:error-lower-limit { double }?
+  & attribute chart:error-upper-limit { double }?
+  & attribute chart:error-upper-indicator { boolean }?
+  & attribute chart:error-lower-indicator { boolean }?
+  & attribute chart:error-lower-range { cellRangeAddressList }?
+  & attribute chart:error-upper-range { cellRangeAddressList }?
+  & attribute chart:series-source { "columns" | "rows" }?
+  & attribute chart:regression-type {
+      "none" | "linear" | "logarithmic" | "exponential" | "power"
+    }?
+  & attribute chart:axis-position { "start" | "end" | double }?
+  & attribute chart:axis-label-position {
+      "near-axis"
+      | "near-axis-other-side"
+      | "outside-start"
+      | "outside-end"
+    }?
+  & attribute chart:tick-mark-position {
+      "at-labels" | "at-axis" | "at-labels-and-axis"
+    }?
+  & attribute chart:include-hidden-cells { boolean }?
+labelPositions =
+  "avoid-overlap"
+  | "center"
+  | "top"
+  | "top-right"
+  | "right"
+  | "bottom-right"
+  | "bottom"
+  | "bottom-left"
+  | "left"
+  | "top-left"
+  | "inside"
+  | "outside"
+  | "near-origin"
+style-drawing-page-properties-attlist =
+  attribute presentation:transition-type {
+    "manual" | "automatic" | "semi-automatic"
+  }?
+  & attribute presentation:transition-style {
+      "none"
+      | "fade-from-left"
+      | "fade-from-top"
+      | "fade-from-right"
+      | "fade-from-bottom"
+      | "fade-from-upperleft"
+      | "fade-from-upperright"
+      | "fade-from-lowerleft"
+      | "fade-from-lowerright"
+      | "move-from-left"
+      | "move-from-top"
+      | "move-from-right"
+      | "move-from-bottom"
+      | "move-from-upperleft"
+      | "move-from-upperright"
+      | "move-from-lowerleft"
+      | "move-from-lowerright"
+      | "uncover-to-left"
+      | "uncover-to-top"
+      | "uncover-to-right"
+      | "uncover-to-bottom"
+      | "uncover-to-upperleft"
+      | "uncover-to-upperright"
+      | "uncover-to-lowerleft"
+      | "uncover-to-lowerright"
+      | "fade-to-center"
+      | "fade-from-center"
+      | "vertical-stripes"
+      | "horizontal-stripes"
+      | "clockwise"
+      | "counterclockwise"
+      | "open-vertical"
+      | "open-horizontal"
+      | "close-vertical"
+      | "close-horizontal"
+      | "wavyline-from-left"
+      | "wavyline-from-top"
+      | "wavyline-from-right"
+      | "wavyline-from-bottom"
+      | "spiralin-left"
+      | "spiralin-right"
+      | "spiralout-left"
+      | "spiralout-right"
+      | "roll-from-top"
+      | "roll-from-left"
+      | "roll-from-right"
+      | "roll-from-bottom"
+      | "stretch-from-left"
+      | "stretch-from-top"
+      | "stretch-from-right"
+      | "stretch-from-bottom"
+      | "vertical-lines"
+      | "horizontal-lines"
+      | "dissolve"
+      | "random"
+      | "vertical-checkerboard"
+      | "horizontal-checkerboard"
+      | "interlocking-horizontal-left"
+      | "interlocking-horizontal-right"
+      | "interlocking-vertical-top"
+      | "interlocking-vertical-bottom"
+      | "fly-away"
+      | "open"
+      | "close"
+      | "melt"
+    }?
+  & attribute presentation:transition-speed { presentationSpeeds }?
+  & attribute smil:type { \string }?
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute presentation:duration { duration }?
+  & attribute presentation:visibility { "visible" | "hidden" }?
+  & attribute draw:background-size { "full" | "border" }?
+  & attribute presentation:background-objects-visible { boolean }?
+  & attribute presentation:background-visible { boolean }?
+  & attribute presentation:display-header { boolean }?
+  & attribute presentation:display-footer { boolean }?
+  & attribute presentation:display-page-number { boolean }?
+  & attribute presentation:display-date-time { boolean }?
+style-drawing-page-properties-elements = presentation-sound?
+\string = xsd:string
+date = xsd:date
+time = xsd:time
+dateTime = xsd:dateTime
+duration = xsd:duration
+integer = xsd:integer
+nonNegativeInteger = xsd:nonNegativeInteger
+positiveInteger = xsd:positiveInteger
+double = xsd:double
+anyURI = xsd:anyURI
+base64Binary = xsd:base64Binary
+ID = xsd:ID
+IDREF = xsd:IDREF
+IDREFS = xsd:IDREFS
+NCName = xsd:NCName
+boolean = "true" | "false"
+dateOrDateTime = xsd:date | xsd:dateTime
+timeOrDateTime = xsd:time | xsd:dateTime
+language = xsd:language
+countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
+scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+character = xsd:string { length = "1" }
+length =
+  xsd:string {
+    pattern =
+      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  }
+nonNegativeLength =
+  xsd:string {
+    pattern =
+      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  }
+positiveLength =
+  xsd:string {
+    pattern =
+      
"([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  }
+percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
+zeroToHundredPercent =
+  xsd:string {
+    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+  }
+signedZeroToHundredPercent =
+  xsd:string {
+    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+  }
+relativeLength = xsd:string { pattern = "[0-9]+\*" }
+coordinate = length
+distance = length
+color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
+angle = xsd:string
+CURIE =
+  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
+CURIEs = list { CURIE+ }
+SafeCURIE =
+  xsd:string {
+    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
+    minLength = "3"
+  }
+URIorSafeCURIE = anyURI | SafeCURIE
+styleName = xsd:NCName
+styleNameRef = xsd:NCName | empty
+styleNameRefs = list { xsd:NCName* }
+variableName = xsd:string
+targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+valueType =
+  "float"
+  | "time"
+  | "date"
+  | "percentage"
+  | "currency"
+  | "boolean"
+  | "string"
+points =
+  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
+pathData = xsd:string
+vector3D =
+  xsd:string {
+    pattern =
+      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\)"
+  }
+namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
+anyIRI =
+  xsd:anyURI
+  >> dc:description [
+       "An IRI-reference as defined in [RFC3987]. See ODF 1.2 Part 1 section 
18.3."
+     ]
+anyAttListOrElements =
+  attribute * { text }*,
+  anyElements
+anyElements =
+  element * {
+    mixed { anyAttListOrElements }
+  }*
diff --git a/lisp/org/ob-C.el b/lisp/org/ob-C.el
index 77cfd53..2bdda68 100644
--- a/lisp/org/ob-C.el
+++ b/lisp/org/ob-C.el
@@ -1,8 +1,9 @@
-;;; ob-C.el --- org-babel functions for C and similar languages
+;;; ob-C.el --- Babel Functions for C and Similar Languages -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;;      Thierry Banel
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
 
@@ -23,37 +24,57 @@
 
 ;;; Commentary:
 
-;; Org-Babel support for evaluating C code.
+;; Org-Babel support for evaluating C, C++, D code.
 ;;
 ;; very limited implementation:
 ;; - currently only support :results output
 ;; - not much in the way of error feedback
 
 ;;; Code:
-(eval-when-compile
-  (require 'cl))
-(require 'ob)
+
 (require 'cc-mode)
+(require 'ob)
 
-(declare-function org-entry-get "org"
-                 (pom property &optional inherit literal-nil))
 
+(declare-function org-entry-get "org" (pom property &optional inherit 
literal-nil))
+(declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("C++" . "cpp"))
+(add-to-list 'org-babel-tangle-lang-exts '("D" . "d"))
 
 (defvar org-babel-default-header-args:C '())
 
-(defvar org-babel-C-compiler "gcc"
-  "Command used to compile a C source code file into an
-executable.")
-
-(defvar org-babel-C++-compiler "g++"
-  "Command used to compile a C++ source code file into an
-executable.")
+(defcustom org-babel-C-compiler "gcc"
+  "Command used to compile a C source code file into an executable.
+May be either a command in the path, like gcc
+or an absolute path name, like /usr/local/bin/gcc
+parameter may be used, like gcc -v"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
+
+(defcustom org-babel-C++-compiler "g++"
+  "Command used to compile a C++ source code file into an executable.
+May be either a command in the path, like g++
+or an absolute path name, like /usr/local/bin/g++
+parameter may be used, like g++ -v"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
+
+(defcustom org-babel-D-compiler "rdmd"
+  "Command used to compile and execute a D source code file.
+May be either a command in the path, like rdmd
+or an absolute path name, like /usr/local/bin/rdmd
+parameter may be used, like rdmd --chatty"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
 
 (defvar org-babel-c-variant nil
-  "Internal variable used to hold which type of C (e.g. C or C++)
+  "Internal variable used to hold which type of C (e.g. C or C++ or D)
 is currently being evaluated.")
 
 (defun org-babel-execute:cpp (body params)
@@ -61,88 +82,189 @@ is currently being evaluated.")
 This function calls `org-babel-execute:C++'."
   (org-babel-execute:C++ body params))
 
+(defun org-babel-expand-body:cpp (body params)
+  "Expand a block of C++ code with org-babel according to its
+header arguments."
+  (org-babel-expand-body:C++ body params))
+
 (defun org-babel-execute:C++ (body params)
   "Execute a block of C++ code with org-babel.
 This function is called by `org-babel-execute-src-block'."
   (let ((org-babel-c-variant 'cpp)) (org-babel-C-execute body params)))
 
 (defun org-babel-expand-body:C++ (body params)
-  "Expand a block of C++ code with org-babel according to it's
-header arguments (calls `org-babel-C-expand')."
-  (let ((org-babel-c-variant 'cpp)) (org-babel-C-expand body params)))
+  "Expand a block of C++ code with org-babel according to its
+header arguments."
+  (let ((org-babel-c-variant 'cpp)) (org-babel-C-expand-C++ body params)))
+
+(defun org-babel-execute:D (body params)
+  "Execute a block of D code with org-babel.
+This function is called by `org-babel-execute-src-block'."
+  (let ((org-babel-c-variant 'd)) (org-babel-C-execute body params)))
+
+(defun org-babel-expand-body:D (body params)
+  "Expand a block of D code with org-babel according to its
+header arguments."
+  (let ((org-babel-c-variant 'd)) (org-babel-C-expand-D body params)))
 
 (defun org-babel-execute:C (body params)
   "Execute a block of C code with org-babel.
 This function is called by `org-babel-execute-src-block'."
   (let ((org-babel-c-variant 'c)) (org-babel-C-execute body params)))
 
-(defun org-babel-expand-body:c (body params)
-  "Expand a block of C code with org-babel according to it's
-header arguments (calls `org-babel-C-expand')."
-  (let ((org-babel-c-variant 'c)) (org-babel-C-expand body params)))
+(defun org-babel-expand-body:C (body params)
+  "Expand a block of C code with org-babel according to its
+header arguments."
+  (let ((org-babel-c-variant 'c)) (org-babel-C-expand-C body params)))
 
 (defun org-babel-C-execute (body params)
   "This function should only be called by `org-babel-execute:C'
-or `org-babel-execute:C++'."
+or `org-babel-execute:C++' or `org-babel-execute:D'."
   (let* ((tmp-src-file (org-babel-temp-file
                        "C-src-"
-                       (cond
-                        ((equal org-babel-c-variant 'c) ".c")
-                        ((equal org-babel-c-variant 'cpp) ".cpp"))))
-         (tmp-bin-file (org-babel-temp-file "C-bin-" org-babel-exeext))
-         (cmdline (cdr (assoc :cmdline params)))
-         (flags (cdr (assoc :flags params)))
-         (full-body (org-babel-C-expand body params))
-         (compile
-         (progn
-           (with-temp-file tmp-src-file (insert full-body))
-           (org-babel-eval
-            (format "%s -o %s %s %s"
-                    (cond
-                     ((equal org-babel-c-variant 'c) org-babel-C-compiler)
-                     ((equal org-babel-c-variant 'cpp) org-babel-C++-compiler))
-                    (org-babel-process-file-name tmp-bin-file)
-                    (mapconcat 'identity
-                               (if (listp flags) flags (list flags)) " ")
-                    (org-babel-process-file-name tmp-src-file)) ""))))
+                       (pcase org-babel-c-variant
+                         (`c ".c") (`cpp ".cpp") (`d ".d"))))
+        (tmp-bin-file                  ;not used for D
+         (org-babel-process-file-name
+          (org-babel-temp-file "C-bin-" org-babel-exeext)))
+        (cmdline (cdr (assq :cmdline params)))
+        (cmdline (if cmdline (concat " " cmdline) ""))
+        (flags (cdr (assq :flags params)))
+        (flags (mapconcat 'identity
+                          (if (listp flags) flags (list flags)) " "))
+        (libs (org-babel-read
+               (or (cdr (assq :libs params))
+                   (org-entry-get nil "libs" t))
+               nil))
+        (libs (mapconcat #'identity
+                         (if (listp libs) libs (list libs))
+                         " "))
+        (full-body
+         (pcase org-babel-c-variant
+           (`c (org-babel-C-expand-C body params))
+           (`cpp (org-babel-C-expand-C++ body params))
+           (`d (org-babel-C-expand-D body params)))))
+    (with-temp-file tmp-src-file (insert full-body))
+    (pcase org-babel-c-variant
+      ((or `c `cpp)
+       (org-babel-eval
+       (format "%s -o %s %s %s %s"
+               (pcase org-babel-c-variant
+                 (`c org-babel-C-compiler)
+                 (`cpp org-babel-C++-compiler))
+               tmp-bin-file
+               flags
+               (org-babel-process-file-name tmp-src-file)
+               libs)
+       ""))
+      (`d nil)) ;; no separate compilation for D
     (let ((results
-           (org-babel-trim
-            (org-babel-eval
-             (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) ""))))
-      (org-babel-reassemble-table
-       (org-babel-result-cond (cdr (assoc :result-params params))
-        (org-babel-read results)
-         (let ((tmp-file (org-babel-temp-file "c-")))
-           (with-temp-file tmp-file (insert results))
-           (org-babel-import-elisp-from-file tmp-file)))
-       (org-babel-pick-name
-        (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
-       (org-babel-pick-name
-        (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))
-    ))
-
-(defun org-babel-C-expand (body params)
+          (org-babel-eval
+           (pcase org-babel-c-variant
+             ((or `c `cpp)
+              (concat tmp-bin-file cmdline))
+             (`d
+              (format "%s %s %s %s"
+                      org-babel-D-compiler
+                      flags
+                      (org-babel-process-file-name tmp-src-file)
+                      cmdline)))
+           "")))
+      (when results
+       (setq results (org-trim (org-remove-indentation results)))
+       (org-babel-reassemble-table
+        (org-babel-result-cond (cdr (assq :result-params params))
+          (org-babel-read results t)
+          (let ((tmp-file (org-babel-temp-file "c-")))
+            (with-temp-file tmp-file (insert results))
+            (org-babel-import-elisp-from-file tmp-file)))
+        (org-babel-pick-name
+         (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+        (org-babel-pick-name
+         (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))
+      )))
+
+(defun org-babel-C-expand-C++ (body params)
   "Expand a block of C or C++ code with org-babel according to
-it's header arguments."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-        (main-p (not (string= (cdr (assoc :main params)) "no")))
-        (includes (or (cdr (assoc :includes params))
-                      (org-babel-read (org-entry-get nil "includes" t))))
-        (defines (org-babel-read
-                  (or (cdr (assoc :defines params))
-                      (org-babel-read (org-entry-get nil "defines" t))))))
+its header arguments."
+  (org-babel-C-expand-C body params))
+
+(defun org-babel-C-expand-C (body params)
+  "Expand a block of C or C++ code with org-babel according to
+its header arguments."
+  (let ((vars (org-babel--get-vars params))
+       (colnames (cdr (assq :colname-names params)))
+       (main-p (not (string= (cdr (assq :main params)) "no")))
+       (includes (org-babel-read
+                  (or (cdr (assq :includes params))
+                      (org-entry-get nil "includes" t))
+                  nil))
+       (defines (org-babel-read
+                 (or (cdr (assq :defines params))
+                     (org-entry-get nil "defines" t))
+                 nil)))
+    (when (stringp includes)
+      (setq includes (split-string includes)))
+    (when (stringp defines)
+      (let ((y nil)
+           (result (list t)))
+       (dolist (x (split-string defines))
+         (if (null y)
+             (setq y x)
+           (nconc result (list (concat y " " x)))
+           (setq y nil)))
+       (setq defines (cdr result))))
     (mapconcat 'identity
               (list
                ;; includes
                (mapconcat
                 (lambda (inc) (format "#include %s" inc))
-                (if (listp includes) includes (list includes)) "\n")
+                includes "\n")
                ;; defines
                (mapconcat
                 (lambda (inc) (format "#define %s" inc))
                 (if (listp defines) defines (list defines)) "\n")
                ;; variables
                (mapconcat 'org-babel-C-var-to-C vars "\n")
+               ;; table sizes
+               (mapconcat 'org-babel-C-table-sizes-to-C vars "\n")
+               ;; tables headers utility
+               (when colnames
+                 (org-babel-C-utility-header-to-C))
+               ;; tables headers
+               (mapconcat 'org-babel-C-header-to-C colnames "\n")
+               ;; body
+               (if main-p
+                   (org-babel-C-ensure-main-wrap body)
+                 body) "\n") "\n")))
+
+(defun org-babel-C-expand-D (body params)
+  "Expand a block of D code with org-babel according to
+its header arguments."
+  (let ((vars (org-babel--get-vars params))
+       (colnames (cdr (assq :colname-names params)))
+       (main-p (not (string= (cdr (assq :main params)) "no")))
+       (imports (or (cdr (assq :imports params))
+                    (org-babel-read (org-entry-get nil "imports" t)))))
+    (when (stringp imports)
+      (setq imports (split-string imports)))
+    (setq imports (append imports '("std.stdio" "std.conv")))
+    (mapconcat 'identity
+              (list
+               "module mmm;"
+               ;; imports
+               (mapconcat
+                (lambda (inc) (format "import %s;" inc))
+                imports "\n")
+               ;; variables
+               (mapconcat 'org-babel-C-var-to-C vars "\n")
+               ;; table sizes
+               (mapconcat 'org-babel-C-table-sizes-to-C vars "\n")
+               ;; tables headers utility
+               (when colnames
+                 (org-babel-C-utility-header-to-C))
+               ;; tables headers
+               (mapconcat 'org-babel-C-header-to-C colnames "\n")
                ;; body
                (if main-p
                    (org-babel-C-ensure-main-wrap body)
@@ -154,12 +276,12 @@ it's header arguments."
       body
     (format "int main() {\n%s\nreturn 0;\n}\n" body)))
 
-(defun org-babel-prep-session:C (session params)
+(defun org-babel-prep-session:C (_session _params)
   "This function does nothing as C is a compiled language with no
 support for sessions"
   (error "C is a compiled language -- no support for sessions"))
 
-(defun org-babel-load-session:C (session body params)
+(defun org-babel-load-session:C (_session _body _params)
   "This function does nothing as C is a compiled language with no
 support for sessions"
   (error "C is a compiled language -- no support for sessions"))
@@ -177,58 +299,79 @@ support for sessions"
   "Determine the type of VAL.
 Return a list (TYPE-NAME FORMAT).  TYPE-NAME should be the name of the type.
 FORMAT can be either a format string or a function which is called with VAL."
+  (let* ((basetype (org-babel-C-val-to-base-type val))
+        (type
+         (pcase basetype
+           (`integerp '("int" "%d"))
+           (`floatp '("double" "%f"))
+           (`stringp
+            (list
+             (if (eq org-babel-c-variant 'd) "string" "const char*")
+             "\"%s\""))
+           (_ (error "unknown type %S" basetype)))))
+    (cond
+     ((integerp val) type) ;; an integer declared in the #+begin_src line
+     ((floatp val) type) ;; a numeric declared in the #+begin_src line
+     ((and (listp val) (listp (car val))) ;; a table
+      `(,(car type)
+       (lambda (val)
+         (cons
+          (format "[%d][%d]" (length val) (length (car val)))
+          (concat
+           (if (eq org-babel-c-variant 'd) "[\n" "{\n")
+           (mapconcat
+            (lambda (v)
+              (concat
+               (if (eq org-babel-c-variant 'd) " [" " {")
+               (mapconcat (lambda (w) (format ,(cadr type) w)) v ",")
+               (if (eq org-babel-c-variant 'd) "]" "}")))
+            val
+            ",\n")
+           (if (eq org-babel-c-variant 'd) "\n]" "\n}"))))))
+     ((or (listp val) (vectorp val)) ;; a list declared in the #+begin_src line
+      `(,(car type)
+       (lambda (val)
+         (cons
+          (format "[%d]" (length val))
+          (concat
+           (if (eq org-babel-c-variant 'd) "[" "{")
+           (mapconcat (lambda (v) (format ,(cadr type) v)) val ",")
+           (if (eq org-babel-c-variant 'd) "]" "}"))))))
+     (t ;; treat unknown types as string
+      type))))
+
+(defun org-babel-C-val-to-base-type (val)
+  "Determine the base type of VAL which may be
+`integerp' if all base values are integers
+`floatp' if all base values are either floating points or integers
+`stringp' otherwise."
   (cond
-   ((integerp val) '("int" "%d"))
-   ((floatp val) '("double" "%f"))
+   ((integerp val) 'integerp)
+   ((floatp val) 'floatp)
    ((or (listp val) (vectorp val))
-    (lexical-let ((type (org-babel-C-val-to-C-list-type val)))
-      (list (car type)
-           (lambda (val)
-             (cons
-              (format "[%d]%s"
-                      (length val)
-                      (car (org-babel-C-format-val type (elt val 0))))
-              (concat "{ "
-                      (mapconcat (lambda (v)
-                                   (cdr (org-babel-C-format-val type v)))
-                                 val
-                                 ", ")
-                      " }"))))))
-   (t ;; treat unknown types as string
-    '("char" (lambda (val)
-              (let ((s (format "%s" val))) ;; convert to string for unknown 
types
-                (cons (format "[%d]" (1+ (length s)))
-                      (concat "\"" s "\""))))))))
-
-(defun org-babel-C-val-to-C-list-type (val)
-  "Determine the C array type of a VAL."
-  (let (type)
-    (mapc
-     #'(lambda (i)
-        (let* ((tmp-type (org-babel-C-val-to-C-type i))
-               (type-name (car type))
-               (tmp-type-name (car tmp-type)))
-          (when (and type (not (string= type-name tmp-type-name)))
-            (if (and (member type-name '("int" "double" "int32_t"))
-                     (member tmp-type-name '("int" "double" "int32_t")))
-                (setq tmp-type '("double" "" "%f"))
-              (error "Only homogeneous lists are supported by C.  You can not 
mix %s and %s"
-                     type-name
-                     tmp-type-name)))
-          (setq type tmp-type)))
-     val)
-    type))
+    (let ((type nil))
+      (mapc (lambda (v)
+             (pcase (org-babel-C-val-to-base-type v)
+               (`stringp (setq type 'stringp))
+               (`floatp
+                (if (or (not type) (eq type 'integerp))
+                    (setq type 'floatp)))
+               (`integerp
+                (unless type (setq type 'integerp)))))
+           val)
+      type))
+   (t 'stringp)))
 
 (defun org-babel-C-var-to-C (pair)
   "Convert an elisp val into a string of C code specifying a var
 of the same value."
   ;; TODO list support
   (let ((var (car pair))
-        (val (cdr pair)))
+       (val (cdr pair)))
     (when (symbolp val)
       (setq val (symbol-name val))
       (when (= (length val) 1)
-        (setq val (string-to-char val))))
+       (setq val (string-to-char val))))
     (let* ((type-data (org-babel-C-val-to-C-type val))
           (type (car type-data))
           (formated (org-babel-C-format-val type-data val))
@@ -240,6 +383,66 @@ of the same value."
              suffix
              data))))
 
+(defun org-babel-C-table-sizes-to-C (pair)
+  "Create constants of table dimensions, if PAIR is a table."
+  (when (listp (cdr pair))
+    (cond
+     ((listp (cadr pair)) ;; a table
+      (concat
+       (format "const int %s_rows = %d;" (car pair) (length (cdr pair)))
+       "\n"
+       (format "const int %s_cols = %d;" (car pair) (length (cadr pair)))))
+     (t ;; a list declared in the #+begin_src line
+      (format "const int %s_cols = %d;" (car pair) (length (cdr pair)))))))
+
+(defun org-babel-C-utility-header-to-C ()
+  "Generate a utility function to convert a column name
+into a column number."
+  (pcase org-babel-c-variant
+    ((or `c `cpp)
+     "int get_column_num (int nbcols, const char** header, const char* column)
+{
+  int c;
+  for (c=0; c<nbcols; c++)
+    if (strcmp(header[c],column)==0)
+      return c;
+  return -1;
+}
+")
+    (`d
+     "int get_column_num (string[] header, string column)
+{
+  foreach (c, h; header)
+    if (h==column)
+      return to!int(c);
+  return -1;
+}
+")))
+
+(defun org-babel-C-header-to-C (head)
+  "Convert an elisp list of header table into a C or D vector
+specifying a variable with the name of the table."
+  (let ((table (car head))
+        (headers (cdr head)))
+    (concat
+     (format
+      (pcase org-babel-c-variant
+       ((or `c `cpp) "const char* %s_header[%d] = {%s};")
+       (`d "string %s_header[%d] = [%s];"))
+      table
+      (length headers)
+      (mapconcat (lambda (h) (format "%S" h)) headers ","))
+     "\n"
+     (pcase org-babel-c-variant
+       ((or `c `cpp)
+       (format
+        "const char* %s_h (int row, const char* col) { return 
%s[row][get_column_num(%d,%s_header,col)]; }"
+        table table (length headers) table))
+       (`d
+       (format
+        "string %s_h (size_t row, string col) { return 
%s[row][get_column_num(%s_header,col)]; }"
+        table table table))))))
+
 (provide 'ob-C)
 
 ;;; ob-C.el ends here
diff --git a/lisp/org/ob-J.el b/lisp/org/ob-J.el
new file mode 100644
index 0000000..eba4bc6
--- /dev/null
+++ b/lisp/org/ob-J.el
@@ -0,0 +1,186 @@
+;;; ob-J.el --- Babel Functions for J                -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating J code.
+;;
+;; Session interaction depends on `j-console' from package `j-mode'
+;; (available in MELPA).
+
+;;; Code:
+
+(require 'ob)
+
+(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function j-console-ensure-session "ext:j-console" ())
+
+(defcustom org-babel-J-command "jconsole"
+  "Command to call J."
+  :group 'org-babel
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type 'string)
+
+(defun org-babel-expand-body:J (body _params &optional _processed-params)
+  "Expand BODY according to PARAMS, return the expanded body.
+PROCESSED-PARAMS isn't used yet."
+  (org-babel-J-interleave-echos-except-functions body))
+
+(defun org-babel-J-interleave-echos (body)
+  "Interleave echo',' between each source line of BODY."
+  (mapconcat #'identity (split-string body "\n") "\necho','\n"))
+
+(defun org-babel-J-interleave-echos-except-functions (body)
+  "Interleave echo',' between source lines of BODY that aren't functions."
+  (if (obj-string-match-m 
"\\(?:^\\|\n\\)[^\n]*\\(?:0\\|1\\|2\\|3\\|4\\|dyad\\) : 0\n.*\n)\\(?:\n\\|$\\)" 
body)
+      (let ((s1 (substring body 0 (match-beginning 0)))
+           (s2 (match-string 0 body))
+           (s3 (substring body (match-end 0))))
+       (concat
+        (if (string= s1 "")
+            ""
+          (concat (org-babel-J-interleave-echos s1)
+                  "\necho','\n"))
+        s2
+        "\necho','\n"
+        (org-babel-J-interleave-echos-except-functions s3)))
+    (org-babel-J-interleave-echos body)))
+
+(defalias 'org-babel-execute:j 'org-babel-execute:J)
+
+(defun org-babel-execute:J (body params)
+  "Execute a block of J code BODY.
+PARAMS are given by org-babel.
+This function is called by `org-babel-execute-src-block'"
+  (message "executing J source code block")
+  (let* ((processed-params (org-babel-process-params params))
+        (sessionp (cdr (assq :session params)))
+         (full-body (org-babel-expand-body:J
+                     body params processed-params))
+        (tmp-script-file (org-babel-temp-file "J-src")))
+    (org-babel-j-initiate-session sessionp)
+    (org-babel-J-strip-whitespace
+     (if (string= sessionp "none")
+        (progn
+          (with-temp-file tmp-script-file
+            (insert full-body))
+          (org-babel-eval (format "%s < %s" org-babel-J-command 
tmp-script-file) ""))
+       (org-babel-J-eval-string full-body)))))
+
+(defun org-babel-J-eval-string (str)
+  "Sends STR to the `j-console-cmd' session and exectues it."
+  (let ((session (j-console-ensure-session)))
+    (with-current-buffer (process-buffer session)
+      (goto-char (point-max))
+      (insert (format "\n%s\n" str))
+      (let ((beg (point)))
+       (comint-send-input)
+       (sit-for .1)
+       (buffer-substring-no-properties
+        beg (point-max))))))
+
+(defun org-babel-J-strip-whitespace (str)
+  "Remove whitespace from jconsole output STR."
+  (mapconcat
+   #'identity
+   (delete "" (mapcar
+              #'org-babel-J-print-block
+              (split-string str "^ *,\n" t)))
+   "\n\n"))
+
+(defun obj-get-string-alignment (str)
+  "Return a number to describe STR alignment.
+STR represents a table.
+Positive/negative/zero result means right/left/undetermined.
+Don't trust first line."
+  (let* ((str (org-trim str))
+        (lines (split-string str "\n" t))
+        n1 n2)
+    (cond ((<= (length lines) 1)
+          0)
+         ((= (length lines) 2)
+          ;; numbers are right-aligned
+          (if (and
+               (numberp (read (car lines)))
+               (numberp (read (cadr lines)))
+               (setq n1 (obj-match-second-space-right (nth 0 lines)))
+               (setq n2 (obj-match-second-space-right (nth 1 lines))))
+              n2
+            0))
+         ((not (obj-match-second-space-left (nth 0 lines)))
+          0)
+         ((and
+           (setq n1 (obj-match-second-space-left (nth 1 lines)))
+           (setq n2 (obj-match-second-space-left (nth 2 lines)))
+           (= n1 n2))
+          n1)
+         ((and
+           (setq n1 (obj-match-second-space-right (nth 1 lines)))
+           (setq n2 (obj-match-second-space-right (nth 2 lines)))
+           (= n1 n2))
+          (- n1))
+         (t 0))))
+
+(defun org-babel-J-print-block (x)
+  "Prettify jconsole output X."
+  (let* ((x (org-trim x))
+        (a (obj-get-string-alignment x))
+        (lines (split-string x "\n" t))
+        b)
+    (cond ((< a 0)
+          (setq b (obj-match-second-space-right (nth 0 lines)))
+          (concat (make-string (+ a b) ? ) x))
+         ((> a 0)
+          (setq b (obj-match-second-space-left (nth 0 lines)))
+          (concat (make-string (- a b) ? ) x))
+         (t x))))
+
+(defun obj-match-second-space-left (s)
+  "Return position of leftmost space in second space block of S or nil."
+  (and (string-match "^ *[^ ]+\\( \\)" s)
+       (match-beginning 1)))
+
+(defun obj-match-second-space-right (s)
+  "Return position of rightmost space in second space block of S or nil."
+  (and (string-match "^ *[^ ]+ *\\( \\)[^ ]" s)
+       (match-beginning 1)))
+
+(defun obj-string-match-m (regexp string &optional start)
+  "Call (string-match REGEXP STRING START).
+REGEXP is modified so that .* matches newlines as well."
+  (string-match
+   (replace-regexp-in-string "\\.\\*" "[\0-\377[:nonascii:]]*" regexp)
+   string
+   start))
+
+(defun org-babel-j-initiate-session (&optional session)
+  "Initiate a J session.
+SESSION is a parameter given by org-babel."
+  (unless (string= session "none")
+    (require 'j-console)
+    (j-console-ensure-session)))
+
+(provide 'ob-J)
+
+;;; ob-J.el ends here
diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el
index 51d3427..3accade 100644
--- a/lisp/org/ob-R.el
+++ b/lisp/org/ob-R.el
@@ -1,4 +1,4 @@
-;;; ob-R.el --- org-babel functions for R code evaluation
+;;; ob-R.el --- Babel Functions for R                -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -27,16 +27,17 @@
 ;; Org-Babel support for evaluating R code
 
 ;;; Code:
+
+(require 'cl-lib)
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function orgtbl-to-tsv "org-table" (table params))
 (declare-function R "ext:essd-r" (&optional start-args))
 (declare-function inferior-ess-send-input "ext:ess-inf" ())
 (declare-function ess-make-buffer-current "ext:ess-inf" ())
 (declare-function ess-eval-buffer "ext:ess-inf" (vis))
-(declare-function org-number-sequence "org-compat" (from &optional to inc))
-(declare-function org-remove-if-not "org" (predicate seq))
+(declare-function ess-wait-for-process "ext:ess-inf"
+                 (&optional proc sec-prompt wait force-redisplay))
 
 (defconst org-babel-header-args:R
   '((width              . :any)
@@ -60,12 +61,25 @@
     (useDingbats        . :any)
     (horizontal                 . :any)
     (results             . ((file list vector table scalar verbatim)
-                           (raw org html latex code pp wrap)
-                           (replace silent append prepend)
+                           (raw html latex org code pp drawer)
+                           (replace silent none append prepend)
                            (output value graphics))))
   "R-specific header arguments.")
 
+(defconst ob-R-safe-header-args
+  (append org-babel-safe-header-args
+         '(:width :height :bg :units :pointsize :antialias :quality
+                  :compression :res :type :family :title :fonts
+                  :version :paper :encoding :pagecentre :colormodel
+                  :useDingbats :horizontal))
+  "Header args which are safe for R babel blocks.
+
+See `org-babel-safe-header-args' for documentation of the format of
+this variable.")
+
 (defvar org-babel-default-header-args:R '())
+(put 'org-babel-default-header-args:R 'safe-local-variable
+     (org-babel-header-args-safe-fn ob-R-safe-header-args))
 
 (defcustom org-babel-R-command "R --slave --no-save"
   "Name of command to use for executing R code."
@@ -73,56 +87,103 @@
   :version "24.1"
   :type 'string)
 
-(defvar ess-local-process-name) ; dynamically scoped
+(defvar ess-current-process-name) ; dynamically scoped
+(defvar ess-local-process-name)   ; dynamically scoped
 (defun org-babel-edit-prep:R (info)
-  (let ((session (cdr (assoc :session (nth 2 info)))))
-    (when (and session (string-match "^\\*\\(.+?\\)\\*$" session))
-      (save-match-data (org-babel-R-initiate-session session nil)))))
-
-(defun org-babel-expand-body:R (body params &optional graphics-file)
+  (let ((session (cdr (assq :session (nth 2 info)))))
+    (when (and session
+              (string-prefix-p "*"  session)
+              (string-suffix-p "*" session))
+      (org-babel-R-initiate-session session nil))))
+
+;; The usage of utils::read.table() ensures that the command
+;; read.table() can be found even in circumstances when the utils
+;; package is not in the search path from R.
+(defconst ob-R-transfer-variable-table-with-header
+  "%s <- local({
+     con <- textConnection(
+       %S
+     )
+     res <- utils::read.table(
+       con,
+       header    = %s,
+       row.names = %s,
+       sep       = \"\\t\",
+       as.is     = TRUE
+     )
+     close(con)
+     res
+   })"
+  "R code used to transfer a table defined as a variable from org to R.
+
+This function is used when the table contains a header.")
+
+(defconst ob-R-transfer-variable-table-without-header
+  "%s <- local({
+     con <- textConnection(
+       %S
+     )
+     res <- utils::read.table(
+       con,
+       header    = %s,
+       row.names = %s,
+       sep       = \"\\t\",
+       as.is     = TRUE,
+       fill      = TRUE,
+       col.names = paste(\"V\", seq_len(%d), sep =\"\")
+     )
+     close(con)
+     res
+   })"
+  "R code used to transfer a table defined as a variable from org to R.
+
+This function is used when the table does not contain a header.")
+
+(defun org-babel-expand-body:R (body params &optional _graphics-file)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((graphics-file
-        (or graphics-file (org-babel-R-graphical-output-file params))))
-    (mapconcat
-     #'identity
-     (let ((inside
-            (append
-             (when (cdr (assoc :prologue params))
-               (list (cdr (assoc :prologue params))))
-             (org-babel-variable-assignments:R params)
-             (list body)
-             (when (cdr (assoc :epilogue params))
-               (list (cdr (assoc :epilogue params)))))))
-       (if graphics-file
-           (append
-            (list (org-babel-R-construct-graphics-device-call
-                   graphics-file params))
-            inside
-            (list "dev.off()"))
-         inside))
-     "\n")))
+  (mapconcat 'identity
+            (append
+             (when (cdr (assq :prologue params))
+               (list (cdr (assq :prologue params))))
+             (org-babel-variable-assignments:R params)
+             (list body)
+             (when (cdr (assq :epilogue params))
+               (list (cdr (assq :epilogue params)))))
+            "\n"))
 
 (defun org-babel-execute:R (body params)
   "Execute a block of R code.
 This function is called by `org-babel-execute-src-block'."
   (save-excursion
-    (let* ((result-params (cdr (assoc :result-params params)))
-          (result-type (cdr (assoc :result-type params)))
+    (let* ((result-params (cdr (assq :result-params params)))
+          (result-type (cdr (assq :result-type params)))
            (session (org-babel-R-initiate-session
-                    (cdr (assoc :session params)) params))
-          (colnames-p (cdr (assoc :colnames params)))
-          (rownames-p (cdr (assoc :rownames params)))
-          (graphics-file (org-babel-R-graphical-output-file params))
-          (full-body (org-babel-expand-body:R body params graphics-file))
+                    (cdr (assq :session params)) params))
+          (colnames-p (cdr (assq :colnames params)))
+          (rownames-p (cdr (assq :rownames params)))
+          (graphics-file (and (member "graphics" (assq :result-params params))
+                              (org-babel-graphical-output-file params)))
+          (full-body
+           (let ((inside
+                  (list (org-babel-expand-body:R body params graphics-file))))
+             (mapconcat 'identity
+                        (if graphics-file
+                            (append
+                             (list (org-babel-R-construct-graphics-device-call
+                                    graphics-file params))
+                             inside
+                             (list "},error=function(e){plot(x=-1:1, y=-1:1, 
type='n', xlab='', ylab='', axes=FALSE); text(x=0, y=0, labels=e$message, 
col='red'); paste('ERROR', e$message, sep=' : ')}); dev.off()"))
+                          inside)
+                        "\n")))
           (result
            (org-babel-R-evaluate
             session full-body result-type result-params
             (or (equal "yes" colnames-p)
                 (org-babel-pick-name
-                 (cdr (assoc :colname-names params)) colnames-p))
+                 (cdr (assq :colname-names params)) colnames-p))
             (or (equal "yes" rownames-p)
                 (org-babel-pick-name
-                 (cdr (assoc :rowname-names params)) rownames-p)))))
+                 (cdr (assq :rowname-names params)) rownames-p)))))
       (if graphics-file nil result))))
 
 (defun org-babel-prep-session:R (session params)
@@ -148,21 +209,21 @@ This function is called by `org-babel-execute-src-block'."
 
 (defun org-babel-variable-assignments:R (params)
   "Return list of R statements assigning the block's variables."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (mapcar
      (lambda (pair)
        (org-babel-R-assign-elisp
        (car pair) (cdr pair)
-       (equal "yes" (cdr (assoc :colnames params)))
-       (equal "yes" (cdr (assoc :rownames params)))))
+       (equal "yes" (cdr (assq :colnames params)))
+       (equal "yes" (cdr (assq :rownames params)))))
      (mapcar
       (lambda (i)
        (cons (car (nth i vars))
              (org-babel-reassemble-table
               (cdr (nth i vars))
-              (cdr (nth i (cdr (assoc :colname-names params))))
-              (cdr (nth i (cdr (assoc :rowname-names params)))))))
-      (org-number-sequence 0 (1- (length vars)))))))
+              (cdr (nth i (cdr (assq :colname-names params))))
+              (cdr (nth i (cdr (assq :rowname-names params)))))))
+      (number-sequence 0 (1- (length vars)))))))
 
 (defun org-babel-R-quote-tsv-field (s)
   "Quote field S for export to R."
@@ -173,35 +234,25 @@ This function is called by `org-babel-execute-src-block'."
 (defun org-babel-R-assign-elisp (name value colnames-p rownames-p)
   "Construct R code assigning the elisp VALUE to a variable named NAME."
   (if (listp value)
-      (let* ((lengths (mapcar 'length (org-remove-if-not 'sequencep value)))
+      (let* ((lengths (mapcar 'length (cl-remove-if-not 'sequencep value)))
             (max (if lengths (apply 'max lengths) 0))
-            (min (if lengths (apply 'min lengths) 0))
-            (transition-file (org-babel-temp-file "R-import-")))
+            (min (if lengths (apply 'min lengths) 0)))
         ;; Ensure VALUE has an orgtbl structure (depth of at least 2).
         (unless (listp (car value)) (setq value (list value)))
-        (with-temp-file transition-file
-          (insert
-          (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field))
-          "\n"))
-       (let ((file (org-babel-process-file-name transition-file 'noquote))
+       (let ((file (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
              (header (if (or (eq (nth 1 value) 'hline) colnames-p)
                          "TRUE" "FALSE"))
              (row-names (if rownames-p "1" "NULL")))
          (if (= max min)
-             (format "%s <- read.table(\"%s\",
-                      header=%s,
-                      row.names=%s,
-                      sep=\"\\t\",
-                      as.is=TRUE)" name file header row-names)
-           (format "%s <- read.table(\"%s\",
-                   header=%s,
-                   row.names=%s,
-                   sep=\"\\t\",
-                   as.is=TRUE,
-                   fill=TRUE,
-                   col.names = paste(\"V\", seq_len(%d), sep =\"\"))"
+             (format ob-R-transfer-variable-table-with-header
+                     name file header row-names)
+           (format ob-R-transfer-variable-table-without-header
                    name file header row-names max))))
-    (format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
+    (cond ((integerp value) (format "%s <- %s" name (concat (number-to-string 
value) "L")))
+         ((floatp   value) (format "%s <- %s" name value))
+         ((stringp  value) (format "%s <- %S" name (org-no-properties value)))
+         (t                (format "%s <- %S" name (prin1-to-string value))))))
+
 
 (defvar ess-ask-for-ess-directory) ; dynamically scoped
 (defun org-babel-R-initiate-session (session params)
@@ -209,8 +260,9 @@ This function is called by `org-babel-execute-src-block'."
   (unless (string= session "none")
     (let ((session (or session "*R*"))
          (ess-ask-for-ess-directory
-          (and (and (boundp 'ess-ask-for-ess-directory) 
ess-ask-for-ess-directory)
-               (not (cdr (assoc :dir params))))))
+          (and (boundp 'ess-ask-for-ess-directory)
+               ess-ask-for-ess-directory
+               (not (cdr (assq :dir params))))))
       (if (org-babel-comint-buffer-livep session)
          session
        (save-window-excursion
@@ -218,6 +270,10 @@ This function is called by `org-babel-execute-src-block'."
            ;; Session buffer exists, but with dead process
            (set-buffer session))
          (require 'ess) (R)
+         (let ((R-proc (get-process (or ess-local-process-name
+                                        ess-current-process-name))))
+           (while (process-get R-proc 'callbacks)
+             (ess-wait-for-process R-proc)))
          (rename-buffer
           (if (bufferp session)
               (buffer-name session)
@@ -234,11 +290,6 @@ current code buffer."
        (process-name (get-buffer-process session)))
   (ess-make-buffer-current))
 
-(defun org-babel-R-graphical-output-file (params)
-  "Name of file to which R should send graphical output."
-  (and (member "graphics" (cdr (assq :result-params params)))
-       (cdr (assq :file params))))
-
 (defvar org-babel-R-graphics-devices
   '((:bmp "bmp" "filename")
     (:jpg "jpeg" "filename")
@@ -265,8 +316,7 @@ Each member of this list is a list with three members:
                                :type :family :title :fonts :version
                                :paper :encoding :pagecentre :colormodel
                                :useDingbats :horizontal))
-        (device (and (string-match ".+\\.\\([^.]+\\)" out-file)
-                     (match-string 1 out-file)))
+        (device (file-name-extension out-file))
         (device-info (or (assq (intern (concat ":" device))
                                org-babel-R-graphics-devices)
                           (assq :png org-babel-R-graphics-devices)))
@@ -280,14 +330,43 @@ Each member of this list is a list with three members:
                              (substring (symbol-name (car pair)) 1)
                              (cdr pair)) ""))
                params ""))
-    (format "%s(%s=\"%s\"%s%s%s)"
+    (format "%s(%s=\"%s\"%s%s%s); tryCatch({"
            device filearg out-file args
            (if extra-args "," "") (or extra-args ""))))
 
-(defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
-(defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
-
-(defvar org-babel-R-write-object-command 
"{function(object,transfer.file){object;invisible(if(inherits(try({tfile<-tempfile();write.table(object,file=tfile,sep=\"\\t\",na=\"nil\",row.names=%s,col.names=%s,quote=FALSE);file.rename(tfile,transfer.file)},silent=TRUE),\"try-error\")){if(!file.exists(transfer.file))file.create(transfer.file)})}}(object=%s,transfer.file=\"%s\")")
+(defconst org-babel-R-eoe-indicator "'org_babel_R_eoe'")
+(defconst org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
+
+(defconst org-babel-R-write-object-command "{
+    function(object,transfer.file) {
+        object
+        invisible(
+            if (
+                inherits(
+                    try(
+                        {
+                            tfile<-tempfile()
+                            write.table(object, file=tfile, sep=\"\\t\",
+                                        na=\"nil\",row.names=%s,col.names=%s,
+                                        quote=FALSE)
+                            file.rename(tfile,transfer.file)
+                        },
+                        silent=TRUE),
+                    \"try-error\"))
+                {
+                    if(!file.exists(transfer.file))
+                        file.create(transfer.file)
+                }
+            )
+    }
+}(object=%s,transfer.file=\"%s\")"
+  "A template for an R command to evaluate a block of code and write the 
result to a file.
+
+Has four %s escapes to be filled in:
+1. Row names, \"TRUE\" or \"FALSE\"
+2. Column names, \"TRUE\" or \"FALSE\"
+3. The code to be run (must be an expression, not a statement)
+4. The name of the file to write to")
 
 (defun org-babel-R-evaluate
   (session body result-type result-params column-names-p row-names-p)
@@ -299,12 +378,12 @@ Each member of this list is a list with three members:
      body result-type result-params column-names-p row-names-p)))
 
 (defun org-babel-R-evaluate-external-process
-  (body result-type result-params column-names-p row-names-p)
+    (body result-type result-params column-names-p row-names-p)
   "Evaluate BODY in external R process.
-If RESULT-TYPE equals 'output then return standard output as a
-string.  If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string.  If RESULT-TYPE equals `value' then return the value of the
 last statement in BODY, as elisp."
-  (case result-type
+  (cl-case result-type
     (value
      (let ((tmp-file (org-babel-temp-file "R-")))
        (org-babel-eval org-babel-R-command
@@ -319,7 +398,7 @@ last statement in BODY, as elisp."
        (org-babel-result-cond result-params
          (with-temp-buffer
            (insert-file-contents tmp-file)
-           (buffer-string))
+           (org-babel-chomp (buffer-string) "\n"))
          (org-babel-import-elisp-from-file tmp-file '(16)))
        column-names-p)))
     (output (org-babel-eval org-babel-R-command body))))
@@ -327,12 +406,12 @@ last statement in BODY, as elisp."
 (defvar ess-eval-visibly-p)
 
 (defun org-babel-R-evaluate-session
-  (session body result-type result-params column-names-p row-names-p)
+    (session body result-type result-params column-names-p row-names-p)
   "Evaluate BODY in SESSION.
-If RESULT-TYPE equals 'output then return standard output as a
-string.  If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string.  If RESULT-TYPE equals `value' then return the value of the
 last statement in BODY, as elisp."
-  (case result-type
+  (cl-case result-type
     (value
      (with-temp-buffer
        (insert (org-babel-chomp body))
@@ -353,12 +432,12 @@ last statement in BODY, as elisp."
        (org-babel-result-cond result-params
          (with-temp-buffer
            (insert-file-contents tmp-file)
-           (buffer-string))
+           (org-babel-chomp (buffer-string) "\n"))
          (org-babel-import-elisp-from-file tmp-file '(16)))
        column-names-p)))
     (output
      (mapconcat
-      #'org-babel-chomp
+      'org-babel-chomp
       (butlast
        (delq nil
             (mapcar
@@ -366,11 +445,12 @@ last statement in BODY, as elisp."
              (mapcar
               (lambda (line) ;; cleanup extra prompts left in output
                 (if (string-match
-                     "^\\([ ]*[>+\\.][ ]?\\)+\\([[0-9]+\\|[ ]\\)" line)
+                     "^\\([>+.]\\([ ][>.+]\\)*[ ]\\)"
+                     (car (split-string line "\n")))
                     (substring line (match-end 1))
                   line))
               (org-babel-comint-with-output (session org-babel-R-eoe-output)
-                (insert (mapconcat #'org-babel-chomp
+                (insert (mapconcat 'org-babel-chomp
                                    (list body org-babel-R-eoe-indicator)
                                    "\n"))
                 (inferior-ess-send-input)))))) "\n"))))
diff --git a/lisp/org/ob-abc.el b/lisp/org/ob-abc.el
new file mode 100644
index 0000000..0ce503d
--- /dev/null
+++ b/lisp/org/ob-abc.el
@@ -0,0 +1,92 @@
+;;; ob-abc.el --- Org Babel Functions for ABC -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+;; Author: William Waites
+;; Keywords: literate programming, music
+;; Homepage: http://www.tardis.ed.ac.uk/wwaites
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; This file adds support to Org Babel for music in ABC notation.
+;;; It requires that the abcm2ps program is installed.
+;;; See http://moinejf.free.fr/
+
+(require 'ob)
+
+;; optionally define a file extension for this language
+(add-to-list 'org-babel-tangle-lang-exts '("abc" . "abc"))
+
+;; optionally declare default header arguments for this language
+(defvar org-babel-default-header-args:abc
+  '((:results . "file") (:exports . "results"))
+  "Default arguments to use when evaluating an ABC source block.")
+
+(defun org-babel-expand-body:abc (body params)
+  "Expand BODY according to PARAMS, return the expanded body."
+  (let ((vars (org-babel--get-vars params)))
+    (mapc
+     (lambda (pair)
+       (let ((name (symbol-name (car pair)))
+            (value (cdr pair)))
+        (setq body
+              (replace-regexp-in-string
+               (concat "\$" (regexp-quote name))
+               (if (stringp value) value (format "%S" value))
+               body))))
+     vars)
+    body))
+
+(defun org-babel-execute:abc (body params)
+  "Execute a block of ABC code with org-babel.  This function is
+   called by `org-babel-execute-src-block'"
+  (message "executing Abc source code block")
+  (let* ((cmdline (cdr (assq :cmdline params)))
+        (out-file (let ((file (cdr (assq :file params))))
+                    (if file (replace-regexp-in-string "\.pdf$" ".ps" file)
+                      (error "abc code block requires :file header 
argument"))))
+        (in-file (org-babel-temp-file "abc-"))
+        (render (concat "abcm2ps" " " cmdline
+                     " -O " (org-babel-process-file-name out-file)
+                     " " (org-babel-process-file-name in-file))))
+    (with-temp-file in-file (insert (org-babel-expand-body:abc body params)))
+    (org-babel-eval render "")
+    ;;; handle where abcm2ps changes the file name (to support multiple files
+    (when (or (string= (file-name-extension out-file) "eps")
+             (string= (file-name-extension out-file) "svg"))
+      (rename-file (concat
+                   (file-name-sans-extension out-file) "001."
+                   (file-name-extension out-file))
+                  out-file t))
+    ;;; if we were asked for a pdf...
+    (when (string= (file-name-extension (cdr (assq :file params))) "pdf")
+      (org-babel-eval (concat "ps2pdf" " " out-file " " (cdr (assq :file 
params))) ""))
+    ;;; indicate that the file has been written
+    nil))
+
+;; This function should be used to assign any variables in params in
+;; the context of the session environment.
+(defun org-babel-prep-session:abc (_session _params)
+  "Return an error because abc does not support sessions."
+  (error "ABC does not support sessions"))
+
+(provide 'ob-abc)
+;;; ob-abc.el ends here
diff --git a/lisp/org/ob-asymptote.el b/lisp/org/ob-asymptote.el
index e3b73c1..1dbf484 100644
--- a/lisp/org/ob-asymptote.el
+++ b/lisp/org/ob-asymptote.el
@@ -1,4 +1,4 @@
-;;; ob-asymptote.el --- org-babel functions for asymptote evaluation
+;;; ob-asymptote.el --- Babel Functions for Asymptote -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -43,11 +43,6 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
-
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
-(declare-function org-combine-plists "org" (&rest plists))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("asymptote" . "asy"))
@@ -59,13 +54,10 @@
 (defun org-babel-execute:asymptote (body params)
   "Execute a block of Asymptote code.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
-         (out-file (cdr (assoc :file params)))
-         (format (or (and out-file
-                          (string-match ".+\\.\\(.+\\)" out-file)
-                          (match-string 1 out-file))
+  (let* ((out-file (cdr (assq :file params)))
+         (format (or (file-name-extension out-file)
                      "pdf"))
-         (cmdline (cdr (assoc :cmdline params)))
+         (cmdline (cdr (assq :cmdline params)))
          (in-file (org-babel-temp-file "asymptote-"))
          (cmd
          (concat "asy "
@@ -83,7 +75,7 @@ This function is called by `org-babel-execute-src-block'."
     (message cmd) (shell-command cmd)
     nil)) ;; signal that output has already been written to file
 
-(defun org-babel-prep-session:asymptote (session params)
+(defun org-babel-prep-session:asymptote (_session _params)
   "Return an error if the :session header argument is set.
 Asymptote does not support sessions"
   (error "Asymptote does not support sessions"))
@@ -91,7 +83,7 @@ Asymptote does not support sessions"
 (defun org-babel-variable-assignments:asymptote (params)
   "Return list of asymptote statements assigning the block's variables."
   (mapcar #'org-babel-asymptote-var-to-asymptote
-         (mapcar #'cdr (org-babel-get-header params :var))))
+         (org-babel--get-vars params)))
 
 (defun org-babel-asymptote-var-to-asymptote (pair)
   "Convert an elisp value into an Asymptote variable.
@@ -128,21 +120,17 @@ a variable of the same value."
 
 DATA is a list.  Return type as a symbol.
 
-The type is `string' if any element in DATA is
-a string.  Otherwise, it is either `real', if some elements are
-floats, or `int'."
-  (let* ((type 'int)
-        find-type                      ; for byte-compiler
-        (find-type
-         (function
-          (lambda (row)
-            (catch 'exit
-              (mapc (lambda (el)
-                      (cond ((listp el) (funcall find-type el))
-                            ((stringp el) (throw 'exit (setq type 'string)))
-                            ((floatp el) (setq type 'real))))
-                    row))))))
-    (funcall find-type data) type))
+The type is `string' if any element in DATA is a string.
+Otherwise, it is either `real', if some elements are floats, or
+`int'."
+  (letrec ((type 'int)
+          (find-type
+           (lambda (row)
+             (dolist (e row type)
+               (cond ((listp e) (setq type (funcall find-type e)))
+                     ((stringp e) (throw 'exit 'string))
+                     ((floatp e) (setq type 'real)))))))
+    (catch 'exit (funcall find-type data)) type))
 
 (provide 'ob-asymptote)
 
diff --git a/lisp/org/ob-awk.el b/lisp/org/ob-awk.el
index c2ac5ca..2db4eea 100644
--- a/lisp/org/ob-awk.el
+++ b/lisp/org/ob-awk.el
@@ -1,4 +1,4 @@
-;;; ob-awk.el --- org-babel functions for awk evaluation
+;;; ob-awk.el --- Babel Functions for Awk            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -27,17 +27,15 @@
 ;;
 ;; - :in-file takes a path to a file of data to be processed by awk
 ;;
-;; - :stdin takes an Org-mode data or code block reference, the value
-;;          of which will be passed to the awk process through STDIN
+;; - :stdin takes an Org data or code block reference, the value of
+;;          which will be passed to the awk process through STDIN
 
 ;;; Code:
 (require 'ob)
 (require 'org-compat)
-(eval-when-compile (require 'cl))
 
 (declare-function org-babel-ref-resolve "ob-ref" (ref))
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
+(declare-function orgtbl-to-generic "org-table" (table params))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("awk" . "awk"))
@@ -45,34 +43,38 @@
 (defvar org-babel-awk-command "awk"
   "Name of the awk executable command.")
 
-(defun org-babel-expand-body:awk (body params)
+(defun org-babel-expand-body:awk (body _params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (dolist (pair (mapcar #'cdr (org-babel-get-header params :var)))
-    (setf body (replace-regexp-in-string
-                (regexp-quote (format "$%s" (car pair))) (cdr pair) body)))
   body)
 
 (defun org-babel-execute:awk (body params)
   "Execute a block of Awk code with org-babel.  This function is
 called by `org-babel-execute-src-block'"
   (message "executing Awk source code block")
-  (let* ((result-params (cdr (assoc :result-params params)))
-         (cmd-line (cdr (assoc :cmd-line params)))
-         (in-file (cdr (assoc :in-file params)))
+  (let* ((result-params (cdr (assq :result-params params)))
+         (cmd-line (cdr (assq :cmd-line params)))
+         (in-file (cdr (assq :in-file params)))
         (full-body (org-babel-expand-body:awk body params))
         (code-file (let ((file (org-babel-temp-file "awk-")))
                       (with-temp-file file (insert full-body)) file))
-        (stdin (let ((stdin (cdr (assoc :stdin params))))
+        (stdin (let ((stdin (cdr (assq :stdin params))))
                   (when stdin
                     (let ((tmp (org-babel-temp-file "awk-stdin-"))
                           (res (org-babel-ref-resolve stdin)))
                       (with-temp-file tmp
                         (insert (org-babel-awk-var-to-awk res)))
                       tmp))))
-         (cmd (mapconcat #'identity (remove nil (list org-babel-awk-command
-                                                     "-f" code-file
-                                                     cmd-line
-                                                     in-file))
+         (cmd (mapconcat #'identity
+                        (append
+                         (list org-babel-awk-command
+                               "-f" code-file cmd-line)
+                         (mapcar (lambda (pair)
+                                   (format "-v %s='%s'"
+                                           (car pair)
+                                           (org-babel-awk-var-to-awk
+                                            (cdr pair))))
+                                 (org-babel--get-vars params))
+                         (list in-file))
                         " ")))
     (org-babel-reassemble-table
      (let ((results
@@ -88,9 +90,9 @@ called by `org-babel-execute-src-block'"
             (with-temp-file tmp (insert results))
             (org-babel-import-elisp-from-file tmp)))))
      (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
      (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
 
 (defun org-babel-awk-var-to-awk (var &optional sep)
   "Return a printed value of VAR suitable for parsing with awk."
@@ -102,11 +104,6 @@ called by `org-babel-execute-src-block'"
       (mapconcat echo-var var "\n"))
      (t (funcall echo-var var)))))
 
-(defun org-babel-awk-table-or-string (results)
-  "If the results look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
-  (org-babel-script-escape results))
-
 (provide 'ob-awk)
 
 
diff --git a/lisp/org/ob-calc.el b/lisp/org/ob-calc.el
index 6298bba..d4b7260 100644
--- a/lisp/org/ob-calc.el
+++ b/lisp/org/ob-calc.el
@@ -1,4 +1,4 @@
-;;; ob-calc.el --- org-babel functions for calc code evaluation
+;;; ob-calc.el --- Babel Functions for Calc          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -28,18 +28,18 @@
 ;;; Code:
 (require 'ob)
 (require 'calc)
-(unless (featurep 'xemacs)
-  (require 'calc-trail)
-  (require 'calc-store))
+(require 'calc-trail)
+(require 'calc-store)
 
 (declare-function calc-store-into    "calc-store" (&optional var))
 (declare-function calc-recall        "calc-store" (&optional var))
 (declare-function math-evaluate-expr "calc-ext"   (x))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-default-header-args:calc nil
   "Default arguments for evaluating an calc source block.")
 
-(defun org-babel-expand-body:calc (body params)
+(defun org-babel-expand-body:calc (body _params)
   "Expand BODY according to PARAMS, return the expanded body." body)
 
 (defvar org--var-syms) ; Dynamically scoped from org-babel-execute:calc
@@ -48,7 +48,7 @@
   "Execute a block of calc code with Babel."
   (unless (get-buffer "*Calculator*")
     (save-window-excursion (calc) (calc-quit)))
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
+  (let* ((vars (org-babel--get-vars params))
         (org--var-syms (mapcar #'car vars))
         (var-names (mapcar #'symbol-name org--var-syms)))
     (mapc
@@ -85,15 +85,17 @@
                                    ;; parse line into calc objects
                                    (car (math-read-exprs line)))))))))
                   ))))))
-     (mapcar #'org-babel-trim
+     (mapcar #'org-trim
             (split-string (org-babel-expand-body:calc body params) "[\n\r]"))))
   (save-excursion
     (with-current-buffer (get-buffer "*Calculator*")
-      (calc-eval (calc-top 1)))))
+      (prog1
+        (calc-eval (calc-top 1))
+        (calc-pop 1)))))
 
 (defun org-babel-calc-maybe-resolve-var (el)
   (if (consp el)
-      (if (and (equal 'var (car el)) (member (cadr el) org--var-syms))
+      (if (and (eq 'var (car el)) (member (cadr el) org--var-syms))
          (progn
            (calc-recall (cadr el))
            (prog1 (calc-top 1)
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index b9af45a..3956157 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -1,9 +1,9 @@
-;;; ob-clojure.el --- org-babel functions for clojure evaluation
+;;; ob-clojure.el --- Babel Functions for Clojure    -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
-;; Author: Joel Boehland
-;;     Eric Schulte
+;; Author: Joel Boehland, Eric Schulte, Oleh Krehel
+;;
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
 
@@ -24,21 +24,30 @@
 
 ;;; Commentary:
 
-;; Support for evaluating clojure code, relies on slime for all eval.
+;; Support for evaluating clojure code
 
-;;; Requirements:
+;; Requirements:
 
 ;; - clojure (at least 1.2.0)
 ;; - clojure-mode
-;; - slime
+;; - either cider or SLIME
 
-;; By far, the best way to install these components is by following
+;; For Cider, see https://github.com/clojure-emacs/cider
+
+;; For SLIME, the best way to install these components is by following
 ;; the directions as set out by Phil Hagelberg (Technomancy) on the
 ;; web page: http://technomancy.us/126
 
 ;;; Code:
+(require 'cl-lib)
 (require 'ob)
 
+(declare-function cider-current-connection "ext:cider-client" (&optional type))
+(declare-function cider-current-session "ext:cider-client" ())
+(declare-function nrepl-dict-get "ext:nrepl-client" (dict key))
+(declare-function nrepl-sync-request:eval "ext:nrepl-client"
+                 (input connection session &optional ns))
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function slime-eval "ext:slime" (sexp &optional package))
 
 (defvar org-babel-tangle-lang-exts)
@@ -47,49 +56,63 @@
 (defvar org-babel-default-header-args:clojure '())
 (defvar org-babel-header-args:clojure '((package . :any)))
 
+(defcustom org-babel-clojure-backend
+  (cond ((featurep 'cider) 'cider)
+       (t 'slime))
+  "Backend used to evaluate Clojure code blocks."
+  :group 'org-babel
+  :type '(choice
+         (const :tag "cider" cider)
+         (const :tag "SLIME" slime)))
+
 (defun org-babel-expand-body:clojure (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-        (result-params (cdr (assoc :result-params params)))
+  (let* ((vars (org-babel--get-vars params))
+        (result-params (cdr (assq :result-params params)))
         (print-level nil) (print-length nil)
-        (body (org-babel-trim
-               (if (> (length vars) 0)
-                   (concat "(let ["
-                           (mapconcat
-                            (lambda (var)
-                              (format "%S (quote %S)" (car var) (cdr var)))
-                            vars "\n      ")
-                           "]\n" body ")")
-                 body))))
-    (cond ((or (member "code" result-params) (member "pp" result-params))
-          (format (concat "(let [org-mode-print-catcher 
(java.io.StringWriter.)] "
-                          "(clojure.pprint/with-pprint-dispatch 
clojure.pprint/%s-dispatch "
-                          "(clojure.pprint/pprint (do %s) 
org-mode-print-catcher) "
-                          "(str org-mode-print-catcher)))")
-                  (if (member "code" result-params) "code" "simple") body))
-         ;; if (:results output), collect printed output
-         ((member "output" result-params)
-          (format "(clojure.core/with-out-str %s)" body))
-         (t body))))
+        (body (org-trim
+               (if (null vars) (org-trim body)
+                 (concat "(let ["
+                         (mapconcat
+                          (lambda (var)
+                            (format "%S (quote %S)" (car var) (cdr var)))
+                          vars "\n      ")
+                         "]\n" body ")")))))
+    (if (or (member "code" result-params)
+           (member "pp" result-params))
+       (format "(clojure.pprint/pprint (do %s))" body)
+      body)))
 
 (defun org-babel-execute:clojure (body params)
   "Execute a block of Clojure code with Babel."
-  (require 'slime)
-  (with-temp-buffer
-    (insert (org-babel-expand-body:clojure body params))
-    (let ((result
-           (slime-eval
-            `(swank:eval-and-grab-output
-              ,(buffer-substring-no-properties (point-min) (point-max)))
-            (cdr (assoc :package params)))))
-      (let ((result-params (cdr (assoc :result-params params))))
-        (org-babel-result-cond result-params
-          result
-          (condition-case nil (org-babel-script-escape result)
-            (error result)))))))
+  (let ((expanded (org-babel-expand-body:clojure body params))
+       result)
+    (cl-case org-babel-clojure-backend
+      (cider
+       (require 'cider)
+       (let ((result-params (cdr (assq :result-params params))))
+        (setq result
+              (nrepl-dict-get
+               (nrepl-sync-request:eval
+                expanded (cider-current-connection) (cider-current-session))
+               (if (or (member "output" result-params)
+                       (member "pp" result-params))
+                   "out"
+                 "value")))))
+      (slime
+       (require 'slime)
+       (with-temp-buffer
+        (insert expanded)
+        (setq result
+              (slime-eval
+               `(swank:eval-and-grab-output
+                 ,(buffer-substring-no-properties (point-min) (point-max)))
+               (cdr (assq :package params)))))))
+    (org-babel-result-cond (cdr (assq :result-params params))
+      result
+      (condition-case nil (org-babel-script-escape result)
+       (error result)))))
 
 (provide 'ob-clojure)
 
-
-
 ;;; ob-clojure.el ends here
diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el
index 78c5021..cc60f4e 100644
--- a/lisp/org/ob-comint.el
+++ b/lisp/org/ob-comint.el
@@ -1,4 +1,4 @@
-;;; ob-comint.el --- org-babel functions for interaction with comint buffers
+;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -33,10 +33,7 @@
 (require 'ob-core)
 (require 'org-compat)
 (require 'comint)
-(eval-when-compile (require 'cl))
-(declare-function with-parsed-tramp-file-name "tramp"
-                  (filename var &rest body) t)
-(declare-function tramp-flush-directory-property "tramp-cache" (key directory))
+(require 'tramp)
 
 (defun org-babel-comint-buffer-livep (buffer)
   "Check if BUFFER is a comint buffer with a live process."
@@ -49,12 +46,14 @@ BUFFER is checked with `org-babel-comint-buffer-livep'.  
BODY is
 executed inside the protection of `save-excursion' and
 `save-match-data'."
   (declare (indent 1))
-  `(save-excursion
+  `(progn
+     (unless (org-babel-comint-buffer-livep ,buffer)
+       (error "Buffer %s does not exist or has no process" ,buffer))
      (save-match-data
-       (unless (org-babel-comint-buffer-livep ,buffer)
-         (error "Buffer %s does not exist or has no process" ,buffer))
-       (set-buffer ,buffer)
-       ,@body)))
+       (with-current-buffer ,buffer
+        (save-excursion
+          (let ((comint-input-filter (lambda (_input) nil)))
+            ,@body))))))
 (def-edebug-spec org-babel-comint-in-buffer (form body))
 
 (defmacro org-babel-comint-with-output (meta &rest body)
@@ -70,53 +69,49 @@ elements are optional.
 This macro ensures that the filter is removed in case of an error
 or user `keyboard-quit' during execution of body."
   (declare (indent 1))
-  (let ((buffer (car meta))
-       (eoe-indicator (cadr meta))
-       (remove-echo (cadr (cdr meta)))
-       (full-body (cadr (cdr (cdr meta)))))
+  (let ((buffer (nth 0 meta))
+       (eoe-indicator (nth 1 meta))
+       (remove-echo (nth 2 meta))
+       (full-body (nth 3 meta)))
     `(org-babel-comint-in-buffer ,buffer
-       (let ((string-buffer "") dangling-text raw)
-        ;; setup filter
-        (setq comint-output-filter-functions
+       (let* ((string-buffer "")
+             (comint-output-filter-functions
               (cons (lambda (text) (setq string-buffer (concat string-buffer 
text)))
                     comint-output-filter-functions))
-        (unwind-protect
-            (progn
-              ;; got located, and save dangling text
-              (goto-char (process-mark (get-buffer-process (current-buffer))))
-              (let ((start (point))
-                    (end (point-max)))
-                (setq dangling-text (buffer-substring start end))
-                (delete-region start end))
-              ;; pass FULL-BODY to process
-              ,@body
-              ;; wait for end-of-evaluation indicator
-              (while (progn
-                       (goto-char comint-last-input-end)
-                       (not (save-excursion
-                              (and (re-search-forward
-                                    (regexp-quote ,eoe-indicator) nil t)
-                                   (re-search-forward
-                                    comint-prompt-regexp nil t)))))
-                (accept-process-output (get-buffer-process (current-buffer)))
-                ;; thought the following this would allow async
-                ;; background running, but I was wrong...
-                ;; (run-with-timer .5 .5 'accept-process-output
-                ;;              (get-buffer-process (current-buffer)))
-                )
-              ;; replace cut dangling text
-              (goto-char (process-mark (get-buffer-process (current-buffer))))
-              (insert dangling-text))
-          ;; remove filter
-          (setq comint-output-filter-functions
-                (cdr comint-output-filter-functions)))
+             dangling-text)
+        ;; got located, and save dangling text
+        (goto-char (process-mark (get-buffer-process (current-buffer))))
+        (let ((start (point))
+              (end (point-max)))
+          (setq dangling-text (buffer-substring start end))
+          (delete-region start end))
+        ;; pass FULL-BODY to process
+        ,@body
+        ;; wait for end-of-evaluation indicator
+        (while (progn
+                 (goto-char comint-last-input-end)
+                 (not (save-excursion
+                        (and (re-search-forward
+                              (regexp-quote ,eoe-indicator) nil t)
+                             (re-search-forward
+                              comint-prompt-regexp nil t)))))
+          (accept-process-output (get-buffer-process (current-buffer)))
+          ;; thought the following this would allow async
+          ;; background running, but I was wrong...
+          ;; (run-with-timer .5 .5 'accept-process-output
+          ;;            (get-buffer-process (current-buffer)))
+          )
+        ;; replace cut dangling text
+        (goto-char (process-mark (get-buffer-process (current-buffer))))
+        (insert dangling-text)
+
         ;; remove echo'd FULL-BODY from input
-        (if (and ,remove-echo ,full-body
-                 (string-match
-                  (replace-regexp-in-string
-                   "\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
-                  string-buffer))
-            (setq raw (substring string-buffer (match-end 0))))
+        (when (and ,remove-echo ,full-body
+                   (string-match
+                    (replace-regexp-in-string
+                     "\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
+                    string-buffer))
+          (setq string-buffer (substring string-buffer (match-end 0))))
         (split-string string-buffer comint-prompt-regexp)))))
 (def-edebug-spec org-babel-comint-with-output (sexp body))
 
@@ -149,15 +144,14 @@ Don't return until FILE exists.  Code in STRING must 
ensure that
 FILE exists at end of evaluation."
   (unless (org-babel-comint-buffer-livep buffer)
     (error "Buffer %s does not exist or has no process" buffer))
-  (if (file-exists-p file) (delete-file file))
+  (when (file-exists-p file) (delete-file file))
   (process-send-string
    (get-buffer-process buffer)
-   (if (string-match "\n$" string) string (concat string "\n")))
+   (if (= (aref string (1- (length string))) ?\n) string (concat string "\n")))
   ;; From Tramp 2.1.19 the following cache flush is not necessary
-  (if (file-remote-p default-directory)
-      (let (v)
-       (with-parsed-tramp-file-name default-directory nil
-                                    (tramp-flush-directory-property v ""))))
+  (when (file-remote-p default-directory)
+    (with-parsed-tramp-file-name default-directory nil
+      (tramp-flush-directory-property v "")))
   (while (not (file-exists-p file)) (sit-for (or period 0.25))))
 
 (provide 'ob-comint)
diff --git a/lisp/org/ob-coq.el b/lisp/org/ob-coq.el
new file mode 100644
index 0000000..93d2b1f
--- /dev/null
+++ b/lisp/org/ob-coq.el
@@ -0,0 +1,78 @@
+;;; ob-coq.el --- Babel Functions for Coq            -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Rudimentary support for evaluating Coq code blocks.  Currently only
+;; session evaluation is supported.  Requires both coq.el and
+;; coq-inferior.el, both of which are distributed with Coq.
+;;
+;; http://coq.inria.fr/
+
+;;; Code:
+(require 'ob)
+
+(declare-function run-coq "ext:coq-inferior.el" (cmd))
+(declare-function coq-proc "ext:coq-inferior.el" ())
+
+(defvar coq-program-name "coqtop"
+  "Name of the coq toplevel to run.")
+
+(defvar org-babel-coq-buffer "*coq*"
+  "Buffer in which to evaluate coq code blocks.")
+
+(defun org-babel-coq-clean-prompt (string)
+  (if (string-match "^[^[:space:]]+ < " string)
+      (substring string 0 (match-beginning 0))
+    string))
+
+(defun org-babel-execute:coq (body params)
+  (let ((full-body (org-babel-expand-body:generic body params))
+       (session (org-babel-coq-initiate-session))
+       (pt (lambda ()
+             (marker-position
+              (process-mark (get-buffer-process (current-buffer)))))))
+    (org-babel-coq-clean-prompt
+     (org-babel-comint-in-buffer session
+       (let ((start (funcall pt)))
+        (with-temp-buffer
+          (insert full-body)
+          (comint-send-region (coq-proc) (point-min) (point-max))
+          (comint-send-string (coq-proc)
+           (if (string= (buffer-substring (- (point-max) 1) (point-max)) ".")
+               "\n"
+             ".\n")))
+        (while (equal start (funcall pt)) (sleep-for 0.1))
+        (buffer-substring start (funcall pt)))))))
+
+(defun org-babel-coq-initiate-session ()
+  "Initiate a coq session.
+If there is not a current inferior-process-buffer in SESSION then
+create one.  Return the initialized session."
+  (unless (fboundp 'run-coq)
+    (error "`run-coq' not defined, load coq-inferior.el"))
+  (save-window-excursion (run-coq coq-program-name))
+  (sit-for 0.1)
+  (get-buffer org-babel-coq-buffer))
+
+(provide 'ob-coq)
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index cfbcbe6..c630b70 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1,4 +1,4 @@
-;;; ob-core.el --- working with code blocks in org-mode
+;;; ob-core.el --- Working with Code Blocks          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -23,8 +23,7 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Code:
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'ob-eval)
 (require 'org-macs)
 (require 'org-compat)
@@ -33,66 +32,70 @@
   (if (memq system-type '(windows-nt cygwin))
       ".exe"
     nil))
-;; dynamically scoped for tramp
-(defvar org-babel-call-process-region-original nil)
-(defvar org-src-lang-modes)
+
 (defvar org-babel-library-of-babel)
-(declare-function outline-show-all "outline" ())
-(declare-function org-every "org" (pred seq))
-(declare-function org-reduce "org" (CL-FUNC CL-SEQ &rest CL-KEYS))
+(defvar org-edit-src-content-indentation)
+(defvar org-src-lang-modes)
+(defvar org-src-preserve-indentation)
+
+(declare-function org-at-item-p "org-list" ())
+(declare-function org-at-table-p "org" (&optional table-type))
+(declare-function org-babel-lob-execute-maybe "ob-lob" ())
+(declare-function org-babel-ref-goto-headline-id "ob-ref" (id))
+(declare-function org-babel-ref-headline-body "ob-ref" ())
+(declare-function org-babel-ref-parse "ob-ref" (assignment))
+(declare-function org-babel-ref-resolve "ob-ref" (ref))
+(declare-function org-babel-ref-split-args "ob-ref" (arg-string))
+(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info))
+(declare-function org-completing-read "org" (&rest args))
+(declare-function org-current-level "org" ())
+(declare-function org-cycle "org" (&optional arg))
+(declare-function org-do-remove-indentation "org" (&optional n))
+(declare-function org-edit-src-code "org-src" (&optional code 
edit-buffer-name))
+(declare-function org-edit-src-exit "org-src"  ())
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-normalize-string "org-element" (s))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-entry-get "org" (pom property &optional inherit 
literal-nil))
+(declare-function org-escape-code-in-region "org-src" (beg end))
+(declare-function org-get-indentation "org" (&optional line))
+(declare-function org-get-indentation "org" (&optional line))
+(declare-function org-in-regexp "org" (regexp &optional nlines visually))
+(declare-function org-indent-line "org" ())
+(declare-function org-list-get-list-end "org-list" (item struct prevs))
+(declare-function org-list-prevs-alist "org-list" (struct))
+(declare-function org-list-struct "org-list" ())
+(declare-function org-list-to-generic "org-list" (LIST PARAMS))
+(declare-function org-list-to-lisp "org-list" (&optional delete))
+(declare-function org-macro-escape-arguments "org-macro" (&rest args))
+(declare-function org-make-options-regexp "org" (kwds &optional extra))
 (declare-function org-mark-ring-push "org" (&optional pos buffer))
-(declare-function tramp-compat-make-temp-file "tramp-compat"
-                  (filename &optional dir-flag))
-(declare-function org-icompleting-read "org" (&rest args))
-(declare-function org-edit-src-code "org-src"
-                  (&optional context code edit-buffer-name))
-(declare-function org-edit-src-exit "org-src"  (&optional context))
-(declare-function org-open-at-point "org" (&optional in-emacs 
reference-buffer))
-(declare-function org-outline-overlay-data "org" (&optional use-markers))
-(declare-function org-set-outline-overlay-data "org" (data))
 (declare-function org-narrow-to-subtree "org" ())
-(declare-function org-split-string "org" (string &optional separators))
-(declare-function org-entry-get "org"
-                 (pom property &optional inherit literal-nil))
-(declare-function org-make-options-regexp "org" (kwds &optional extra))
-(declare-function org-do-remove-indentation "org" (&optional n))
 (declare-function org-next-block "org" (arg &optional backward block-regexp))
+(declare-function org-number-sequence "org-compat" (from &optional to inc))
+(declare-function org-open-at-point "org" (&optional in-emacs 
reference-buffer))
+(declare-function org-outline-overlay-data "org" (&optional use-markers))
 (declare-function org-previous-block "org" (arg &optional block-regexp))
+(declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-reverse-string "org" (string))
+(declare-function org-set-outline-overlay-data "org" (data))
 (declare-function org-show-context "org" (&optional key))
-(declare-function org-at-table-p "org" (&optional table-type))
-(declare-function org-cycle "org" (&optional arg))
-(declare-function org-uniquify "org" (list))
-(declare-function org-current-level "org" ())
-(declare-function org-table-import "org-table" (file arg))
-(declare-function org-add-hook "org-compat"
-                 (hook function &optional append local))
+(declare-function org-split-string "org" (string &optional separators))
+(declare-function org-src-coderef-format "org-src" (element))
+(declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
 (declare-function org-table-align "org-table" ())
 (declare-function org-table-end "org-table" (&optional table-type))
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
-(declare-function orgtbl-to-orgtbl "org-table" (table params))
-(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info))
-(declare-function org-babel-lob-get-info "ob-lob" nil)
-(declare-function org-babel-ref-split-args "ob-ref" (arg-string))
-(declare-function org-babel-ref-parse "ob-ref" (assignment))
-(declare-function org-babel-ref-resolve "ob-ref" (ref))
-(declare-function org-babel-ref-goto-headline-id "ob-ref" (id))
-(declare-function org-babel-ref-headline-body "ob-ref" ())
-(declare-function org-babel-lob-execute-maybe "ob-lob" ())
-(declare-function org-number-sequence "org-compat" (from &optional to inc))
-(declare-function org-at-item-p "org-list" ())
-(declare-function org-list-parse-list "org-list" (&optional delete))
-(declare-function org-list-to-generic "org-list" (LIST PARAMS))
-(declare-function org-list-struct "org-list" ())
-(declare-function org-list-prevs-alist "org-list" (struct))
-(declare-function org-list-get-list-end "org-list" (item struct prevs))
-(declare-function org-remove-if "org" (predicate seq))
-(declare-function org-completing-read "org" (&rest args))
-(declare-function org-escape-code-in-region "org-src" (beg end))
-(declare-function org-unescape-code-in-string "org-src" (s))
+(declare-function org-table-import "org-table" (file arg))
 (declare-function org-table-to-lisp "org-table" (&optional txt))
-(declare-function org-reverse-string "org" (string))
-(declare-function org-element-context "org-element" (&optional ELEMENT))
+(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function org-unescape-code-in-string "org-src" (s))
+(declare-function org-uniquify "org" (list))
+(declare-function orgtbl-to-generic "org-table" (table params))
+(declare-function orgtbl-to-orgtbl "org-table" (table params))
+(declare-function outline-show-all "outline" ())
+(declare-function tramp-compat-make-temp-file "tramp-compat" (filename 
&optional dir-flag))
 
 (defgroup org-babel nil
   "Code block evaluation and management in `org-mode' documents."
@@ -101,11 +104,12 @@
 
 (defcustom org-confirm-babel-evaluate t
   "Confirm before evaluation.
+\\<org-mode-map>\
 Require confirmation before interactively evaluating code
-blocks in Org-mode buffers.  The default value of this variable
-is t, meaning confirmation is required for any code block
-evaluation.  This variable can be set to nil to inhibit any
-future confirmation requests.  This variable can also be set to a
+blocks in Org buffers.  The default value of this variable is t,
+meaning confirmation is required for any code block evaluation.
+This variable can be set to nil to inhibit any future
+confirmation requests.  This variable can also be set to a
 function which takes two arguments the language of the code block
 and the body of the code block.  Such a function should then
 return a non-nil value if the user should be prompted for
@@ -113,10 +117,11 @@ execution or nil if no prompt is required.
 
 Warning: Disabling confirmation may result in accidental
 evaluation of potentially harmful code.  It may be advisable
-remove code block execution from C-c C-c as further protection
+remove code block execution from `\\[org-ctrl-c-ctrl-c]' \
+as further protection
 against accidental code block evaluation.  The
 `org-babel-no-eval-on-ctrl-c-ctrl-c' variable can be used to
-remove code block execution from the C-c C-c keybinding."
+remove code block execution from the `\\[org-ctrl-c-ctrl-c]' keybinding."
   :group 'org-babel
   :version "24.1"
   :type '(choice boolean function))
@@ -124,19 +129,24 @@ remove code block execution from the C-c C-c keybinding."
 (put 'org-confirm-babel-evaluate 'safe-local-variable (lambda (x) (eq x t)))
 
 (defcustom org-babel-no-eval-on-ctrl-c-ctrl-c nil
-  "Remove code block evaluation from the C-c C-c key binding."
+  "\\<org-mode-map>\
+Remove code block evaluation from the `\\[org-ctrl-c-ctrl-c]' key binding."
   :group 'org-babel
   :version "24.1"
   :type 'boolean)
 
 (defcustom org-babel-results-keyword "RESULTS"
   "Keyword used to name results generated by code blocks.
-Should be either RESULTS or NAME however any capitalization may
-be used."
+It should be \"RESULTS\".  However any capitalization may be
+used."
   :group 'org-babel
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'string)
+  :type 'string
+  :safe (lambda (v)
+         (and (stringp v)
+              (eq (compare-strings "RESULTS" nil nil v nil nil t)
+                  t))))
 
 (defcustom org-babel-noweb-wrap-start "<<"
   "String used to begin a noweb reference in a code block.
@@ -155,6 +165,19 @@ See also `org-babel-noweb-wrap-start'."
 This string must include a \"%s\" which will be replaced by the results."
   :group 'org-babel
   :type 'string)
+(put 'org-babel-inline-result-wrap
+     'safe-local-variable
+     (lambda (value)
+       (and (stringp value)
+           (string-match-p "%s" value))))
+
+(defcustom org-babel-hash-show-time nil
+  "Non-nil means show the time the code block was evaluated in the result 
hash."
+  :group 'org-babel
+  :type 'boolean
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :safe #'booleanp)
 
 (defun org-babel-noweb-wrap (&optional regexp)
   (concat org-babel-noweb-wrap-start
@@ -169,14 +192,6 @@ This string must include a \"%s\" which will be replaced 
by the results."
   "^[ \t]*#\\+headers?:[ \t]*\\([^\n]*\\)$"
   "Regular expression used to match multi-line header arguments.")
 
-(defvar org-babel-src-name-w-name-regexp
-  (concat org-babel-src-name-regexp
-         "\\("
-         org-babel-multi-line-header-regexp
-         "\\)*"
-         "\\([^ ()\f\t\n\r\v]+\\)")
-  "Regular expression matching source name lines with a name.")
-
 (defvar org-babel-src-block-regexp
   (concat
    ;; (1) indentation                 (2) lang
@@ -189,168 +204,100 @@ This string must include a \"%s\" which will be 
replaced by the results."
    "\\([^\000]*?\n\\)??[ \t]*#\\+end_src")
   "Regexp used to identify code blocks.")
 
-(defvar org-babel-inline-src-block-regexp
-  (concat
-   ;; (1) replacement target (2) lang
-   "\\(?:^\\|[^-[:alnum:]]\\)\\(src_\\([^ \f\t\n\r\v]+\\)"
-   ;; (3,4) (unused, headers)
-   "\\(\\|\\[\\(.*?\\)\\]\\)"
-   ;; (5) body
-   "{\\([^\f\n\r\v]+?\\)}\\)")
-  "Regexp used to identify inline src-blocks.")
-
-(defun org-babel-get-header (params key &optional others)
-  "Select only header argument of type KEY from a list.
-Optional argument OTHERS indicates that only the header that do
-not match KEY should be returned."
-  (delq nil
-       (mapcar
-        (lambda (p) (when (funcall (if others #'not #'identity) (eq (car p) 
key)) p))
-        params)))
-
-(defun org-babel-get-inline-src-block-matches()
-  "Set match data if within body of an inline source block.
-Returns non-nil if match-data set"
-  (let ((src-at-0-p (save-excursion
-                     (beginning-of-line 1)
-                     (string= "src" (thing-at-point 'word))))
-       (first-line-p (= (line-beginning-position) (point-min)))
-       (orig (point)))
-    (let ((search-for (cond ((and src-at-0-p first-line-p  "src_"))
-                           (first-line-p "[[:punct:] \t]src_")
-                           (t "[[:punct:] \f\t\n\r\v]src_")))
-         (lower-limit (if first-line-p
-                          nil
-                        (- (point-at-bol) 1))))
-      (save-excursion
-       (when (or (and src-at-0-p (bobp))
-                 (and (re-search-forward "}" (point-at-eol) t)
-                      (re-search-backward search-for lower-limit t)
-                      (> orig (point))))
-         (when (looking-at org-babel-inline-src-block-regexp)
-           t ))))))
-
-(defvar org-babel-inline-lob-one-liner-regexp)
-(defun org-babel-get-lob-one-liner-matches()
-  "Set match data if on line of an lob one liner.
-Returns non-nil if match-data set"
-  (save-excursion
-    (unless (= (point) (point-at-bol)) ;; move before inline block
-      (re-search-backward "[ \f\t\n\r\v]" nil t))
-    (if (looking-at org-babel-inline-lob-one-liner-regexp)
-       t
-      nil)))
-
-(defun org-babel-get-src-block-info (&optional light)
-  "Get information on the current source block.
-
-Optional argument LIGHT does not resolve remote variable
-references; a process which could likely result in the execution
-of other code blocks.
+(defun org-babel--get-vars (params)
+  "Return the babel variable assignments in PARAMS.
+
+PARAMS is a quasi-alist of header args, which may contain
+multiple entries for the key `:var'.  This function returns a
+list of the cdr of all the `:var' entries."
+  (mapcar #'cdr
+         (cl-remove-if-not (lambda (x) (eq (car x) :var)) params)))
+
+(defvar org-babel-exp-reference-buffer nil
+  "Buffer containing original contents of the exported buffer.
+This is used by Babel to resolve references in source blocks.
+Its value is dynamically bound during export.")
+
+(defun org-babel-check-confirm-evaluate (info)
+  "Check whether INFO allows code block evaluation.
+
+Returns nil if evaluation is disallowed, t if it is
+unconditionally allowed, and the symbol `query' if the user
+should be asked whether to allow evaluation."
+  (let* ((headers (nth 2 info))
+        (eval (or (cdr  (assq :eval headers))
+                  (when (assq :noeval headers) "no")))
+        (eval-no (member eval '("no" "never")))
+        (export org-babel-exp-reference-buffer)
+        (eval-no-export (and export (member eval '("no-export" 
"never-export"))))
+        (noeval (or eval-no eval-no-export))
+        (query (or (equal eval "query")
+                   (and export (equal eval "query-export"))
+                   (if (functionp org-confirm-babel-evaluate)
+                       (save-excursion
+                         (goto-char (nth 5 info))
+                         (funcall org-confirm-babel-evaluate
+                                  ;; language, code block body
+                                  (nth 0 info) (nth 1 info)))
+                     org-confirm-babel-evaluate))))
+    (cond
+     (noeval nil)
+     (query 'query)
+     (t t))))
 
-Returns a list
- (language body header-arguments-alist switches name indent block-head)."
-  (let ((case-fold-search t) head info name indent)
-    ;; full code block
-    (if (setq head (org-babel-where-is-src-block-head))
-       (save-excursion
-         (goto-char head)
-         (setq info (org-babel-parse-src-block-match))
-         (setq indent (car (last info)))
-         (setq info (butlast info))
-         (while (and (forward-line -1)
-                     (looking-at org-babel-multi-line-header-regexp))
-           (setf (nth 2 info)
-                 (org-babel-merge-params
-                  (nth 2 info)
-                  (org-babel-parse-header-arguments (match-string 1)))))
-         (when (looking-at org-babel-src-name-w-name-regexp)
-           (setq name (org-no-properties (match-string 3)))))
-      ;; inline source block
-      (when (org-babel-get-inline-src-block-matches)
-       (setq info (org-babel-parse-inline-src-block-match))))
-    ;; resolve variable references and add summary parameters
-    (when (and info (not light))
-      (setf (nth 2 info) (org-babel-process-params (nth 2 info))))
-    (when info (append info (list name indent head)))))
-
-(defvar org-current-export-file) ; dynamically bound
-(defmacro org-babel-check-confirm-evaluate (info &rest body)
-  "Evaluate BODY with special execution confirmation variables set.
-
-Specifically; NOEVAL will indicate if evaluation is allowed,
-QUERY will indicate if a user query is required, CODE-BLOCK will
-hold the language of the code block, and BLOCK-NAME will hold the
-name of the code block."
-  (declare (indent defun))
-  (org-with-gensyms
-      (lang block-body headers name eval eval-no export eval-no-export)
-    `(let* ((,lang           (nth 0 ,info))
-           (,block-body     (nth 1 ,info))
-           (,headers        (nth 2 ,info))
-           (,name           (nth 4 ,info))
-           (,eval           (or (cdr  (assoc :eval   ,headers))
-                                (when (assoc :noeval ,headers) "no")))
-           (,eval-no        (or (equal ,eval "no")
-                                (equal ,eval "never")))
-           (,export         (org-bound-and-true-p org-current-export-file))
-           (,eval-no-export (and ,export (or (equal ,eval "no-export")
-                                             (equal ,eval "never-export"))))
-           (noeval          (or ,eval-no ,eval-no-export))
-           (query           (or (equal ,eval "query")
-                                (and ,export (equal ,eval "query-export"))
-                                (if (functionp org-confirm-babel-evaluate)
-                                    (funcall org-confirm-babel-evaluate
-                                             ,lang ,block-body)
-                                  org-confirm-babel-evaluate)))
-           (code-block      (if ,info (format  " %s "  ,lang) " "))
-           (block-name      (if ,name (format " (%s) " ,name) " ")))
-       ;; Silence byte-compiler is `body' doesn't use those vars.
-       (ignore noeval query)
-       ,@body)))
-
-(defsubst org-babel-check-evaluate (info)
+(defun org-babel-check-evaluate (info)
   "Check if code block INFO should be evaluated.
-Do not query the user."
-  (org-babel-check-confirm-evaluate info
-    (not (when noeval
-          (message "Evaluation of this%scode-block%sis disabled."
-                    code-block block-name)))))
-
- ;; dynamically scoped for asynchronous export
+Do not query the user, but do display an informative message if
+evaluation is blocked.  Returns non-nil if evaluation is not blocked."
+  (let ((confirmed (org-babel-check-confirm-evaluate info)))
+    (unless confirmed
+      (message "Evaluation of this %s code block%sis disabled."
+              (nth 0 info)
+              (let ((name (nth 4 info)))
+                (if name (format " (%s) " name) " "))))
+    confirmed))
+
+;; Dynamically scoped for asynchronous export.
 (defvar org-babel-confirm-evaluate-answer-no)
 
-(defsubst org-babel-confirm-evaluate (info)
+(defun org-babel-confirm-evaluate (info)
   "Confirm evaluation of the code block INFO.
 
-If the variable `org-babel-confirm-evaluate-answer-no' is bound
-to a non-nil value, auto-answer with \"no\".
-
 This query can also be suppressed by setting the value of
 `org-confirm-babel-evaluate' to nil, in which case all future
 interactive code block evaluations will proceed without any
 confirmation from the user.
 
 Note disabling confirmation may result in accidental evaluation
-of potentially harmful code."
-  (org-babel-check-confirm-evaluate info
-    (not (when query
-          (unless
-              (and (not (org-bound-and-true-p
+of potentially harmful code.
+
+The variable `org-babel-confirm-evaluate-answer-no' is used by
+the async export process, which requires a non-interactive
+environment, to override this check."
+  (let* ((evalp (org-babel-check-confirm-evaluate info))
+        (lang (nth 0 info))
+        (name (nth 4 info))
+        (name-string (if name (format " (%s) " name) " ")))
+    (pcase evalp
+      (`nil nil)
+      (`t t)
+      (`query (or
+              (and (not (bound-and-true-p
                          org-babel-confirm-evaluate-answer-no))
                    (yes-or-no-p
-                    (format "Evaluate this%scode block%son your system? "
-                            code-block block-name)))
-            (message "Evaluation of this%scode-block%sis aborted."
-                      code-block block-name))))))
+                    (format "Evaluate this %s code block%son your system? "
+                            lang name-string)))
+              (progn
+               (message "Evaluation of this %s code block%sis aborted."
+                        lang name-string)
+               nil)))
+      (x (error "Unexpected value `%s' from 
`org-babel-check-confirm-evaluate'" x)))))
 
 ;;;###autoload
 (defun org-babel-execute-safely-maybe ()
   (unless org-babel-no-eval-on-ctrl-c-ctrl-c
     (org-babel-execute-maybe)))
 
-(add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-execute-safely-maybe)
-
 ;;;###autoload
 (defun org-babel-execute-maybe ()
   (interactive)
@@ -361,8 +308,8 @@ of potentially harmful code."
   "Execute BODY if point is in a source block and return t.
 
 Otherwise do nothing and return nil."
-  `(if (or (org-babel-where-is-src-block-head)
-           (org-babel-get-inline-src-block-matches))
+  `(if (memq (org-element-type (org-element-context))
+            '(inline-src-block src-block))
        (progn
         ,@body
         t)
@@ -394,12 +341,16 @@ a window into the `org-babel-get-src-block-info' 
function."
              (header-args (nth 2 info)))
          (when name            (funcall printf "Name: %s\n"     name))
          (when lang            (funcall printf "Lang: %s\n"     lang))
+         (funcall printf "Properties:\n")
+         (funcall printf "\t:header-args \t%s\n" (org-entry-get (point) 
"header-args" t))
+         (funcall printf "\t:header-args:%s \t%s\n" lang (org-entry-get 
(point) (concat "header-args:" lang) t))
+
          (when (funcall full switches) (funcall printf "Switches: %s\n" 
switches))
          (funcall printf "Header Arguments:\n")
          (dolist (pair (sort header-args
                              (lambda (a b) (string< (symbol-name (car a))
                                                     (symbol-name (car b))))))
-           (when (funcall full (cdr pair))
+           (when (funcall full (format "%s" (cdr pair)))
              (funcall printf "\t%S%s\t%s\n"
                       (car pair)
                       (if (> (length (format "%S" (car pair))) 7) "" "\t")
@@ -442,11 +393,13 @@ then run `org-babel-switch-to-session'."
     (colnames  . ((nil no yes)))
     (comments  . ((no link yes org both noweb)))
     (dir       . :any)
-    (eval      . ((never query)))
+    (eval      . ((yes no no-export strip-export never-export eval never
+                       query)))
     (exports   . ((code results both none)))
     (epilogue   . :any)
     (file      . :any)
     (file-desc  . :any)
+    (file-ext   . :any)
     (hlines    . ((no yes)))
     (mkdirp    . ((yes no)))
     (no-expand)
@@ -454,6 +407,7 @@ then run `org-babel-switch-to-session'."
     (noweb     . ((yes no tangle no-export strip-export)))
     (noweb-ref . :any)
     (noweb-sep  . :any)
+    (output-dir . :any)
     (padline   . ((yes no)))
     (post       . :any)
     (prologue   . :any)
@@ -476,31 +430,76 @@ then run `org-babel-switch-to-session'."
 Note that individual languages may define their own language
 specific header arguments as well.")
 
+(defconst org-babel-safe-header-args
+  '(:cache :colnames :comments :exports :epilogue :hlines :noeval
+          :noweb :noweb-ref :noweb-sep :padline :prologue :rownames
+          :sep :session :tangle :wrap
+          (:eval . ("never" "query"))
+          (:results . (lambda (str) (not (string-match "file" str)))))
+  "A list of safe header arguments for babel source blocks.
+
+The list can have entries of the following forms:
+- :ARG                     -> :ARG is always a safe header arg
+- (:ARG . (VAL1 VAL2 ...)) -> :ARG is safe as a header arg if it is
+                              `equal' to one of the VALs.
+- (:ARG . FN)              -> :ARG is safe as a header arg if the function FN
+                              returns non-nil.  FN is passed one
+                              argument, the value of the header arg
+                              (as a string).")
+
+(defmacro org-babel-header-args-safe-fn (safe-list)
+  "Return a function that determines whether a list of header args are safe.
+
+Intended usage is:
+\(put \\='org-babel-default-header-args \\='safe-local-variable
+ (org-babel-header-args-safe-p org-babel-safe-header-args)
+
+This allows org-babel languages to extend the list of safe values for
+their `org-babel-default-header-args:foo' variable.
+
+For the format of SAFE-LIST, see `org-babel-safe-header-args'."
+  `(lambda (value)
+     (and (listp value)
+         (cl-every
+          (lambda (pair)
+            (and (consp pair)
+                 (org-babel-one-header-arg-safe-p pair ,safe-list)))
+          value))))
+
 (defvar org-babel-default-header-args
   '((:session . "none") (:results . "replace") (:exports . "code")
     (:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no"))
   "Default arguments to use when evaluating a source block.")
+(put 'org-babel-default-header-args 'safe-local-variable
+     (org-babel-header-args-safe-fn org-babel-safe-header-args))
 
 (defvar org-babel-default-inline-header-args
-  '((:session . "none") (:results . "replace") (:exports . "results"))
+  '((:session . "none") (:results . "replace")
+    (:exports . "results") (:hlines . "yes"))
   "Default arguments to use when evaluating an inline source block.")
-
-(defvar org-babel-data-names '("tblname" "results" "name"))
-
-(defvar org-babel-result-regexp
-  (concat "^[ \t]*#\\+"
-         (regexp-opt org-babel-data-names t)
-         "\\(\\[\\("
-         ;; FIXME The string below is `org-ts-regexp'
-         "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)>"
-         " \\)?\\([[:alnum:]]+\\)\\]\\)?\\:[ \t]*")
+(put 'org-babel-default-inline-header-args 'safe-local-variable
+     (org-babel-header-args-safe-fn org-babel-safe-header-args))
+
+(defconst org-babel-name-regexp
+  (format "^[ \t]*#\\+%s:[ \t]*"
+         ;; FIXME: TBLNAME is for backward compatibility.
+         (regexp-opt '("NAME" "TBLNAME")))
+  "Regexp matching a NAME keyword.")
+
+(defconst org-babel-result-regexp
+  (format "^[ \t]*#\\+%s\\(?:\\[\\(?:%s \\)?\\([[:alnum:]]+\\)\\]\\)?:[ \t]*"
+         org-babel-results-keyword
+         ;; <%Y-%m-%d %H:%M:%S>
+         "<\\(?:[0-9]\\{4\\}-[0-1][0-9]-[0-3][0-9] \
+[0-2][0-9]\\(?::[0-5][0-9]\\)\\{2\\}\\)>")
   "Regular expression used to match result lines.
 If the results are associated with a hash key then the hash will
-be saved in the second match data.")
+be saved in match group 1.")
 
-(defvar org-babel-result-w-name-regexp
-  (concat org-babel-result-regexp
-         "\\([^ ()\f\t\n\r\v]+\\)\\((\\(.*\\))\\|\\)"))
+(defconst org-babel-result-w-name-regexp
+  (concat org-babel-result-regexp "\\(?9:[^ \t\n\r\v\f]+\\)")
+  "Regexp matching a RESULTS keyword with a name.
+Name is saved in match group 9.")
 
 (defvar org-babel-min-lines-for-block-output 10
   "The minimum number of lines for block output.
@@ -510,33 +509,58 @@ block.  Otherwise the output is marked as literal by 
inserting
 colons at the starts of the lines.  This variable only takes
 effect if the :results output option is in effect.")
 
+(defvar org-babel-noweb-error-all-langs nil
+  "Raise errors when noweb references don't resolve.
+Also see `org-babel-noweb-error-langs' to control noweb errors on
+a language by language bases.")
+
 (defvar org-babel-noweb-error-langs nil
   "Languages for which Babel will raise literate programming errors.
 List of languages for which errors should be raised when the
 source code block satisfying a noweb reference in this language
-can not be resolved.")
+can not be resolved.  Also see `org-babel-noweb-error-all-langs'
+to raise errors for all languages.")
 
 (defvar org-babel-hash-show 4
   "Number of initial characters to show of a hidden results hash.")
 
-(defvar org-babel-hash-show-time nil
-  "Non-nil means show the time the code block was evaluated in the result 
hash.")
-
 (defvar org-babel-after-execute-hook nil
   "Hook for functions to be called after `org-babel-execute-src-block'")
 
-(defun org-babel-named-src-block-regexp-for-name (name)
-  "This generates a regexp used to match a src block named NAME."
-  (concat org-babel-src-name-regexp (regexp-quote name)
-         "[ \t(]*[\r\n]\\(?:^#.*[\r\n]\\)*"
+(defun org-babel-named-src-block-regexp-for-name (&optional name)
+  "This generates a regexp used to match a src block named NAME.
+If NAME is nil, match any name.  Matched name is then put in
+match group 9.  Other match groups are defined in
+`org-babel-src-block-regexp'."
+  (concat org-babel-src-name-regexp
+         (concat (if name (regexp-quote name) "\\(?9:.*?\\)") "[ \t]*" )
+         "\\(?:\n[ \t]*#\\+\\S-+:.*\\)*?"
+         "\n"
          (substring org-babel-src-block-regexp 1)))
 
 (defun org-babel-named-data-regexp-for-name (name)
   "This generates a regexp used to match data named NAME."
-  (concat org-babel-result-regexp (regexp-quote name) "\\([ \t]\\|$\\)"))
+  (concat org-babel-name-regexp (regexp-quote name) "[ \t]*$"))
+
+(defun org-babel--normalize-body (datum)
+  "Normalize body for element or object DATUM.
+DATUM is a source block element or an inline source block object.
+Remove final newline character and spurious indentation."
+  (let* ((value (org-element-property :value datum))
+        (body (if (string-suffix-p "\n" value)
+                  (substring value 0 -1)
+                value)))
+    (cond ((eq (org-element-type datum) 'inline-src-block)
+          ;; Newline characters and indentation in an inline
+          ;; src-block are not meaningful, since they could come from
+          ;; some paragraph filling.  Treat them as a white space.
+          (replace-regexp-in-string "\n[ \t]*" " " body))
+         ((or org-src-preserve-indentation
+              (org-element-property :preserve-indent datum))
+          body)
+         (t (org-remove-indentation body)))))
 
 ;;; functions
-(defvar call-process-region)
 (defvar org-babel-current-src-block-location nil
   "Marker pointing to the src block currently being executed.
 This may also point to a call line or an inline code block.  If
@@ -546,6 +570,56 @@ the outer-most code block.")
 
 (defvar *this*)
 
+(defun org-babel-get-src-block-info (&optional light datum)
+  "Extract information from a source block or inline source block.
+
+Optional argument LIGHT does not resolve remote variable
+references; a process which could likely result in the execution
+of other code blocks.
+
+By default, consider the block at point.  However, when optional
+argument DATUM is provided, extract information from that parsed
+object instead.
+
+Return nil if point is not on a source block.  Otherwise, return
+a list with the following pattern:
+
+  (language body arguments switches name start coderef)"
+  (let* ((datum (or datum (org-element-context)))
+        (type (org-element-type datum))
+        (inline (eq type 'inline-src-block)))
+    (when (memq type '(inline-src-block src-block))
+      (let* ((lang (org-element-property :language datum))
+            (lang-headers (intern
+                           (concat "org-babel-default-header-args:" lang)))
+            (name (org-element-property :name datum))
+            (info
+             (list
+              lang
+              (org-babel--normalize-body datum)
+              (apply #'org-babel-merge-params
+                     (if inline org-babel-default-inline-header-args
+                       org-babel-default-header-args)
+                     (and (boundp lang-headers) (eval lang-headers t))
+                     (append
+                      ;; If DATUM is provided, make sure we get node
+                      ;; properties applicable to its location within
+                      ;; the document.
+                      (org-with-point-at (org-element-property :begin datum)
+                        (org-babel-params-from-properties lang))
+                      (mapcar #'org-babel-parse-header-arguments
+                              (cons (org-element-property :parameters datum)
+                                    (org-element-property :header datum)))))
+              (or (org-element-property :switches datum) "")
+              name
+              (org-element-property (if inline :begin :post-affiliated)
+                                    datum)
+              (and (not inline) (org-src-coderef-format datum)))))
+       (unless light
+         (setf (nth 2 info) (org-babel-process-params (nth 2 info))))
+       (setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info)))
+       info))))
+
 ;;;###autoload
 (defun org-babel-execute-src-block (&optional arg info params)
   "Execute the current source code block.
@@ -565,110 +639,91 @@ block."
   (interactive)
   (let* ((org-babel-current-src-block-location
          (or org-babel-current-src-block-location
-             (nth 6 info)
+             (nth 5 info)
              (org-babel-where-is-src-block-head)))
-        (info (if info
-                  (copy-tree info)
-                (org-babel-get-src-block-info)))
-        (merged-params (org-babel-merge-params (nth 2 info) params)))
-    (when (org-babel-check-evaluate
-          (let ((i info)) (setf (nth 2 i) merged-params) i))
-      (let* ((params (if params
-                        (org-babel-process-params merged-params)
-                      (nth 2 info)))
-            (cachep (and (not arg) (cdr (assoc :cache params))
-                          (string= "yes" (cdr (assoc :cache params)))))
-            (new-hash (when cachep (org-babel-sha1-hash info)))
-            (old-hash (when cachep (org-babel-current-result-hash)))
-            (cache-current-p (and (not arg) new-hash
-                                  (equal new-hash old-hash))))
+        (info (if info (copy-tree info) (org-babel-get-src-block-info))))
+    ;; Merge PARAMS with INFO before considering source block
+    ;; evaluation since both could disagree.
+    (cl-callf org-babel-merge-params (nth 2 info) params)
+    (when (org-babel-check-evaluate info)
+      (cl-callf org-babel-process-params (nth 2 info))
+      (let* ((params (nth 2 info))
+            (cache (let ((c (cdr (assq :cache params))))
+                     (and (not arg) c (string= "yes" c))))
+            (new-hash (and cache (org-babel-sha1-hash info)))
+            (old-hash (and cache (org-babel-current-result-hash)))
+            (current-cache (and new-hash (equal new-hash old-hash))))
        (cond
-        (cache-current-p
-         (save-excursion ;; return cached result
+        (current-cache
+         (save-excursion               ;Return cached result.
            (goto-char (org-babel-where-is-src-block-result nil info))
-           (end-of-line 1) (forward-char 1)
+           (forward-line)
+           (skip-chars-forward " \t")
            (let ((result (org-babel-read-result)))
-             (message (replace-regexp-in-string
-                       "%" "%%" (format "%S" result)))
-              result)))
-        ((org-babel-confirm-evaluate
-          (let ((i info)) (setf (nth 2 i) merged-params) i))
+             (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
+             result)))
+        ((org-babel-confirm-evaluate info)
          (let* ((lang (nth 0 info))
-                (result-params (cdr (assoc :result-params params)))
-                (body (setf (nth 1 info)
-                            (if (org-babel-noweb-p params :eval)
-                                (org-babel-expand-noweb-references info)
-                              (nth 1 info))))
-                (dir (cdr (assoc :dir params)))
+                (result-params (cdr (assq :result-params params)))
+                ;; Expand noweb references in BODY and remove any
+                ;; coderef.
+                (body
+                 (let ((coderef (nth 6 info))
+                       (expand
+                        (if (org-babel-noweb-p params :eval)
+                            (org-babel-expand-noweb-references info)
+                          (nth 1 info))))
+                   (if (not coderef) expand
+                     (replace-regexp-in-string
+                      (org-src-coderef-regexp coderef) "" expand nil nil 1))))
+                (dir (cdr (assq :dir params)))
                 (default-directory
                   (or (and dir (file-name-as-directory (expand-file-name dir)))
                       default-directory))
-                (org-babel-call-process-region-original ;; for tramp handler
-                 (or (org-bound-and-true-p
-                      org-babel-call-process-region-original)
-                     (symbol-function 'call-process-region)))
-                (indent (nth 5 info))
-                result cmd)
-           (unwind-protect
-               (let ((call-process-region
-                      (lambda (&rest args)
-                        (apply 'org-babel-tramp-handle-call-process-region
-                               args))))
-                 (let ((lang-check
-                        (lambda (f)
-                          (let ((f (intern (concat "org-babel-execute:" f))))
-                            (when (fboundp f) f)))))
-                   (setq cmd
-                         (or (funcall lang-check lang)
-                             (funcall lang-check
-                                      (symbol-name
-                                       (cdr (assoc lang org-src-lang-modes))))
-                             (error "No org-babel-execute function for %s!"
-                                    lang))))
-                 (message "executing %s code block%s..."
-                          (capitalize lang)
-                          (if (nth 4 info) (format " (%s)" (nth 4 info)) ""))
-                 (if (member "none" result-params)
-                     (progn
-                       (funcall cmd body params)
-                       (message "result silenced")
-                       (setq result nil))
-                   (setq result
-                         (let ((result (funcall cmd body params)))
-                            (if (and (eq (cdr (assoc :result-type params))
-                                         'value)
-                                     (or (member "vector" result-params)
-                                         (member "table" result-params))
-                                     (not (listp result)))
-                                (list (list result)) result)))
-                   ;; If non-empty result and :file then write to :file.
-                   (when (cdr (assoc :file params))
-                     (when result
-                       (with-temp-file (cdr (assoc :file params))
-                         (insert
-                          (org-babel-format-result
-                           result (cdr (assoc :sep (nth 2 info)))))))
-                     (setq result (cdr (assoc :file params))))
-                   ;; Possibly perform post process provided its appropriate.
-                   (when (cdr (assoc :post params))
-                     (let ((*this* (if (cdr (assoc :file params))
-                                       (org-babel-result-to-file
-                                        (cdr (assoc :file params))
-                                        (when (assoc :file-desc params)
-                                          (or (cdr (assoc :file-desc params))
-                                              result)))
-                                     result)))
-                       (setq result (org-babel-ref-resolve
-                                     (cdr (assoc :post params))))
-                       (when (cdr (assoc :file params))
-                         (setq result-params
-                               (remove "file" result-params)))))
-                   (org-babel-insert-result
-                    result result-params info new-hash indent lang))
-                  (run-hooks 'org-babel-after-execute-hook)
-                 result)
-             (setq call-process-region
-                   'org-babel-call-process-region-original)))))))))
+                (cmd (intern (concat "org-babel-execute:" lang)))
+                result)
+           (unless (fboundp cmd)
+             (error "No org-babel-execute function for %s!" lang))
+           (message "executing %s code block%s..."
+                    (capitalize lang)
+                    (let ((name (nth 4 info)))
+                      (if name (format " (%s)" name) "")))
+           (if (member "none" result-params)
+               (progn (funcall cmd body params)
+                      (message "result silenced"))
+             (setq result
+                   (let ((r (funcall cmd body params)))
+                     (if (and (eq (cdr (assq :result-type params)) 'value)
+                              (or (member "vector" result-params)
+                                  (member "table" result-params))
+                              (not (listp r)))
+                         (list (list r))
+                       r)))
+             (let ((file (cdr (assq :file params))))
+               ;; If non-empty result and :file then write to :file.
+               (when file
+                 (when result
+                   (with-temp-file file
+                     (insert (org-babel-format-result
+                              result (cdr (assq :sep params))))))
+                 (setq result file))
+               ;; Possibly perform post process provided its
+               ;; appropriate.  Dynamically bind "*this*" to the
+               ;; actual results of the block.
+               (let ((post (cdr (assq :post params))))
+                 (when post
+                   (let ((*this* (if (not file) result
+                                   (org-babel-result-to-file
+                                    file
+                                    (let ((desc (assq :file-desc params)))
+                                      (and desc (or (cdr desc) result)))))))
+                     (setq result (org-babel-ref-resolve post))
+                     (when file
+                       (setq result-params (remove "file" result-params))))))
+               (org-babel-insert-result
+                result result-params info new-hash lang)))
+           (run-hooks 'org-babel-after-execute-hook)
+           result)))))))
 
 (defun org-babel-expand-body:generic (body params &optional var-lines)
   "Expand BODY with PARAMS.
@@ -676,8 +731,8 @@ Expand a block of code with org-babel according to its 
header
 arguments.  This generic implementation of body expansion is
 called for languages which have not defined their own specific
 org-babel-expand-body:lang function."
-  (let ((pro (cdr (assoc :prologue params)))
-       (epi (cdr (assoc :epilogue params))))
+  (let ((pro (cdr (assq :prologue params)))
+       (epi (cdr (assq :epilogue params))))
     (mapconcat #'identity
               (append (when pro (list pro))
                       var-lines
@@ -708,10 +763,9 @@ arguments and pop open the results in a preview buffer."
            (org-babel-expand-body:generic
             body params (and (fboundp assignments-cmd)
                              (funcall assignments-cmd params))))))
-    (if (org-called-interactively-p 'any)
+    (if (called-interactively-p 'any)
        (org-edit-src-code
-        nil expanded
-        (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))
+        expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))
       expanded)))
 
 (defun org-babel-edit-distance (s1 s2)
@@ -742,7 +796,7 @@ arguments and pop open the results in a preview buffer."
       (dolist (arg-pair new-list)
        (let ((header (car arg-pair)))
          (setq results
-               (cons arg-pair (org-remove-if
+               (cons arg-pair (cl-remove-if
                                (lambda (pair) (equal header (car pair)))
                                results))))))
     results))
@@ -770,37 +824,43 @@ arguments and pop open the results in a preview buffer."
     (message "No suspicious header arguments found.")))
 
 ;;;###autoload
-(defun org-babel-insert-header-arg ()
+(defun org-babel-insert-header-arg (&optional header-arg value)
   "Insert a header argument selecting from lists of common args and values."
   (interactive)
-  (let* ((lang (car (org-babel-get-src-block-info 'light)))
+  (let* ((info (org-babel-get-src-block-info 'light))
+        (lang (car info))
+        (begin (nth 5 info))
         (lang-headers (intern (concat "org-babel-header-args:" lang)))
         (headers (org-babel-combine-header-arg-lists
                   org-babel-common-header-args-w-values
-                  (when (boundp lang-headers) (eval lang-headers))))
-        (arg (org-icompleting-read
-              "Header Arg: "
-              (mapcar
-               (lambda (header-spec) (symbol-name (car header-spec)))
-               headers))))
-    (insert ":" arg)
-    (let ((vals (cdr (assoc (intern arg) headers))))
-      (when vals
-       (insert
-        " "
-        (cond
-         ((eq vals :any)
-          (read-from-minibuffer "value: "))
-         ((listp vals)
-          (mapconcat
-           (lambda (group)
-             (let ((arg (org-icompleting-read
-                         "value: "
-                         (cons "default" (mapcar #'symbol-name group)))))
-               (if (and arg (not (string= "default" arg)))
-                   (concat arg " ")
-                 "")))
-           vals ""))))))))
+                  (when (boundp lang-headers) (eval lang-headers t))))
+        (header-arg (or header-arg
+                        (completing-read
+                         "Header Arg: "
+                         (mapcar
+                          (lambda (header-spec) (symbol-name (car 
header-spec)))
+                          headers))))
+        (vals (cdr (assoc (intern header-arg) headers)))
+        (value (or value
+                   (cond
+                    ((eq vals :any)
+                     (read-from-minibuffer "value: "))
+                    ((listp vals)
+                     (mapconcat
+                      (lambda (group)
+                        (let ((arg (completing-read
+                                    "Value: "
+                                    (cons "default"
+                                          (mapcar #'symbol-name group)))))
+                          (if (and arg (not (string= "default" arg)))
+                              (concat arg " ")
+                            "")))
+                      vals ""))))))
+    (save-excursion
+      (goto-char begin)
+      (goto-char (point-at-eol))
+      (unless (= (char-before (point)) ?\ ) (insert " "))
+      (insert ":" header-arg) (when value (insert " " value)))))
 
 ;; Add support for completing-read insertion of header arguments after ":"
 (defun org-babel-header-arg-expand ()
@@ -811,7 +871,7 @@ arguments and pop open the results in a preview buffer."
 (defun org-babel-enter-header-arg-w-completion (&optional lang)
   "Insert header argument appropriate for LANG with completion."
   (let* ((lang-headers-var (intern (concat "org-babel-header-args:" lang)))
-         (lang-headers (when (boundp lang-headers-var) (eval 
lang-headers-var)))
+         (lang-headers (when (boundp lang-headers-var) (eval lang-headers-var 
t)))
         (headers-w-values (org-babel-combine-header-arg-lists
                            org-babel-common-header-args-w-values lang-headers))
          (headers (mapcar #'symbol-name (mapcar #'car headers-w-values)))
@@ -842,8 +902,8 @@ session."
                       (if (org-babel-noweb-p params :eval)
                           (org-babel-expand-noweb-references info)
                         (nth 1 info)))))
-         (session (cdr (assoc :session params)))
-        (dir (cdr (assoc :dir params)))
+         (session (cdr (assq :session params)))
+        (dir (cdr (assq :dir params)))
         (default-directory
           (or (and dir (file-name-as-directory dir)) default-directory))
         (cmd (intern (concat "org-babel-load-session:" lang))))
@@ -863,17 +923,17 @@ the session.  Copy the body of the code block to the kill 
ring."
          (lang (nth 0 info))
          (body (nth 1 info))
          (params (nth 2 info))
-         (session (cdr (assoc :session params)))
-        (dir (cdr (assoc :dir params)))
+         (session (cdr (assq :session params)))
+        (dir (cdr (assq :dir params)))
         (default-directory
           (or (and dir (file-name-as-directory dir)) default-directory))
         (init-cmd (intern (format "org-babel-%s-initiate-session" lang)))
         (prep-cmd (intern (concat "org-babel-prep-session:" lang))))
-    (if (and (stringp session) (string= session "none"))
-       (error "This block is not using a session!"))
+    (when (and (stringp session) (string= session "none"))
+      (error "This block is not using a session!"))
     (unless (fboundp init-cmd)
       (error "No org-babel-initiate-session function for %s!" lang))
-    (with-temp-buffer (insert (org-babel-trim body))
+    (with-temp-buffer (insert (org-trim body))
                       (copy-region-as-kill (point-min) (point-max)))
     (when arg
       (unless (fboundp prep-cmd)
@@ -912,15 +972,15 @@ with a prefix argument then this is passed on to
     (org-edit-src-code)
     (funcall swap-windows)))
 
+;;;###autoload
 (defmacro org-babel-do-in-edit-buffer (&rest body)
   "Evaluate BODY in edit buffer if there is a code block at point.
 Return t if a code block was found at point, nil otherwise."
   `(let ((org-src-window-setup 'switch-invisibly))
      (when (and (org-babel-where-is-src-block-head)
-               (org-edit-src-code nil nil nil))
+               (org-edit-src-code))
        (unwind-protect (progn ,@body)
-        (if (org-bound-and-true-p org-edit-src-from-org-mode)
-            (org-edit-src-exit)))
+        (org-edit-src-exit))
        t)))
 (def-edebug-spec org-babel-do-in-edit-buffer (body))
 
@@ -928,10 +988,10 @@ Return t if a code block was found at point, nil 
otherwise."
   "Read key sequence and execute the command in edit buffer.
 Enter a key sequence to be executed in the language major-mode
 edit buffer.  For example, TAB will alter the contents of the
-Org-mode code block according to the effect of TAB in the
-language major-mode buffer.  For languages that support
-interactive sessions, this can be used to send code from the Org
-buffer to the session for evaluation using the native major-mode
+Org code block according to the effect of TAB in the language
+major mode buffer.  For languages that support interactive
+sessions, this can be used to send code from the Org buffer
+to the session for evaluation using the native major mode
 evaluation mechanisms."
   (interactive "kEnter key-sequence to execute in edit buffer: ")
   (org-babel-do-in-edit-buffer
@@ -941,7 +1001,7 @@ evaluation mechanisms."
 (defvar org-bracket-link-regexp)
 
 (defun org-babel-active-location-p ()
-  (memq (car (save-match-data (org-element-context)))
+  (memq (org-element-type (save-match-data (org-element-context)))
        '(babel-call inline-babel-call inline-src-block src-block)))
 
 ;;;###autoload
@@ -965,7 +1025,7 @@ results already exist."
            ;; file results
            (org-open-at-point)
          (let ((r (org-babel-format-result
-                   (org-babel-read-result) (cdr (assoc :sep (nth 2 info))))))
+                   (org-babel-read-result) (cdr (assq :sep (nth 2 info))))))
            (pop-to-buffer (get-buffer-create "*Org-Babel Results*"))
            (delete-region (point-min) (point-max))
            (insert r)))
@@ -995,7 +1055,8 @@ beg-body --------- point at the beginning of the body
 end-body --------- point at the end of the body"
   (declare (indent 1))
   (let ((tempvar (make-symbol "file")))
-    `(let* ((,tempvar ,file)
+    `(let* ((case-fold-search t)
+           (,tempvar ,file)
            (visited-p (or (null ,tempvar)
                           (get-file-buffer (expand-file-name ,tempvar))))
            (point (point)) to-be-removed)
@@ -1035,80 +1096,91 @@ end-body --------- point at the end of the body"
 
 ;;;###autoload
 (defmacro org-babel-map-inline-src-blocks (file &rest body)
-  "Evaluate BODY forms on each inline source-block in FILE.
+  "Evaluate BODY forms on each inline source block in FILE.
 If FILE is nil evaluate BODY forms on source blocks in current
 buffer."
-  (declare (indent 1))
-  (let ((tempvar (make-symbol "file")))
-    `(let* ((,tempvar ,file)
-           (visited-p (or (null ,tempvar)
+  (declare (indent 1) (debug (form body)))
+  (org-with-gensyms (datum end point tempvar to-be-removed visitedp)
+    `(let* ((case-fold-search t)
+           (,tempvar ,file)
+           (,visitedp (or (null ,tempvar)
                           (get-file-buffer (expand-file-name ,tempvar))))
-           (point (point)) to-be-removed)
+           (,point (point))
+           ,to-be-removed)
        (save-window-excursion
         (when ,tempvar (find-file ,tempvar))
-        (setq to-be-removed (current-buffer))
+        (setq ,to-be-removed (current-buffer))
         (goto-char (point-min))
-        (while (re-search-forward org-babel-inline-src-block-regexp nil t)
-          (when (org-babel-active-location-p)
-            (goto-char (match-beginning 1))
-            (save-match-data ,@body))
-          (goto-char (match-end 0))))
-       (unless visited-p (kill-buffer to-be-removed))
-       (goto-char point))))
-(def-edebug-spec org-babel-map-inline-src-blocks (form body))
-
-(defvar org-babel-lob-one-liner-regexp)
+        (while (re-search-forward "src_\\S-" nil t)
+          (let ((,datum (save-match-data (org-element-context))))
+            (when (eq (org-element-type ,datum) 'inline-src-block)
+              (goto-char (match-beginning 0))
+              (let ((,end (copy-marker (org-element-property :end ,datum))))
+                ,@body
+                (goto-char ,end)
+                (set-marker ,end nil))))))
+       (unless ,visitedp (kill-buffer ,to-be-removed))
+       (goto-char ,point))))
 
 ;;;###autoload
 (defmacro org-babel-map-call-lines (file &rest body)
   "Evaluate BODY forms on each call line in FILE.
 If FILE is nil evaluate BODY forms on source blocks in current
 buffer."
-  (declare (indent 1))
-  (let ((tempvar (make-symbol "file")))
-    `(let* ((,tempvar ,file)
-           (visited-p (or (null ,tempvar)
+  (declare (indent 1) (debug (form body)))
+  (org-with-gensyms (datum end point tempvar to-be-removed visitedp)
+    `(let* ((case-fold-search t)
+           (,tempvar ,file)
+           (,visitedp (or (null ,tempvar)
                           (get-file-buffer (expand-file-name ,tempvar))))
-           (point (point)) to-be-removed)
+           (,point (point))
+           ,to-be-removed)
        (save-window-excursion
         (when ,tempvar (find-file ,tempvar))
-        (setq to-be-removed (current-buffer))
+        (setq ,to-be-removed (current-buffer))
         (goto-char (point-min))
-        (while (re-search-forward org-babel-lob-one-liner-regexp nil t)
-          (when (org-babel-active-location-p)
-            (goto-char (match-beginning 1))
-            (save-match-data ,@body))
-          (goto-char (match-end 0))))
-       (unless visited-p (kill-buffer to-be-removed))
-       (goto-char point))))
-(def-edebug-spec org-babel-map-call-lines (form body))
+        (while (re-search-forward "call_\\S-\\|^[ \t]*#\\+CALL:" nil t)
+          (let ((,datum (save-match-data (org-element-context))))
+            (when (memq (org-element-type ,datum)
+                        '(babel-call inline-babel-call))
+              (goto-char (match-beginning 0))
+              (let ((,end (copy-marker (org-element-property :end ,datum))))
+                ,@body
+                (goto-char ,end)
+                (set-marker ,end nil))))))
+       (unless ,visitedp (kill-buffer ,to-be-removed))
+       (goto-char ,point))))
 
 ;;;###autoload
 (defmacro org-babel-map-executables (file &rest body)
-  (declare (indent 1))
-  (let ((tempvar (make-symbol "file"))
-       (rx (make-symbol "rx")))
-    `(let* ((,tempvar ,file)
-           (,rx (concat "\\(" org-babel-src-block-regexp
-                        "\\|" org-babel-inline-src-block-regexp
-                        "\\|" org-babel-lob-one-liner-regexp "\\)"))
-           (visited-p (or (null ,tempvar)
+  "Evaluate BODY forms on each active Babel code in FILE.
+If FILE is nil evaluate BODY forms on source blocks in current
+buffer."
+  (declare (indent 1) (debug (form body)))
+  (org-with-gensyms (datum end point tempvar to-be-removed visitedp)
+    `(let* ((case-fold-search t)
+           (,tempvar ,file)
+           (,visitedp (or (null ,tempvar)
                           (get-file-buffer (expand-file-name ,tempvar))))
-           (point (point)) to-be-removed)
+           (,point (point))
+           ,to-be-removed)
        (save-window-excursion
         (when ,tempvar (find-file ,tempvar))
-        (setq to-be-removed (current-buffer))
+        (setq ,to-be-removed (current-buffer))
         (goto-char (point-min))
-        (while (re-search-forward ,rx nil t)
-          (when (org-babel-active-location-p)
-            (goto-char (match-beginning 1))
-            (when (looking-at org-babel-inline-src-block-regexp)
-              (forward-char 1))
-            (save-match-data ,@body))
-          (goto-char (match-end 0))))
-       (unless visited-p (kill-buffer to-be-removed))
-       (goto-char point))))
-(def-edebug-spec org-babel-map-executables (form body))
+        (while (re-search-forward
+                "\\(call\\|src\\)_\\|^[ \t]*#\\+\\(BEGIN_SRC\\|CALL:\\)" nil t)
+          (let ((,datum (save-match-data (org-element-context))))
+            (when (memq (org-element-type ,datum)
+                        '(babel-call inline-babel-call inline-src-block
+                                     src-block))
+              (goto-char (match-beginning 0))
+              (let ((,end (copy-marker (org-element-property :end ,datum))))
+                ,@body
+                (goto-char ,end)
+                (set-marker ,end nil))))))
+       (unless ,visitedp (kill-buffer ,to-be-removed))
+       (goto-char ,point))))
 
 ;;;###autoload
 (defun org-babel-execute-buffer (&optional arg)
@@ -1119,7 +1191,8 @@ the current buffer."
   (org-babel-eval-wipe-error-buffer)
   (org-save-outline-visibility t
     (org-babel-map-executables nil
-      (if (looking-at org-babel-lob-one-liner-regexp)
+      (if (memq (org-element-type (org-element-context))
+               '(babel-call inline-babel-call))
           (org-babel-lob-execute-maybe)
         (org-babel-execute-src-block arg)))))
 
@@ -1164,7 +1237,20 @@ the current subtree."
                              (member (car arg) '(:results :exports)))
                         (mapconcat #'identity (sort (funcall rm (split-string 
v))
                                                     #'string<) " "))
-                       (t v)))))))
+                       (t v))))))
+          ;; expanded body
+          (lang (nth 0 info))
+          (params (nth 2 info))
+          (body (if (org-babel-noweb-p params :eval)
+                          (org-babel-expand-noweb-references info) (nth 1 
info)))
+          (expand-cmd (intern (concat "org-babel-expand-body:" lang)))
+          (assignments-cmd (intern (concat "org-babel-variable-assignments:"
+                                           lang)))
+          (expanded
+           (if (fboundp expand-cmd) (funcall expand-cmd body params)
+             (org-babel-expand-body:generic
+              body params (and (fboundp assignments-cmd)
+                               (funcall assignments-cmd params))))))
       (let* ((it (format "%s-%s"
                          (mapconcat
                           #'identity
@@ -1173,26 +1259,32 @@ the current subtree."
                                                 (when normalized
                                                   (format "%S" normalized))))
                                             (nth 2 info))) ":")
-                         (nth 1 info)))
+                         expanded))
              (hash (sha1 it)))
-        (when (org-called-interactively-p 'interactive) (message hash))
+        (when (called-interactively-p 'interactive) (message hash))
         hash))))
 
-(defun org-babel-current-result-hash ()
+(defun org-babel-current-result-hash (&optional info)
   "Return the current in-buffer hash."
-  (org-babel-where-is-src-block-result)
-  (org-no-properties (match-string 5)))
+  (let ((result (org-babel-where-is-src-block-result nil info)))
+    (when result
+      (org-with-wide-buffer
+       (goto-char result)
+       (looking-at org-babel-result-regexp)
+       (match-string-no-properties 1)))))
 
-(defun org-babel-set-current-result-hash (hash)
+(defun org-babel-set-current-result-hash (hash info)
   "Set the current in-buffer hash to HASH."
-  (org-babel-where-is-src-block-result)
-  (save-excursion (goto-char (match-beginning 5))
-                 (mapc #'delete-overlay (overlays-at (point)))
-                 (forward-char org-babel-hash-show)
-                 (mapc #'delete-overlay (overlays-at (point)))
-                 (replace-match hash nil nil nil 5)
-                 (goto-char (point-at-bol))
-                 (org-babel-hide-hash)))
+  (org-with-wide-buffer
+   (goto-char (org-babel-where-is-src-block-result nil info))
+   (looking-at org-babel-result-regexp)
+   (goto-char (match-beginning 1))
+   (mapc #'delete-overlay (overlays-at (point)))
+   (forward-char org-babel-hash-show)
+   (mapc #'delete-overlay (overlays-at (point)))
+   (replace-match hash nil nil nil 1)
+   (beginning-of-line)
+   (org-babel-hide-hash)))
 
 (defun org-babel-hide-hash ()
   "Hide the hash in the current results line.
@@ -1201,11 +1293,11 @@ will remain visible."
   (add-to-invisibility-spec '(org-babel-hide-hash . t))
   (save-excursion
     (when (and (re-search-forward org-babel-result-regexp nil t)
-               (match-string 5))
-      (let* ((start (match-beginning 5))
+               (match-string 1))
+      (let* ((start (match-beginning 1))
              (hide-start (+ org-babel-hash-show start))
-             (end (match-end 5))
-             (hash (match-string 5))
+             (end (match-end 1))
+             (hash (match-string 1))
              ov1 ov2)
         (setq ov1 (make-overlay start hide-start))
         (setq ov2 (make-overlay hide-start end))
@@ -1227,14 +1319,14 @@ the `org-mode-hook'."
 
 (defun org-babel-hash-at-point (&optional point)
   "Return the value of the hash at POINT.
+\\<org-mode-map>\
 The hash is also added as the last element of the kill ring.
-This can be called with C-c C-c."
+This can be called with `\\[org-ctrl-c-ctrl-c]'."
   (interactive)
   (let ((hash (car (delq nil (mapcar
                              (lambda (ol) (overlay-get ol 'babel-hash))
                               (overlays-at (or point (point))))))))
     (when hash (kill-new hash) (message hash))))
-(add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-hash-at-point)
 
 (defun org-babel-result-hide-spec ()
   "Hide portions of results lines.
@@ -1288,15 +1380,15 @@ portions of results lines."
                                 (eq (overlay-get overlay 'invisible)
                                    'org-babel-hide-result))
                               (overlays-at start)))
-              (if (or (not force) (eq force 'off))
-                  (mapc (lambda (ov)
-                          (when (member ov org-babel-hide-result-overlays)
-                            (setq org-babel-hide-result-overlays
-                                  (delq ov org-babel-hide-result-overlays)))
-                          (when (eq (overlay-get ov 'invisible)
-                                    'org-babel-hide-result)
-                            (delete-overlay ov)))
-                        (overlays-at start)))
+              (when (or (not force) (eq force 'off))
+               (mapc (lambda (ov)
+                       (when (member ov org-babel-hide-result-overlays)
+                         (setq org-babel-hide-result-overlays
+                               (delq ov org-babel-hide-result-overlays)))
+                       (when (eq (overlay-get ov 'invisible)
+                                 'org-babel-hide-result)
+                         (delete-overlay ov)))
+                     (overlays-at start)))
             (setq ov (make-overlay start end))
             (overlay-put ov 'invisible 'org-babel-hide-result)
             ;; make the block accessible to isearch
@@ -1316,8 +1408,8 @@ portions of results lines."
 (add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
 ;; Remove overlays when changing major mode
 (add-hook 'org-mode-hook
-         (lambda () (org-add-hook 'change-major-mode-hook
-                                  'org-babel-show-result-all 'append 'local)))
+         (lambda () (add-hook 'change-major-mode-hook
+                         'org-babel-show-result-all 'append 'local)))
 
 (defvar org-file-properties)
 (defun org-babel-params-from-properties (&optional lang)
@@ -1326,122 +1418,98 @@ Return a list of association lists of source block 
params
 specified in the properties of the current outline entry."
   (save-match-data
     (list
-     ;; DEPRECATED header arguments specified as separate property at
-     ;; point of definition
-     (let (val sym)
-       (org-babel-parse-multiple-vars
-       (delq nil
-             (mapcar
-              (lambda (header-arg)
-                (and (setq val (org-entry-get (point) header-arg t))
-                     (cons (intern (concat ":" header-arg))
-                           (org-babel-read val))))
-              (mapcar
-               #'symbol-name
-               (mapcar
-                #'car
-                (org-babel-combine-header-arg-lists
-                 org-babel-common-header-args-w-values
-                 (progn
-                   (setq sym (intern (concat "org-babel-header-args:" lang)))
-                   (and (boundp sym) (eval sym))))))))))
      ;; header arguments specified with the header-args property at
-     ;; point of call
+     ;; point of call.
      (org-babel-parse-header-arguments
       (org-entry-get org-babel-current-src-block-location
-                    "header-args" 'inherit))
-     (when lang ;; language-specific header arguments at point of call
-        (org-babel-parse-header-arguments
-         (org-entry-get org-babel-current-src-block-location
-                        (concat "header-args:" lang) 'inherit))))))
-
-(defvar org-src-preserve-indentation) ;; declare defcustom from org-src
-(defun org-babel-parse-src-block-match ()
-  "Parse the results from a match of the `org-babel-src-block-regexp'."
-  (let* ((block-indentation (length (match-string 1)))
-        (lang (org-no-properties (match-string 2)))
-         (lang-headers (intern (concat "org-babel-default-header-args:" lang)))
-        (switches (match-string 3))
-         (body (org-no-properties
-               (let* ((body (match-string 5))
-                      (sub-length (- (length body) 1)))
-                 (if (and (> sub-length 0)
-                          (string= "\n" (substring body sub-length)))
-                     (substring body 0 sub-length)
-                   (or body "")))))
-        (preserve-indentation (or org-src-preserve-indentation
-                                  (save-match-data
-                                    (string-match "-i\\>" switches)))))
-    (list lang
-          ;; get block body less properties, protective commas, and indentation
-          (with-temp-buffer
-            (save-match-data
-              (insert (org-unescape-code-in-string body))
-             (unless preserve-indentation (org-do-remove-indentation))
-              (buffer-string)))
-         (apply #'org-babel-merge-params
-                org-babel-default-header-args
-                (when (boundp lang-headers) (eval lang-headers))
-                (append
-                 (org-babel-params-from-properties lang)
-                 (list (org-babel-parse-header-arguments
-                        (org-no-properties (or (match-string 4) ""))))))
-         switches
-         block-indentation)))
-
-(defun org-babel-parse-inline-src-block-match ()
-  "Parse the results from a match of the `org-babel-inline-src-block-regexp'."
-  (let* ((lang (org-no-properties (match-string 2)))
-         (lang-headers (intern (concat "org-babel-default-header-args:" 
lang))))
-    (list lang
-          (org-unescape-code-in-string (org-no-properties (match-string 5)))
-          (apply #'org-babel-merge-params
-                org-babel-default-inline-header-args
-                (if (boundp lang-headers) (eval lang-headers) nil)
-                (append
-                 (org-babel-params-from-properties lang)
-                 (list (org-babel-parse-header-arguments
-                        (org-no-properties (or (match-string 4) "")))))))))
+                    "header-args"
+                    'inherit))
+     (and lang  ; language-specific header arguments at point of call
+         (org-babel-parse-header-arguments
+          (org-entry-get org-babel-current-src-block-location
+                         (concat "header-args:" lang)
+                         'inherit))))))
 
 (defun org-babel-balanced-split (string alts)
   "Split STRING on instances of ALTS.
-ALTS is a cons of two character options where each option may be
-either the numeric code of a single character or a list of
-character alternatives.  For example to split on balanced
-instances of \"[ \t]:\" set ALTS to ((32 9) . 58)."
-  (let* ((matches (lambda (ch spec) (if (listp spec) (member ch spec) (equal 
spec ch))))
-        (matched (lambda (ch last)
-                   (if (consp alts)
-                       (and (funcall matches ch (cdr alts))
-                            (funcall matches last (car alts)))
-                     (funcall matches ch alts))))
-        (balance 0) (last 0)
-        quote partial lst)
-    (mapc (lambda (ch)  ; split on [], (), "" balanced instances of [ \t]:
-           (setq balance (+ balance
-                            (cond ((or (equal 91 ch) (equal 40 ch)) 1)
-                                  ((or (equal 93 ch) (equal 41 ch)) -1)
-                                  (t 0))))
-           (when (and (equal 34 ch) (not (equal 92 last)))
-             (setq quote (not quote)))
-           (setq partial (cons ch partial))
-           (when (and (= balance 0) (not quote) (funcall matched ch last))
-             (setq lst (cons (apply #'string (nreverse
-                                              (if (consp alts)
-                                                  (cddr partial)
-                                                (cdr partial))))
-                             lst))
-             (setq partial nil))
-           (setq last ch))
-         (string-to-list string))
-    (nreverse (cons (apply #'string (nreverse partial)) lst))))
+ALTS is a character, or cons of two character options where each
+option may be either the numeric code of a single character or
+a list of character alternatives.  For example, to split on
+balanced instances of \"[ \t]:\", set ALTS to ((32 9) . 58)."
+  (with-temp-buffer
+    (insert string)
+    (goto-char (point-min))
+    (let ((splitp (lambda (past next)
+                   ;; Non-nil when there should be a split after NEXT
+                   ;; character. PAST is the character before NEXT.
+                   (pcase alts
+                     (`(,(and first (pred consp)) . ,(and second (pred consp)))
+                      (and (memq past first) (memq next second)))
+                     (`(,first . ,(and second (pred consp)))
+                      (and (eq past first) (memq next second)))
+                     (`(,(and first (pred consp)) . ,second)
+                      (and (memq past first) (eq next second)))
+                     (`(,first . ,second)
+                      (and (eq past first) (eq next second)))
+                     ((pred (eq next)) t)
+                     (_ nil))))
+         (partial nil)
+         (result nil))
+      (while (not (eobp))
+        (cond
+        ((funcall splitp (char-before) (char-after))
+         ;; There is a split after point.  If ALTS is two-folds,
+         ;; remove last parsed character as it belongs to ALTS.
+         (when (consp alts) (pop partial))
+         ;; Include elements parsed so far in RESULTS and flush
+         ;; partial parsing.
+         (when partial
+           (push (apply #'string (nreverse partial)) result)
+           (setq partial nil))
+         (forward-char))
+        ((memq (char-after) '(?\( ?\[))
+         ;; Include everything between balanced brackets.
+         (let* ((origin (point))
+                (after (char-after))
+                (openings (list after)))
+           (forward-char)
+           (while (and openings (re-search-forward "[]()]" nil t))
+             (pcase (char-before)
+               ((and match (or ?\[ ?\()) (push match openings))
+               (?\] (when (eq ?\[ (car openings)) (pop openings)))
+               (_ (when (eq ?\( (car openings)) (pop openings)))))
+           (if (null openings)
+               (setq partial
+                     (nconc (nreverse (string-to-list
+                                       (buffer-substring origin (point))))
+                            partial))
+             ;; Un-balanced bracket.  Backtrack.
+             (push after partial)
+             (goto-char (1+ origin)))))
+        ((and (eq ?\" (char-after)) (not (eq ?\\ (char-before))))
+         ;; Include everything from current double quote to next
+         ;; non-escaped double quote.
+         (let ((origin (point)))
+           (if (re-search-forward "[^\\]\"" nil t)
+               (setq partial
+                     (nconc (nreverse (string-to-list
+                                       (buffer-substring origin (point))))
+                            partial))
+             ;; No closing double quote.  Backtrack.
+             (push ?\" partial)
+             (forward-char))))
+        (t (push (char-after) partial)
+           (forward-char))))
+      ;; Add pending parsing and return result.
+      (when partial (push (apply #'string (nreverse partial)) result))
+      (nreverse result))))
 
 (defun org-babel-join-splits-near-ch (ch list)
   "Join splits where \"=\" is on either end of the split."
   (let ((last= (lambda (str) (= ch (aref str (1- (length str))))))
        (first= (lambda (str) (= ch (aref str 0)))))
     (reverse
-     (org-reduce (lambda (acc el)
+     (cl-reduce (lambda (acc el)
                   (let ((head (car acc)))
                     (if (and head (or (funcall last= head) (funcall first= 
el)))
                         (cons (concat head el) (cdr acc))
@@ -1474,7 +1542,7 @@ shown below.
   (let (results)
     (mapc (lambda (pair)
            (if (eq (car pair) :var)
-               (mapcar (lambda (v) (push (cons :var (org-babel-trim v)) 
results))
+               (mapcar (lambda (v) (push (cons :var (org-trim v)) results))
                        (org-babel-join-splits-near-ch
                         61 (org-babel-balanced-split (cdr pair) 32)))
              (push pair results)))
@@ -1484,48 +1552,52 @@ shown below.
 (defun org-babel-process-params (params)
   "Expand variables in PARAMS and add summary parameters."
   (let* ((processed-vars (mapcar (lambda (el)
-                                  (if (consp (cdr el))
-                                      (cdr el)
-                                    (org-babel-ref-parse (cdr el))))
-                                (org-babel-get-header params :var)))
-        (vars-and-names (if (and (assoc :colname-names params)
-                                 (assoc :rowname-names params))
+                                  (if (consp el)
+                                      el
+                                    (org-babel-ref-parse el)))
+                                (org-babel--get-vars params)))
+        (vars-and-names (if (and (assq :colname-names params)
+                                 (assq :rowname-names params))
                             (list processed-vars)
                           (org-babel-disassemble-tables
                            processed-vars
-                           (cdr (assoc :hlines params))
-                           (cdr (assoc :colnames params))
-                           (cdr (assoc :rownames params)))))
-        (raw-result (or (cdr (assoc :results params)) ""))
-        (result-params (append
-                        (split-string (if (stringp raw-result)
-                                          raw-result
-                                        (eval raw-result)))
-                        (cdr (assoc :result-params params)))))
+                           (cdr (assq :hlines params))
+                           (cdr (assq :colnames params))
+                           (cdr (assq :rownames params)))))
+        (raw-result (or (cdr (assq :results params)) ""))
+        (result-params (delete-dups
+                        (append
+                         (split-string (if (stringp raw-result)
+                                           raw-result
+                                         (eval raw-result t)))
+                         (cdr (assq :result-params params))))))
     (append
      (mapcar (lambda (var) (cons :var var)) (car vars-and-names))
      (list
-      (cons :colname-names (or (cdr (assoc :colname-names params))
+      (cons :colname-names (or (cdr (assq :colname-names params))
                               (cadr  vars-and-names)))
-      (cons :rowname-names (or (cdr (assoc :rowname-names params))
-                              (caddr vars-and-names)))
+      (cons :rowname-names (or (cdr (assq :rowname-names params))
+                              (cl-caddr vars-and-names)))
       (cons :result-params result-params)
       (cons :result-type  (cond ((member "output" result-params) 'output)
                                ((member "value" result-params) 'value)
                                (t 'value))))
-     (org-babel-get-header params :var 'other))))
+     (cl-remove-if
+      (lambda (x) (memq (car x) '(:colname-names :rowname-names :result-params
+                                           :result-type :var)))
+      params))))
 
 ;; row and column names
 (defun org-babel-del-hlines (table)
   "Remove all `hline's from TABLE."
-  (remove 'hline table))
+  (remq 'hline table))
 
 (defun org-babel-get-colnames (table)
   "Return the column names of TABLE.
 Return a cons cell, the `car' of which contains the TABLE less
 colnames, and the `cdr' of which contains a list of the column
 names."
-  (if (equal 'hline (nth 1 table))
+  (if (eq 'hline (nth 1 table))
       (cons (cddr table) (car table))
     (cons (cdr table) (car table))))
 
@@ -1583,7 +1655,7 @@ of the vars, cnames and rnames."
       (lambda (var)
         (when (listp (cdr var))
           (when (and (not (equal colnames "no"))
-                     (or colnames (and (equal (nth 1 (cdr var)) 'hline)
+                     (or colnames (and (eq (nth 1 (cdr var)) 'hline)
                                        (not (member 'hline (cddr (cdr 
var)))))))
             (let ((both (org-babel-get-colnames (cdr var))))
               (setq cnames (cons (cons (car var) (cdr both))
@@ -1612,35 +1684,26 @@ to the table for reinsertion to org-mode."
             (org-babel-put-colnames table colnames) table))
     table))
 
-(defun org-babel-where-is-src-block-head ()
+(defun org-babel-where-is-src-block-head (&optional src-block)
   "Find where the current source block begins.
-Return the point at the beginning of the current source
-block.  Specifically at the beginning of the #+BEGIN_SRC line.
+
+If optional argument SRC-BLOCK is `src-block' type element, find
+its current beginning instead.
+
+Return the point at the beginning of the current source block.
+Specifically at the beginning of the #+BEGIN_SRC line.  Also set
+match-data relatively to `org-babel-src-block-regexp', which see.
 If the point is not on a source block then return nil."
-  (let ((initial (point)) (case-fold-search t) top bottom)
-    (or
-     (save-excursion ;; on a source name line or a #+header line
-       (beginning-of-line 1)
-       (and (or (looking-at org-babel-src-name-regexp)
-               (looking-at org-babel-multi-line-header-regexp))
-           (progn
-             (while (and (forward-line 1)
-                         (or (looking-at org-babel-src-name-regexp)
-                             (looking-at org-babel-multi-line-header-regexp))))
-             (looking-at org-babel-src-block-regexp))
-            (point)))
-     (save-excursion ;; on a #+begin_src line
-       (beginning-of-line 1)
-       (and (looking-at org-babel-src-block-regexp)
-            (point)))
-     (save-excursion ;; inside a src block
-       (and
-        (re-search-backward "^[ \t]*#\\+begin_src" nil t) (setq top (point))
-        (re-search-forward "^[ \t]*#\\+end_src" nil t) (setq bottom (point))
-        (< top initial) (< initial bottom)
-        (progn (goto-char top) (beginning-of-line 1)
-              (looking-at org-babel-src-block-regexp))
-        (point-marker))))))
+  (let ((element (or src-block (org-element-at-point))))
+    (when (eq (org-element-type element) 'src-block)
+      (let ((end (org-element-property :end element)))
+       (org-with-wide-buffer
+        ;; Ensure point is not on a blank line after the block.
+        (beginning-of-line)
+        (skip-chars-forward " \r\t\n" end)
+        (when (< (point) end)
+          (prog1 (goto-char (org-element-property :post-affiliated element))
+            (looking-at org-babel-src-block-regexp))))))))
 
 ;;;###autoload
 (defun org-babel-goto-src-block-head ()
@@ -1655,56 +1718,52 @@ If the point is not on a source block then return nil."
   (interactive
    (let ((completion-ignore-case t)
         (case-fold-search t)
-        (under-point (thing-at-point 'line)))
-     (list (org-icompleting-read
-           "source-block name: " (org-babel-src-block-names) nil t
-           (cond
-            ;; noweb
-            ((string-match (org-babel-noweb-wrap) under-point)
-             (let ((block-name (match-string 1 under-point)))
-               (string-match "[^(]*" block-name)
-               (match-string 0 block-name)))
-            ;; #+call:
-            ((string-match org-babel-lob-one-liner-regexp under-point)
-             (let ((source-info (car (org-babel-lob-get-info))))
-               (if (string-match "^\\([^\\[]+?\\)\\(\\[.*\\]\\)?(" source-info)
-                   (let ((source-name (match-string 1 source-info)))
-                     source-name))))
-            ;; #+results:
-            ((string-match (concat "#\\+" org-babel-results-keyword
-                                   "\\:\s+\\([^\\(]*\\)") under-point)
-             (match-string 1 under-point))
-            ;; symbol-at-point
-            ((and (thing-at-point 'symbol))
-             (org-babel-find-named-block (thing-at-point 'symbol))
-             (thing-at-point 'symbol))
-            (""))))))
+        (all-block-names (org-babel-src-block-names)))
+     (list (completing-read
+           "source-block name: " all-block-names nil t
+           (let* ((context (org-element-context))
+                  (type (org-element-type context))
+                  (noweb-ref
+                   (and (memq type '(inline-src-block src-block))
+                        (org-in-regexp (org-babel-noweb-wrap)))))
+             (cond
+              (noweb-ref
+               (buffer-substring
+                (+ (car noweb-ref) (length org-babel-noweb-wrap-start))
+                (- (cdr noweb-ref) (length org-babel-noweb-wrap-end))))
+              ((memq type '(babel-call inline-babel-call)) ;#+CALL:
+               (org-element-property :call context))
+              ((car (org-element-property :results context))) ;#+RESULTS:
+              ((let ((symbol (thing-at-point 'symbol))) ;Symbol.
+                 (and symbol
+                      (member-ignore-case symbol all-block-names)
+                      symbol)))
+              (t "")))))))
   (let ((point (org-babel-find-named-block name)))
     (if point
-        ;; taken from `org-open-at-point'
+        ;; Taken from `org-open-at-point'.
         (progn (org-mark-ring-push) (goto-char point) (org-show-context))
       (message "source-code block `%s' not found in this buffer" name))))
 
 (defun org-babel-find-named-block (name)
   "Find a named source-code block.
 Return the location of the source block identified by source
-NAME, or nil if no such block exists.  Set match data according to
-org-babel-named-src-block-regexp."
+NAME, or nil if no such block exists.  Set match data according
+to `org-babel-named-src-block-regexp'."
   (save-excursion
-    (let ((case-fold-search t)
-         (regexp (org-babel-named-src-block-regexp-for-name name)))
-      (goto-char (point-min))
-      (when (or (re-search-forward regexp nil t)
-               (re-search-backward regexp nil t))
-        (match-beginning 0)))))
+    (goto-char (point-min))
+    (ignore-errors
+      (org-next-block 1 nil (org-babel-named-src-block-regexp-for-name 
name)))))
 
 (defun org-babel-src-block-names (&optional file)
   "Returns the names of source blocks in FILE or the current buffer."
+  (when file (find-file file))
   (save-excursion
-    (when file (find-file file)) (goto-char (point-min))
-    (let ((case-fold-search t) names)
-      (while (re-search-forward org-babel-src-name-w-name-regexp nil t)
-       (setq names (cons (match-string 3) names)))
+    (goto-char (point-min))
+    (let ((re (org-babel-named-src-block-regexp-for-name))
+         names)
+      (while (ignore-errors (org-next-block 1 nil re))
+       (push (match-string-no-properties 9) names))
       names)))
 
 ;;;###autoload
@@ -1712,33 +1771,31 @@ org-babel-named-src-block-regexp."
   "Go to a named result."
   (interactive
    (let ((completion-ignore-case t))
-     (list (org-icompleting-read "source-block name: "
-                                (org-babel-result-names) nil t))))
+     (list (completing-read "Source-block name: "
+                           (org-babel-result-names) nil t))))
   (let ((point (org-babel-find-named-result name)))
     (if point
         ;; taken from `org-open-at-point'
         (progn (goto-char point) (org-show-context))
       (message "result `%s' not found in this buffer" name))))
 
-(defun org-babel-find-named-result (name &optional point)
+(defun org-babel-find-named-result (name)
   "Find a named result.
 Return the location of the result named NAME in the current
 buffer or nil if no such result exists."
   (save-excursion
-    (let ((case-fold-search t))
-      (goto-char (or point (point-min)))
-      (catch 'is-a-code-block
-       (when (re-search-forward
-              (concat org-babel-result-regexp
-                      "[ \t]" (regexp-quote name) "[ \t]*[\n\f\v\r]")
-               nil t)
-         (when (and (string= "name" (downcase (match-string 1)))
-                    (or (beginning-of-line 1)
-                        (looking-at org-babel-src-block-regexp)
-                        (looking-at org-babel-multi-line-header-regexp)
-                        (looking-at org-babel-lob-one-liner-regexp)))
-           (throw 'is-a-code-block (org-babel-find-named-result name (point))))
-         (beginning-of-line 0) (point))))))
+    (goto-char (point-min))
+    (let ((case-fold-search t)
+         (re (format "^[ \t]*#\\+%s.*?:[ \t]*%s[ \t]*$"
+                     org-babel-results-keyword
+                     (regexp-quote name))))
+      (catch :found
+       (while (re-search-forward re nil t)
+         (let ((element (org-element-at-point)))
+           (when (or (eq (org-element-type element) 'keyword)
+                     (< (point)
+                        (org-element-property :post-affiliated element)))
+             (throw :found (line-beginning-position)))))))))
 
 (defun org-babel-result-names (&optional file)
   "Returns the names of results in FILE or the current buffer."
@@ -1746,7 +1803,7 @@ buffer or nil if no such result exists."
     (when file (find-file file)) (goto-char (point-min))
     (let ((case-fold-search t) names)
       (while (re-search-forward org-babel-result-w-name-regexp nil t)
-       (setq names (cons (match-string 4) names)))
+       (setq names (cons (match-string-no-properties 9) names)))
       names)))
 
 ;;;###autoload
@@ -1784,26 +1841,31 @@ split.  When called from outside of a code block a new 
code block
 is created.  In both cases if the region is demarcated and if the
 region is not active then the point is demarcated."
   (interactive "P")
-  (let ((info (org-babel-get-src-block-info 'light))
-       (headers (progn (org-babel-where-is-src-block-head)
-                       (match-string 4)))
-       (stars (concat (make-string (or (org-current-level) 1) ?*) " ")))
+  (let* ((info (org-babel-get-src-block-info 'light))
+        (start (org-babel-where-is-src-block-head))
+        (block (and start (match-string 0)))
+        (headers (and start (match-string 4)))
+        (stars (concat (make-string (or (org-current-level) 1) ?*) " "))
+        (lower-case-p (and block
+                           (let (case-fold-search)
+                             (string-match-p "#\\+begin_src" block)))))
     (if info
         (mapc
          (lambda (place)
            (save-excursion
              (goto-char place)
              (let ((lang (nth 0 info))
-                   (indent (make-string (nth 5 info) ? )))
+                   (indent (make-string (org-get-indentation) ?\s)))
               (when (string-match "^[[:space:]]*$"
                                   (buffer-substring (point-at-bol)
                                                     (point-at-eol)))
                 (delete-region (point-at-bol) (point-at-eol)))
                (insert (concat
                        (if (looking-at "^") "" "\n")
-                       indent "#+end_src\n"
+                       indent (funcall (if lower-case-p 'downcase 'upcase) 
"#+end_src\n")
                        (if arg stars indent) "\n"
-                       indent "#+begin_src " lang
+                       indent (funcall (if lower-case-p 'downcase 'upcase) 
"#+begin_src ")
+                       lang
                        (if (> (length headers) 1)
                            (concat " " headers) headers)
                        (if (looking-at "[\n\r]")
@@ -1812,7 +1874,7 @@ region is not active then the point is demarcated."
           (move-end-of-line 2))
          (sort (if (org-region-active-p) (list (mark) (point)) (list (point))) 
#'>))
       (let ((start (point))
-           (lang (org-icompleting-read
+           (lang (completing-read
                   "Lang: "
                   (mapcar #'symbol-name
                           (delete-dups
@@ -1823,134 +1885,222 @@ region is not active then the point is demarcated."
                   (if (org-region-active-p) (mark) (point)) (point))))
        (insert (concat (if (looking-at "^") "" "\n")
                        (if arg (concat stars "\n") "")
-                       "#+begin_src " lang "\n"
+                       (funcall (if lower-case-p 'downcase 'upcase) 
"#+begin_src ")
+                       lang "\n"
                        body
                        (if (or (= (length body) 0)
-                               (string-match "[\r\n]$" body)) "" "\n")
-                       "#+end_src\n"))
+                               (string-suffix-p "\r" body)
+                               (string-suffix-p "\n" body)) "" "\n")
+                       (funcall (if lower-case-p 'downcase 'upcase) 
"#+end_src\n")))
        (goto-char start) (move-end-of-line 1)))))
 
-(defvar org-babel-lob-one-liner-regexp)
-(defun org-babel-where-is-src-block-result (&optional insert info hash indent)
+(defun org-babel--insert-results-keyword (name hash)
+  "Insert RESULTS keyword with NAME value at point.
+If NAME is nil, results are anonymous.  HASH is a string used as
+the results hash, or nil.  Leave point before the keyword."
+  (save-excursion (insert "\n"))       ;open line to indent.
+  (org-indent-line)
+  (delete-char 1)
+  (insert (concat "#+" org-babel-results-keyword
+                 (cond ((not hash) nil)
+                       (org-babel-hash-show-time
+                        (format "[%s %s]"
+                                (format-time-string "<%F %T>")
+                                hash))
+                       (t (format "[%s]" hash)))
+                 ":"
+                 (when name (concat " " name))
+                 "\n"))
+  ;; Make sure results are going to be followed by at least one blank
+  ;; line so they do not get merged with the next element, e.g.,
+  ;;
+  ;;   #+results:
+  ;;   : 1
+  ;;
+  ;;   : fixed-width area, unrelated to the above.
+  (unless (looking-at "^[ \t]*$") (save-excursion (insert "\n")))
+  (beginning-of-line 0)
+  (when hash (org-babel-hide-hash)))
+
+(defun org-babel--clear-results-maybe (hash)
+  "Clear results when hash doesn't match HASH.
+
+When results hash does not match HASH, remove RESULTS keyword at
+point, along with related contents.  Do nothing if HASH is nil.
+
+Return a non-nil value if results were cleared.  In this case,
+leave point where new results should be inserted."
+  (when hash
+    (looking-at org-babel-result-regexp)
+    (unless (string= (match-string 1) hash)
+      (let* ((e (org-element-at-point))
+            (post (copy-marker (org-element-property :post-affiliated e))))
+       ;; Delete contents.
+       (delete-region post
+                      (save-excursion
+                        (goto-char (org-element-property :end e))
+                        (skip-chars-backward " \t\n")
+                        (line-beginning-position 2)))
+       ;; Delete RESULT keyword.  However, if RESULTS keyword is
+       ;; orphaned, ignore this part.  The deletion above already
+       ;; took care of it.
+       (unless (= (point) post)
+         (delete-region (line-beginning-position)
+                        (line-beginning-position 2)))
+       (goto-char post)
+       (set-marker post nil)
+       t))))
+
+(defun org-babel-where-is-src-block-result (&optional insert _info hash)
   "Find where the current source block results begin.
+
 Return the point at the beginning of the result of the current
-source block.  Specifically at the beginning of the results line.
-If no result exists for this block then create a results line
-following the source block."
-  (save-excursion
-    (let* ((case-fold-search t)
-          (on-lob-line (save-excursion
-                         (beginning-of-line 1)
-                         (looking-at org-babel-lob-one-liner-regexp)))
-          (inlinep (when (org-babel-get-inline-src-block-matches)
-                     (match-end 0)))
-          (name (nth 4 (or info (org-babel-get-src-block-info 'light))))
-          (head (unless on-lob-line (org-babel-where-is-src-block-head)))
-          found beg end)
-      (when head (goto-char head))
+source block, specifically at the beginning of the results line.
+
+If no result exists for this block return nil, unless optional
+argument INSERT is non-nil.  In this case, create a results line
+following the source block and return the position at its
+beginning.  In the case of inline code, remove the results part
+instead.
+
+If optional argument HASH is a string, remove contents related to
+RESULTS keyword if its hash is different.  Then update the latter
+to HASH."
+  (let ((context (org-element-context)))
+    (catch :found
       (org-with-wide-buffer
-       (setq
-       found ;; was there a result (before we potentially insert one)
-       (or
-        inlinep
-        (and
-         ;; named results:
-         ;; - return t if it is found, else return nil
-         ;; - if it does not need to be rebuilt, then don't set end
-         ;; - if it does need to be rebuilt then do set end
-         name (setq beg (org-babel-find-named-result name))
-         (prog1 beg
-           (when (and hash (not (string= hash (match-string 5))))
-             (goto-char beg) (setq end beg) ;; beginning of result
-             (forward-line 1)
-             (delete-region end (org-babel-result-end)) nil)))
-        (and
-         ;; unnamed results:
-         ;; - return t if it is found, else return nil
-         ;; - if it is found, and the hash doesn't match, delete and set end
-         (or on-lob-line (re-search-forward "^[ \t]*#\\+end_src" nil t))
-         (progn (end-of-line 1)
-                (if (eobp) (insert "\n") (forward-char 1))
-                (setq end (point))
-                (or (and
-                     (not name)
-                     (progn ;; unnamed results line already exists
-                       (catch 'non-comment
-                         (while (re-search-forward "[^ \f\t\n\r\v]" nil t)
-                           (beginning-of-line 1)
-                           (cond
-                            ((looking-at (concat org-babel-result-regexp "\n"))
-                             (throw 'non-comment t))
-                            ((looking-at "^[ \t]*#") (end-of-line 1))
-                            (t (throw 'non-comment nil))))))
-                     (let ((this-hash (match-string 5)))
-                       (prog1 (point)
-                         ;; must remove and rebuild if hash!=old-hash
-                         (if (and hash (not (string= hash this-hash)))
-                             (prog1 nil
-                               (forward-line 1)
-                               (delete-region
-                                end (org-babel-result-end)))
-                           (setq end nil)))))))))))
-      (if (not (and insert end)) found
-       (goto-char end)
-       (unless beg
-         (if (looking-at "[\n\r]") (forward-char 1) (insert "\n")))
-       (insert (concat
-                (when (wholenump indent) (make-string indent ? ))
-                "#+" org-babel-results-keyword
-                (when hash
-                  (if org-babel-hash-show-time
-                      (concat
-                       "["(format-time-string "<%Y-%m-%d %H:%M:%S>")" "hash"]")
-                    (concat "["hash"]")))
-                ":"
-                (when name (concat " " name)) "\n"))
-       (unless beg (insert "\n") (backward-char))
-       (beginning-of-line 0)
-       (if hash (org-babel-hide-hash))
-       (point)))))
-
-(defvar org-block-regexp)
+       (pcase (org-element-type context)
+        ((or `inline-babel-call `inline-src-block)
+         ;; Results for inline objects are located right after them.
+         ;; There is no RESULTS line to insert either.
+         (let ((limit (org-element-property
+                       :contents-end (org-element-property :parent context))))
+           (goto-char (org-element-property :end context))
+           (skip-chars-forward " \t\n" limit)
+           (throw :found
+                  (and
+                   (< (point) limit)
+                   (let ((result (org-element-context)))
+                     (and (eq (org-element-type result) 'macro)
+                          (string= (org-element-property :key result)
+                                   "results")
+                          (if (not insert) (point)
+                            (delete-region
+                             (point)
+                             (progn
+                               (goto-char (org-element-property :end result))
+                               (skip-chars-backward " \t")
+                               (point)))
+                            (point))))))))
+        ((or `babel-call `src-block)
+         (let* ((name (org-element-property :name context))
+                (named-results (and name (org-babel-find-named-result name))))
+           (goto-char (or named-results (org-element-property :end context)))
+           (cond
+            ;; Existing results named after the current source.
+            (named-results
+             (when (org-babel--clear-results-maybe hash)
+               (org-babel--insert-results-keyword name hash))
+             (throw :found (point)))
+            ;; Named results expect but none to be found.
+            (name)
+            ;; No possible anonymous results at the very end of
+            ;; buffer or outside CONTEXT parent.
+            ((eq (point)
+                 (or (org-element-property
+                      :contents-end (org-element-property :parent context))
+                     (point-max))))
+            ;; Check if next element is an anonymous result below
+            ;; the current block.
+            ((let* ((next (org-element-at-point))
+                    (end (save-excursion
+                           (goto-char
+                            (org-element-property :post-affiliated next))
+                           (line-end-position)))
+                    (empty-result-re (concat org-babel-result-regexp "$"))
+                    (case-fold-search t))
+               (re-search-forward empty-result-re end t))
+             (beginning-of-line)
+             (when (org-babel--clear-results-maybe hash)
+               (org-babel--insert-results-keyword nil hash))
+             (throw :found (point))))))
+        ;; Ignore other elements.
+        (_ (throw :found nil))))
+      ;; No result found.  Insert a RESULTS keyword below element, if
+      ;; appropriate.  In this case, ensure there is an empty line
+      ;; after the previous element.
+      (when insert
+       (save-excursion
+         (goto-char (min (org-element-property :end context) (point-max)))
+         (skip-chars-backward " \t\n")
+         (forward-line)
+         (unless (bolp) (insert "\n"))
+         (insert "\n")
+         (org-babel--insert-results-keyword
+          (org-element-property :name context) hash)
+         (point))))))
+
+(defun org-babel-read-element (element)
+  "Read ELEMENT into emacs-lisp.
+Return nil if ELEMENT cannot be read."
+  (org-with-wide-buffer
+   (goto-char (org-element-property :post-affiliated element))
+   (pcase (org-element-type element)
+     (`fixed-width
+      (let ((v (org-trim (org-element-property :value element))))
+       (or (org-babel--string-to-number v) v)))
+     (`table (org-babel-read-table))
+     (`plain-list (org-babel-read-list))
+     (`example-block
+      (let ((v (org-element-property :value element)))
+       (if (or org-src-preserve-indentation
+               (org-element-property :preserve-indent element))
+           v
+         (org-remove-indentation v))))
+     (`export-block
+      (org-remove-indentation (org-element-property :value element)))
+     (`paragraph
+      ;; Treat paragraphs containing a single link specially.
+      (skip-chars-forward " \t")
+      (if (and (looking-at org-bracket-link-regexp)
+              (save-excursion
+                (goto-char (match-end 0))
+                (skip-chars-forward " \r\t\n")
+                (<= (org-element-property :end element)
+                    (point))))
+         (org-babel-read-link)
+       (buffer-substring-no-properties
+        (org-element-property :contents-begin element)
+        (org-element-property :contents-end element))))
+     ((or `center-block `quote-block `verse-block `special-block)
+      (org-remove-indentation
+       (buffer-substring-no-properties
+       (org-element-property :contents-begin element)
+       (org-element-property :contents-end element))))
+     (_ nil))))
+
 (defun org-babel-read-result ()
-  "Read the result at `point' into emacs-lisp."
-  (let ((case-fold-search t) result-string)
-    (cond
-     ((org-at-table-p) (org-babel-read-table))
-     ((org-at-item-p) (org-babel-read-list))
-     ((looking-at org-bracket-link-regexp) (org-babel-read-link))
-     ((looking-at org-block-regexp) (org-babel-trim (match-string 4)))
-     ((or (looking-at "^[ \t]*: ") (looking-at "^[ \t]*:$"))
-      (setq result-string
-           (org-babel-trim
-            (mapconcat (lambda (line)
-                          (or (and (> (length line) 1)
-                                  (string-match "^[ \t]*: ?\\(.+\\)" line)
-                                  (match-string 1 line))
-                             ""))
-                       (split-string
-                        (buffer-substring
-                          (point) (org-babel-result-end)) "[\r\n]+")
-                       "\n")))
-      (or (org-babel-number-p result-string) result-string))
-     ((looking-at org-babel-result-regexp)
-      (save-excursion (forward-line 1) (org-babel-read-result))))))
+  "Read the result at point into emacs-lisp."
+  (and (not (save-excursion
+             (beginning-of-line)
+             (looking-at-p "[ \t]*$")))
+       (org-babel-read-element (org-element-at-point))))
 
 (defun org-babel-read-table ()
-  "Read the table at `point' into emacs-lisp."
+  "Read the table at point into emacs-lisp."
   (mapcar (lambda (row)
             (if (and (symbolp row) (equal row 'hline)) row
               (mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval)) 
row)))
           (org-table-to-lisp)))
 
 (defun org-babel-read-list ()
-  "Read the list at `point' into emacs-lisp."
+  "Read the list at point into emacs-lisp."
   (mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval))
-         (mapcar #'cadr (cdr (org-list-parse-list)))))
+         (cdr (org-list-to-lisp))))
 
 (defvar org-link-types-re)
 (defun org-babel-read-link ()
-  "Read the link at `point' into emacs-lisp.
+  "Read the link at point into emacs-lisp.
 If the path of the link is a file path it is expanded using
 `expand-file-name'."
   (let* ((case-fold-search t)
@@ -1975,204 +2125,320 @@ If the path of the link is a file path it is expanded 
using
       ;; scalar result
       (funcall echo-res result))))
 
-(defun org-babel-insert-result
-  (result &optional result-params info hash indent lang)
+(defun org-babel-insert-result (result &optional result-params info hash lang)
   "Insert RESULT into the current buffer.
-By default RESULT is inserted after the end of the
-current source block.  With optional argument RESULT-PARAMS
-controls insertion of results in the org-mode file.
-RESULT-PARAMS can take the following values:
+
+By default RESULT is inserted after the end of the current source
+block.  The RESULT of an inline source block usually will be
+wrapped inside a `results' macro and placed on the same line as
+the inline source block.  The macro is stripped upon export.
+Multiline and non-scalar RESULTS from inline source blocks are
+not allowed.  With optional argument RESULT-PARAMS controls
+insertion of results in the Org mode file.  RESULT-PARAMS can
+take the following values:
 
 replace - (default option) insert results after the source block
-          replacing any previously inserted results
+          or inline source block replacing any previously
+          inserted results.
 
-silent -- no results are inserted into the Org-mode buffer but
+silent -- no results are inserted into the Org buffer but
           the results are echoed to the minibuffer and are
           ingested by Emacs (a potentially time consuming
-          process)
+          process).
 
 file ---- the results are interpreted as a file path, and are
-          inserted into the buffer using the Org-mode file syntax
+          inserted into the buffer using the Org file syntax.
 
-list ---- the results are interpreted as an Org-mode list.
+list ---- the results are interpreted as an Org list.
 
-raw ----- results are added directly to the Org-mode file.  This
-          is a good option if you code block will output org-mode
+raw ----- results are added directly to the Org file.  This is
+          a good option if you code block will output Org
           formatted text.
 
-drawer -- results are added directly to the Org-mode file as with
-          \"raw\", but are wrapped in a RESULTS drawer, allowing
-          them to later be replaced or removed automatically.
+drawer -- results are added directly to the Org file as with
+          \"raw\", but are wrapped in a RESULTS drawer or results
+          macro, allowing them to later be replaced or removed
+          automatically.
 
-org ----- results are added inside of a \"#+BEGIN_SRC org\" block.
-          They are not comma-escaped when inserted, but Org syntax
-          here will be discarded when exporting the file.
+org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC
+          org\" block depending on whether the current source block is
+          inline or not.  They are not comma-escaped when inserted,
+          but Org syntax here will be discarded when exporting the
+          file.
 
-html ---- results are added inside of a #+BEGIN_HTML block.  This
-          is a good option if you code block will output html
-          formatted text.
+html ---- results are added inside of a #+BEGIN_EXPORT HTML block
+          or html export snippet depending on whether the current
+          source block is inline or not.  This is a good option
+          if your code block will output html formatted text.
 
-latex --- results are added inside of a #+BEGIN_LATEX block.
-          This is a good option if you code block will output
-          latex formatted text.
+latex --- results are added inside of a #+BEGIN_EXPORT LATEX
+          block or latex export snippet depending on whether the
+          current source block is inline or not.  This is a good
+          option if your code block will output latex formatted
+          text.
 
 code ---- the results are extracted in the syntax of the source
           code of the language being evaluated and are added
-          inside of a #+BEGIN_SRC block with the source-code
-          language set appropriately.  Note this relies on the
-          optional LANG argument."
-  (if (stringp result)
-      (progn
-        (setq result (org-no-properties result))
-        (when (member "file" result-params)
-         (setq result (org-babel-result-to-file
-                       result (when (assoc :file-desc (nth 2 info))
-                                (or (cdr (assoc :file-desc (nth 2 info)))
-                                    result))))))
-    (unless (listp result) (setq result (format "%S" result))))
+          inside of a source block with the source-code language
+          set appropriately.  Also, source block inlining is
+          preserved in this case.  Note this relies on the
+          optional LANG argument.
+
+list ---- the results are rendered as a list.  This option not
+          allowed for inline src blocks.
+
+table --- the results are rendered as a table.  This option not
+          allowed for inline src blocks.
+
+INFO may provide the values of these header arguments (in the
+`header-arguments-alist' see the docstring for
+`org-babel-get-src-block-info'):
+
+:file --- the name of the file to which output should be written.
+
+:wrap --- the effect is similar to `latex' in RESULT-PARAMS but
+          using the argument supplied to specify the export block
+          or snippet type."
+  (cond ((stringp result)
+        (setq result (org-no-properties result))
+        (when (member "file" result-params)
+          (setq result (org-babel-result-to-file
+                        result (when (assq :file-desc (nth 2 info))
+                                 (or (cdr (assq :file-desc (nth 2 info)))
+                                     result))))))
+       ((listp result))
+       (t (setq result (format "%S" result))))
   (if (and result-params (member "silent" result-params))
-      (progn
-       (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
-       result)
-    (save-excursion
-      (let* ((inlinep
-             (save-excursion
-               (when (or (org-babel-get-inline-src-block-matches)
-                         (org-babel-get-lob-one-liner-matches))
-                 (goto-char (match-end 0))
-                 (insert (if (listp result) "\n" " "))
-                 (point))))
-            (existing-result (unless inlinep
-                               (org-babel-where-is-src-block-result
-                                t info hash indent)))
-            (results-switches
-             (cdr (assoc :results_switches (nth 2 info))))
-            (visible-beg (point-min-marker))
-            (visible-end (point-max-marker))
-            ;; When results exist outside of the current visible
-            ;; region of the buffer, be sure to widen buffer to
-            ;; update them.
-            (outside-scope-p (and existing-result
+      (progn (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
+            result)
+    (let ((inline (let ((context (org-element-context)))
+                   (and (memq (org-element-type context)
+                              '(inline-babel-call inline-src-block))
+                        context))))
+      (when inline
+       (let ((warning
+              (or (and (member "table" result-params) "`:results table'")
+                  (and (listp result) "list result")
+                  (and (string-match-p "\n." result) "multiline result")
+                  (and (member "list" result-params) "`:results list'"))))
+         (when warning
+           (user-error "Inline error: %s cannot be used" warning))))
+      (save-excursion
+       (let* ((visible-beg (point-min-marker))
+              (visible-end (copy-marker (point-max) t))
+              (inline (let ((context (org-element-context)))
+                        (and (memq (org-element-type context)
+                                   '(inline-babel-call inline-src-block))
+                             context)))
+              (existing-result (org-babel-where-is-src-block-result t nil 
hash))
+              (results-switches (cdr (assq :results_switches (nth 2 info))))
+              ;; When results exist outside of the current visible
+              ;; region of the buffer, be sure to widen buffer to
+              ;; update them.
+              (outside-scope (and existing-result
+                                  (buffer-narrowed-p)
                                   (or (> visible-beg existing-result)
                                       (<= visible-end existing-result))))
-            beg end)
-       (when (and (stringp result)  ; ensure results end in a newline
-                  (not inlinep)
-                  (> (length result) 0)
-                  (not (or (string-equal (substring result -1) "\n")
-                           (string-equal (substring result -1) "\r"))))
-         (setq result (concat result "\n")))
-       (unwind-protect
-           (progn
-             (when outside-scope-p (widen))
-             (if (not existing-result)
-                 (setq beg (or inlinep (point)))
-               (goto-char existing-result)
-               (save-excursion
-                 (re-search-forward "#" nil t)
-                 (setq indent (- (current-column) 1)))
-               (forward-line 1)
+              beg end indent)
+         ;; Ensure non-inline results end in a newline.
+         (when (and (org-string-nw-p result)
+                    (not inline)
+                    (not (string-equal (substring result -1) "\n")))
+           (setq result (concat result "\n")))
+         (unwind-protect
+             (progn
+               (when outside-scope (widen))
+               (if existing-result (goto-char existing-result)
+                 (goto-char (org-element-property :end inline))
+                 (skip-chars-backward " \t"))
+               (unless inline
+                 (setq indent (org-get-indentation))
+                 (forward-line 1))
                (setq beg (point))
                (cond
+                (inline
+                  ;; Make sure new results are separated from the
+                  ;; source code by one space.
+                  (unless existing-result
+                    (insert " ")
+                    (setq beg (point))))
                 ((member "replace" result-params)
                  (delete-region (point) (org-babel-result-end)))
                 ((member "append" result-params)
                  (goto-char (org-babel-result-end)) (setq beg (point-marker)))
-                ((member "prepend" result-params)))) ; already there
-             (setq results-switches
-                   (if results-switches (concat " " results-switches) ""))
-             (let ((wrap (lambda (start finish &optional no-escape)
-                           (goto-char end) (insert (concat finish "\n"))
-                           (goto-char beg) (insert (concat start "\n"))
-                           (unless no-escape
-                             (org-escape-code-in-region (min (point) end) end))
-                           (goto-char end) (goto-char (point-at-eol))
-                           (setq end (point-marker))))
-                   (proper-list-p (lambda (it) (and (listp it) (null (cdr 
(last it)))))))
-               ;; insert results based on type
-               (cond
-                ;; do nothing for an empty result
-                ((null result))
-                ;; insert a list if preferred
-                ((member "list" result-params)
-                 (insert
-                  (org-babel-trim
-                   (org-list-to-generic
-                    (cons 'unordered
-                          (mapcar
-                           (lambda (el) (list nil (if (stringp el) el (format 
"%S" el))))
-                           (if (listp result) result (split-string result "\n" 
t))))
-                    '(:splicep nil :istart "- " :iend "\n")))
-                  "\n"))
-                ;; assume the result is a table if it's not a string
-                ((funcall proper-list-p result)
-                 (goto-char beg)
-                 (insert (concat (orgtbl-to-orgtbl
-                                  (if (org-every
-                                       (lambda (el) (or (listp el) (eq el 
'hline)))
-                                       result)
-                                      result (list result))
-                                  '(:fmt (lambda (cell) (format "%s" cell)))) 
"\n"))
-                 (goto-char beg) (when (org-at-table-p) (org-table-align)))
-                ((and (listp result) (not (funcall proper-list-p result)))
-                 (insert (format "%s\n" result)))
-                ((member "file" result-params)
-                 (when inlinep (goto-char inlinep))
-                 (insert result))
-                (t (goto-char beg) (insert result)))
-               (when (funcall proper-list-p result) (goto-char 
(org-table-end)))
-               (setq end (point-marker))
-               ;; possibly wrap result
-               (cond
-                ((assoc :wrap (nth 2 info))
-                 (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS")))
-                   (funcall wrap (concat "#+BEGIN_" name)
-                            (concat "#+END_" (car (org-split-string name))))))
-                ((member "html" result-params)
-                 (funcall wrap "#+BEGIN_HTML" "#+END_HTML"))
-                ((member "latex" result-params)
-                 (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX"))
-                ((member "org" result-params)
-                 (goto-char beg) (if (org-at-table-p) (org-cycle))
-                 (funcall wrap "#+BEGIN_SRC org" "#+END_SRC"))
-                ((member "code" result-params)
-                 (funcall wrap (format "#+BEGIN_SRC %s%s" (or lang "none") 
results-switches)
-                          "#+END_SRC"))
-                ((member "raw" result-params)
-                 (goto-char beg) (if (org-at-table-p) (org-cycle)))
-                ((or (member "drawer" result-params)
-                     ;; Stay backward compatible with <7.9.2
-                     (member "wrap" result-params))
-                 (goto-char beg) (if (org-at-table-p) (org-cycle))
-                 (funcall wrap ":RESULTS:" ":END:" 'no-escape))
-                ((and (not (funcall proper-list-p result))
-                      (not (member "file" result-params)))
-                 (org-babel-examplize-region beg end results-switches)
-                 (setq end (point)))))
-             ;; possibly indent the results to match the #+results line
-             (when (and (not inlinep) (numberp indent) indent (> indent 0)
-                        ;; in this case `table-align' does the work for us
-                        (not (and (listp result)
-                                  (member "append" result-params))))
-               (indent-rigidly beg end indent))
-             (if (null result)
-                 (if (member "value" result-params)
-                     (message "Code block returned no value.")
-                   (message "Code block produced no output."))
-               (message "Code block evaluation complete.")))
-         (when outside-scope-p (narrow-to-region visible-beg visible-end))
-         (set-marker visible-beg nil)
-         (set-marker visible-end nil))))))
-
-(defun org-babel-remove-result (&optional info)
+                ((member "prepend" result-params))) ; already there
+               (setq results-switches
+                     (if results-switches (concat " " results-switches) ""))
+               (let ((wrap (lambda (start finish &optional no-escape 
no-newlines
+                                     inline-start inline-finish)
+                             (when inline
+                               (setq start inline-start)
+                               (setq finish inline-finish)
+                               (setq no-newlines t))
+                             (goto-char end)
+                             (insert (concat finish (unless no-newlines "\n")))
+                             (goto-char beg)
+                             (insert (concat start (unless no-newlines "\n")))
+                             (unless no-escape
+                               (org-escape-code-in-region (min (point) end) 
end))
+                             (goto-char end)
+                             (unless no-newlines (goto-char (point-at-eol)))
+                             (setq end (point-marker))))
+                     (tabulablep
+                      (lambda (r)
+                        ;; Non-nil when result R can be turned into
+                        ;; a table.
+                        (and (listp r)
+                             (null (cdr (last r)))
+                             (cl-every
+                              (lambda (e) (or (atom e) (null (cdr (last e)))))
+                              result)))))
+                 ;; insert results based on type
+                 (cond
+                  ;; Do nothing for an empty result.
+                  ((null result))
+                  ;; Insert a list if preferred.
+                  ((member "list" result-params)
+                   (insert
+                    (org-trim
+                     (org-list-to-generic
+                      (cons 'unordered
+                            (mapcar
+                             (lambda (e)
+                               (list (if (stringp e) e (format "%S" e))))
+                             (if (listp result) result
+                               (split-string result "\n" t))))
+                      '(:splicep nil :istart "- " :iend "\n")))
+                    "\n"))
+                  ;; Try hard to print RESULT as a table.  Give up if
+                  ;; it contains an improper list.
+                  ((funcall tabulablep result)
+                   (goto-char beg)
+                   (insert (concat (orgtbl-to-orgtbl
+                                    (if (cl-every
+                                         (lambda (e)
+                                           (or (eq e 'hline) (listp e)))
+                                         result)
+                                        result
+                                      (list result))
+                                    nil)
+                                   "\n"))
+                   (goto-char beg)
+                   (when (org-at-table-p) (org-table-align))
+                   (goto-char (org-table-end)))
+                  ;; Print verbatim a list that cannot be turned into
+                  ;; a table.
+                  ((listp result) (insert (format "%s\n" result)))
+                  ((member "file" result-params)
+                   (when inline
+                     (setq result (org-macro-escape-arguments result)))
+                   (insert result))
+                  ((and inline (not (member "raw" result-params)))
+                   (insert (org-macro-escape-arguments
+                            (org-babel-chomp result "\n"))))
+                  (t (goto-char beg) (insert result)))
+                 (setq end (point-marker))
+                 ;; possibly wrap result
+                 (cond
+                  ((assq :wrap (nth 2 info))
+                   (let ((name (or (cdr (assq :wrap (nth 2 info))) "RESULTS")))
+                     (funcall wrap (concat "#+BEGIN_" name)
+                              (concat "#+END_" (car (org-split-string name)))
+                              nil nil (concat "{{{results(@@" name ":") 
"@@)}}}")))
+                  ((member "html" result-params)
+                   (funcall wrap "#+BEGIN_EXPORT html" "#+END_EXPORT" nil nil
+                            "{{{results(@@html:" "@@)}}}"))
+                  ((member "latex" result-params)
+                   (funcall wrap "#+BEGIN_EXPORT latex" "#+END_EXPORT" nil nil
+                            "{{{results(@@latex:" "@@)}}}"))
+                  ((member "org" result-params)
+                   (goto-char beg) (when (org-at-table-p) (org-cycle))
+                   (funcall wrap "#+BEGIN_SRC org" "#+END_SRC" nil nil
+                            "{{{results(src_org{" "})}}}"))
+                  ((member "code" result-params)
+                   (let ((lang (or lang "none")))
+                     (funcall wrap (format "#+BEGIN_SRC %s%s" lang 
results-switches)
+                              "#+END_SRC" nil nil
+                              (format "{{{results(src_%s[%s]{" lang 
results-switches)
+                              "})}}}")))
+                  ((member "raw" result-params)
+                   (goto-char beg) (when (org-at-table-p) (org-cycle)))
+                  ((or (member "drawer" result-params)
+                       ;; Stay backward compatible with <7.9.2
+                       (member "wrap" result-params))
+                   (goto-char beg) (when (org-at-table-p) (org-cycle))
+                   (funcall wrap ":RESULTS:" ":END:" 'no-escape nil
+                            "{{{results(" ")}}}"))
+                  ((and inline (member "file" result-params))
+                   (funcall wrap nil nil nil nil "{{{results(" ")}}}"))
+                  ((and (not (funcall tabulablep result))
+                        (not (member "file" result-params)))
+                   (let ((org-babel-inline-result-wrap
+                          ;; Hard code {{{results(...)}}} on top of 
customization.
+                          (format "{{{results(%s)}}}"
+                                  org-babel-inline-result-wrap)))
+                     (org-babel-examplify-region beg end results-switches 
inline)
+                     (setq end (point))))))
+               ;; Possibly indent results in par with #+results line.
+               (when (and (not inline) (numberp indent) (> indent 0)
+                          ;; In this case `table-align' does the work
+                          ;; for us.
+                          (not (and (listp result)
+                                    (member "append" result-params))))
+                 (indent-rigidly beg end indent))
+               (if (null result)
+                   (if (member "value" result-params)
+                       (message "Code block returned no value.")
+                     (message "Code block produced no output."))
+                 (message "Code block evaluation complete.")))
+           (when outside-scope (narrow-to-region visible-beg visible-end))
+           (set-marker visible-beg nil)
+           (set-marker visible-end nil)))))))
+
+(defun org-babel-remove-result (&optional info keep-keyword)
   "Remove the result of the current source block."
   (interactive)
-  (let ((location (org-babel-where-is-src-block-result nil info)) start)
+  (let ((location (org-babel-where-is-src-block-result nil info)))
     (when location
-      (setq start (- location 1))
       (save-excursion
-        (goto-char location) (forward-line 1)
-        (delete-region start (org-babel-result-end))))))
+        (goto-char location)
+       (when (looking-at (concat org-babel-result-regexp ".*$"))
+         (delete-region
+          (if keep-keyword (1+ (match-end 0)) (1- (match-beginning 0)))
+          (progn (forward-line 1) (org-babel-result-end))))))))
+
+(defun org-babel-remove-inline-result (&optional datum)
+  "Remove the result of the current inline-src-block or babel call.
+The result must be wrapped in a `results' macro to be removed.
+Leading white space is trimmed."
+  (interactive)
+  (let* ((el (or datum (org-element-context))))
+    (when (memq (org-element-type el) '(inline-src-block inline-babel-call))
+      (org-with-wide-buffer
+       (goto-char (org-element-property :end el))
+       (skip-chars-backward " \t")
+       (let ((result (save-excursion
+                      (skip-chars-forward
+                       " \t\n"
+                       (org-element-property
+                        :contents-end (org-element-property :parent el)))
+                      (org-element-context))))
+        (when (and (eq (org-element-type result) 'macro)
+                   (string= (org-element-property :key result) "results"))
+          (delete-region               ; And leading whitespace.
+           (point)
+           (progn (goto-char (org-element-property :end result))
+                  (skip-chars-backward " \t\n")
+                  (point)))))))))
+
+(defun org-babel-remove-result-one-or-many (x)
+  "Remove the result of the current source block.
+If called with a prefix argument, remove all result blocks
+in the buffer."
+  (interactive "P")
+  (if x
+      (org-babel-map-src-blocks nil (org-babel-remove-result))
+    (org-babel-remove-result)))
 
 (defun org-babel-result-end ()
   "Return the point at the end of the current set of results."
@@ -2210,29 +2476,26 @@ file's directory then expand relative links."
              result)
            (if description (concat "[" description "]") ""))))
 
-(defvar org-babel-capitalize-examplize-region-markers nil
+(defvar org-babel-capitalize-example-region-markers nil
   "Make true to capitalize begin/end example markers inserted by code blocks.")
 
-(defun org-babel-examplize-region (beg end &optional results-switches)
+(defun org-babel-examplify-region (beg end &optional results-switches inline)
   "Comment out region using the inline `==' or `: ' org example quote."
   (interactive "*r")
-  (let ((chars-between (lambda (b e)
-                        (not (string-match "^[\\s]*$" (buffer-substring b 
e)))))
-       (maybe-cap (lambda (str) (if 
org-babel-capitalize-examplize-region-markers
-                                    (upcase str) str))))
-    (if (or (funcall chars-between (save-excursion (goto-char beg) 
(point-at-bol)) beg)
-           (funcall chars-between end (save-excursion (goto-char end) 
(point-at-eol))))
+  (let ((maybe-cap
+        (lambda (str)
+          (if org-babel-capitalize-example-region-markers (upcase str) str))))
+    (if inline
        (save-excursion
          (goto-char beg)
          (insert (format org-babel-inline-result-wrap
-                         (prog1 (buffer-substring beg end)
-                           (delete-region beg end)))))
+                         (delete-and-extract-region beg end))))
       (let ((size (count-lines beg end)))
        (save-excursion
          (cond ((= size 0))          ; do nothing for an empty result
                ((< size org-babel-min-lines-for-block-output)
                 (goto-char beg)
-                (dotimes (n size)
+                (dotimes (_ size)
                   (beginning-of-line 1) (insert ": ") (forward-line 1)))
                (t
                 (goto-char beg)
@@ -2241,16 +2504,37 @@ file's directory then expand relative links."
                                     (funcall maybe-cap "#+begin_example")
                                     results-switches)
                           (funcall maybe-cap "#+begin_example\n")))
-                (if (markerp end) (goto-char end) (forward-char (- end beg)))
+                (let ((p (point)))
+                  (if (markerp end) (goto-char end) (forward-char (- end beg)))
+                  (org-escape-code-in-region p (point)))
                 (insert (funcall maybe-cap "#+end_example\n")))))))))
 
 (defun org-babel-update-block-body (new-body)
   "Update the body of the current code block to NEW-BODY."
-  (if (not (org-babel-where-is-src-block-head))
-      (error "Not in a source block")
-    (save-match-data
-      (replace-match (concat (org-babel-trim new-body) "\n") nil t nil 5))
-    (indent-rigidly (match-beginning 5) (match-end 5) 2)))
+  (let ((element (org-element-at-point)))
+    (unless (eq (org-element-type element) 'src-block)
+      (error "Not in a source block"))
+    (goto-char (org-babel-where-is-src-block-head element))
+    (let* ((ind (org-get-indentation))
+          (body-start (line-beginning-position 2))
+          (body (org-element-normalize-string
+                 (if (or org-src-preserve-indentation
+                         (org-element-property :preserve-indent element))
+                     new-body
+                   (with-temp-buffer
+                     (insert (org-remove-indentation new-body))
+                     (indent-rigidly
+                      (point-min)
+                      (point-max)
+                      (+ ind org-edit-src-content-indentation))
+                     (buffer-string))))))
+      (delete-region body-start
+                    (org-with-wide-buffer
+                     (goto-char (org-element-property :end element))
+                     (skip-chars-backward " \t\n")
+                     (line-beginning-position)))
+      (goto-char body-start)
+      (insert body))))
 
 (defun org-babel-merge-params (&rest plists)
   "Combine all parameter association lists in PLISTS.
@@ -2259,133 +2543,103 @@ This takes into account some special considerations 
for certain
 parameters when merging lists."
   (let* ((results-exclusive-groups
          (mapcar (lambda (group) (mapcar #'symbol-name group))
-                 (cdr (assoc 'results org-babel-common-header-args-w-values))))
+                 (cdr (assq 'results org-babel-common-header-args-w-values))))
         (exports-exclusive-groups
          (mapcar (lambda (group) (mapcar #'symbol-name group))
-                 (cdr (assoc 'exports org-babel-common-header-args-w-values))))
-        (variable-index 0)
-        (e-merge (lambda (exclusive-groups &rest result-params)
-                   ;; maintain exclusivity of mutually exclusive parameters
-                   (let (output)
-                     (mapc (lambda (new-params)
-                             (mapc (lambda (new-param)
-                                     (mapc (lambda (exclusive-group)
-                                             (when (member new-param 
exclusive-group)
-                                               (mapcar (lambda (excluded-param)
-                                                         (setq output
-                                                               (delete
-                                                                excluded-param
-                                                                output)))
-                                                       exclusive-group)))
-                                           exclusive-groups)
-                                     (setq output (org-uniquify
-                                                   (cons new-param output))))
-                                   new-params))
-                           result-params)
-                     output)))
-        params results exports tangle noweb cache vars shebang comments padline
-        clearnames)
-
-    (mapc
-     (lambda (plist)
-       (mapc
-       (lambda (pair)
-         (case (car pair)
-           (:var
-            (let ((name (if (listp (cdr pair))
-                            (cadr pair)
-                          (and (string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*="
-                                             (cdr pair))
-                               (intern (match-string 1 (cdr pair)))))))
-              (if name
-                  (setq vars
-                        (append
-                         (if (member name (mapcar #'car vars))
-                             (progn
-                               (push name clearnames)
-                               (delq nil
-                                     (mapcar
-                                      (lambda (p)
-                                        (unless (equal (car p) name) p))
-                                      vars)))
-                           vars)
-                         (list (cons name pair))))
-                ;; if no name is given and we already have named variables
-                ;; then assign to named variables in order
-                (if (and vars (nth variable-index vars))
-                    (let ((name (car (nth variable-index vars))))
-                      (push name clearnames) ; clear out colnames
-                                             ; and rownames
-                                             ; for replace vars
-                      (prog1 (setf (cddr (nth variable-index vars))
-                                   (concat (symbol-name name) "=" (cdr pair)))
-                        (incf variable-index)))
-                  (error "Variable \"%s\" must be assigned a default value"
-                         (cdr pair))))))
-           (:results
-            (setq results (funcall e-merge results-exclusive-groups
-                                   results
-                                   (split-string
-                                    (let ((r (cdr pair)))
-                                      (if (stringp r) r (eval r)))))))
-           (:file
-            (when (cdr pair)
-              (setq results (funcall e-merge results-exclusive-groups
-                                     results '("file")))
-              (unless (or (member "both" exports)
-                          (member "none" exports)
-                          (member "code" exports))
-                (setq exports (funcall e-merge exports-exclusive-groups
-                                       exports '("results"))))
-              (setq params (cons pair (assq-delete-all (car pair) params)))))
-           (:exports
-            (setq exports (funcall e-merge exports-exclusive-groups
-                                   exports (split-string (cdr pair)))))
-           (:tangle ;; take the latest -- always overwrite
-            (setq tangle (or (list (cdr pair)) tangle)))
-           (:noweb
-            (setq noweb (funcall e-merge
-                                 '(("yes" "no" "tangle" "no-export"
-                                    "strip-export" "eval"))
-                                 noweb
-                                 (split-string (or (cdr pair) "")))))
-           (:cache
-            (setq cache (funcall e-merge '(("yes" "no")) cache
-                                 (split-string (or (cdr pair) "")))))
-           (:padline
-            (setq padline (funcall e-merge '(("yes" "no")) padline
-                                   (split-string (or (cdr pair) "")))))
-           (:shebang ;; take the latest -- always overwrite
-            (setq shebang (or (list (cdr pair)) shebang)))
-           (:comments
-            (setq comments (funcall e-merge '(("yes" "no")) comments
-                                    (split-string (or (cdr pair) "")))))
-           (t ;; replace: this covers e.g. :session
-            (setq params (cons pair (assq-delete-all (car pair) params))))))
-       plist))
-     plists)
-    (setq vars (reverse vars))
-    (while vars (setq params (cons (cons :var (cddr (pop vars))) params)))
-    ;; clear out col-names and row-names for replaced variables
-    (mapc
-     (lambda (name)
-       (mapc
-       (lambda (param)
-         (when (assoc param params)
-           (setf (cdr (assoc param params))
-                 (org-remove-if (lambda (pair) (equal (car pair) name))
-                                (cdr (assoc param params))))
-           (setf params (org-remove-if (lambda (pair) (and (equal (car pair) 
param)
-                                                      (null (cdr pair))))
-                                       params))))
-       (list :colname-names :rowname-names)))
-     clearnames)
-    (mapc
-     (lambda (hd)
-       (let ((key (intern (concat ":" (symbol-name hd))))
-            (val (eval hd)))
-        (setf params (cons (cons key (mapconcat 'identity val " ")) params))))
-     '(results exports tangle noweb padline cache shebang comments))
+                 (cdr (assq 'exports org-babel-common-header-args-w-values))))
+        (merge
+         (lambda (exclusive-groups &rest result-params)
+           ;; Maintain exclusivity of mutually exclusive parameters,
+           ;; as defined in EXCLUSIVE-GROUPS while merging lists in
+           ;; RESULT-PARAMS.
+           (let (output)
+             (dolist (new-params result-params (delete-dups output))
+               (dolist (new-param new-params)
+                 (dolist (exclusive-group exclusive-groups)
+                   (when (member new-param exclusive-group)
+                     (setq output (cl-remove-if
+                                   (lambda (o) (member o exclusive-group))
+                                   output))))
+                 (push new-param output))))))
+        (variable-index 0)             ;Handle positional arguments.
+        clearnames
+        params                         ;Final parameters list.
+        ;; Some keywords accept multiple values.  We need to treat
+        ;; them specially.
+        vars results exports)
+    (dolist (plist plists)
+      (dolist (pair plist)
+       (pcase pair
+         (`(:var . ,value)
+          (let ((name (cond
+                       ((listp value) (car value))
+                       ((string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*=" value)
+                        (intern (match-string 1 value)))
+                       (t nil))))
+            (cond
+             (name
+              (setq vars
+                    (append (if (not (assoc name vars)) vars
+                              (push name clearnames)
+                              (cl-remove-if (lambda (p) (equal name (car p)))
+                                            vars))
+                            (list (cons name pair)))))
+             ((and vars (nth variable-index vars))
+              ;; If no name is given and we already have named
+              ;; variables then assign to named variables in order.
+              (let ((name (car (nth variable-index vars))))
+                ;; Clear out colnames and rownames for replace vars.
+                (push name clearnames)
+                (setf (cddr (nth variable-index vars))
+                      (concat (symbol-name name) "=" value))
+                (cl-incf variable-index)))
+             (t (error "Variable \"%s\" must be assigned a default value"
+                       (cdr pair))))))
+         (`(:results . ,value)
+          (setq results (funcall merge
+                                 results-exclusive-groups
+                                 results
+                                 (split-string
+                                  (if (stringp value) value (eval value t))))))
+         (`(,(or :file :file-ext) . ,value)
+          ;; `:file' and `:file-ext' are regular keywords but they
+          ;; imply a "file" `:results' and a "results" `:exports'.
+          (when value
+            (setq results
+                  (funcall merge results-exclusive-groups results '("file")))
+            (unless (or (member "both" exports)
+                        (member "none" exports)
+                        (member "code" exports))
+              (setq exports
+                    (funcall merge
+                             exports-exclusive-groups exports '("results"))))
+            (push pair params)))
+         (`(:exports . ,value)
+          (setq exports (funcall merge
+                                 exports-exclusive-groups
+                                 exports
+                                 (split-string (or value "")))))
+         ;; Regular keywords: any value overwrites the previous one.
+         (_ (setq params (cons pair (assq-delete-all (car pair) params)))))))
+    ;; Handle `:var' and clear out colnames and rownames for replaced
+    ;; variables.
+    (setq params (nconc (mapcar (lambda (v) (cons :var (cddr v))) vars)
+                       params))
+    (dolist (name clearnames)
+      (dolist (param '(:colname-names :rowname-names))
+       (when (assq param params)
+         (setf (cdr (assq param params))
+               (cl-remove-if (lambda (pair) (equal name (car pair)))
+                             (cdr (assq param params))))
+         (setq params
+               (cl-remove-if (lambda (pair) (and (equal (car pair) param)
+                                            (null (cdr pair))))
+                             params)))))
+    ;; Handle other special keywords, which accept multiple values.
+    (setq params (nconc (list (cons :results (mapconcat #'identity results " 
"))
+                             (cons :exports (mapconcat #'identity exports " 
")))
+                       params))
+    ;; Return merged params.
     params))
 
 (defvar org-babel-use-quick-and-dirty-noweb-expansion nil
@@ -2397,17 +2651,12 @@ header argument from buffer or subtree wide 
properties.")
 (defun org-babel-noweb-p (params context)
   "Check if PARAMS require expansion in CONTEXT.
 CONTEXT may be one of :tangle, :export or :eval."
-  (let* (intersect
-        (intersect (lambda (as bs)
-                     (when as
-                       (if (member (car as) bs)
-                           (car as)
-                         (funcall intersect (cdr as) bs))))))
-    (funcall intersect (case context
-                        (:tangle '("yes" "tangle" "no-export" "strip-export"))
-                        (:eval   '("yes" "no-export" "strip-export" "eval"))
-                        (:export '("yes")))
-            (split-string (or (cdr (assoc :noweb params)) "")))))
+  (let ((allowed-values (cl-case context
+                         (:tangle '("yes" "tangle" "no-export" "strip-export"))
+                         (:eval   '("yes" "no-export" "strip-export" "eval"))
+                         (:export '("yes")))))
+    (cl-some (lambda (v) (member v allowed-values))
+            (split-string (or (cdr (assq :noweb params)) "")))))
 
 (defun org-babel-expand-noweb-references (&optional info parent-buffer)
   "Expand Noweb references in the body of the current source code block.
@@ -2445,7 +2694,7 @@ block but are passed literally to the \"example-block\"."
          (body (nth 1 info))
         (ob-nww-start org-babel-noweb-wrap-start)
         (ob-nww-end org-babel-noweb-wrap-end)
-        (comment (string= "noweb" (cdr (assoc :comments (nth 2 info)))))
+        (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
         (rx-prefix (concat "\\(" org-babel-src-name-regexp "\\|"
                            ":noweb-ref[ \t]+" "\\)"))
          (new-body "")
@@ -2454,11 +2703,11 @@ block but are passed literally to the 
\"example-block\"."
                   (with-temp-buffer
                     (funcall (intern (concat lang "-mode")))
                     (comment-region (point) (progn (insert text) (point)))
-                    (org-babel-trim (buffer-string)))))
+                    (org-trim (buffer-string)))))
         index source-name evaluate prefix)
     (with-temp-buffer
-      (org-set-local 'org-babel-noweb-wrap-start ob-nww-start)
-      (org-set-local 'org-babel-noweb-wrap-end ob-nww-end)
+      (setq-local org-babel-noweb-wrap-start ob-nww-start)
+      (setq-local org-babel-noweb-wrap-end ob-nww-end)
       (insert body) (goto-char (point-min))
       (setq index (point))
       (while (and (re-search-forward (org-babel-noweb-wrap) nil t))
@@ -2502,7 +2751,7 @@ block but are passed literally to the \"example-block\"."
                           (while (re-search-forward rx nil t)
                             (let* ((i (org-babel-get-src-block-info 'light))
                                    (body (org-babel-expand-noweb-references i))
-                                   (sep (or (cdr (assoc :noweb-sep (nth 2 i)))
+                                   (sep (or (cdr (assq :noweb-sep (nth 2 i)))
                                             "\n"))
                                    (full (if comment
                                              (let ((cs 
(org-babel-tangle-comment-links i)))
@@ -2513,11 +2762,11 @@ block but are passed literally to the 
\"example-block\"."
                               (setq expansion (cons sep (cons full 
expansion)))))
                         (org-babel-map-src-blocks nil
                          (let ((i (org-babel-get-src-block-info 'light)))
-                            (when (equal (or (cdr (assoc :noweb-ref (nth 2 i)))
+                            (when (equal (or (cdr (assq :noweb-ref (nth 2 i)))
                                              (nth 4 i))
                                          source-name)
                               (let* ((body (org-babel-expand-noweb-references 
i))
-                                     (sep (or (cdr (assoc :noweb-sep (nth 2 
i)))
+                                     (sep (or (cdr (assq :noweb-sep (nth 2 i)))
                                               "\n"))
                                      (full (if comment
                                                (let ((cs 
(org-babel-tangle-comment-links i)))
@@ -2530,7 +2779,8 @@ block but are passed literally to the \"example-block\"."
                     (and expansion
                          (mapconcat #'identity (nreverse (cdr expansion)) "")))
                   ;; Possibly raise an error if named block doesn't exist.
-                  (if (member lang org-babel-noweb-error-langs)
+                  (if (or org-babel-noweb-error-all-langs
+                         (member lang org-babel-noweb-error-langs))
                       (error "%s" (concat
                                    (org-babel-noweb-wrap source-name)
                                    "could not be resolved (see "
@@ -2540,79 +2790,120 @@ block but are passed literally to the 
\"example-block\"."
       (funcall nb-add (buffer-substring index (point-max))))
     new-body))
 
+(defun org-babel--script-escape-inner (str)
+  (let (in-single in-double backslash out)
+    (mapc
+     (lambda (ch)
+       (setq
+       out
+       (if backslash
+           (progn
+             (setq backslash nil)
+             (cond
+              ((and in-single (eq ch ?'))
+               ;; Escaped single quote inside single quoted string:
+               ;; emit just a single quote, since we've changed the
+               ;; outer quotes to double.
+               (cons ch out))
+              ((eq ch ?\")
+               ;; Escaped double quote
+               (if in-single
+                   ;; This should be interpreted as backslash+quote,
+                   ;; not an escape.  Emit a three backslashes
+                   ;; followed by a quote (because one layer of
+                   ;; quoting will be stripped by `org-babel-read').
+                   (append (list ch ?\\ ?\\ ?\\) out)
+                 ;; Otherwise we are in a double-quoted string.  Emit
+                 ;; a single escaped quote
+                 (append (list ch ?\\) out)))
+              ((eq ch ?\\)
+               ;; Escaped backslash: emit a single escaped backslash
+               (append (list ?\\ ?\\) out))
+              ;; Other: emit a quoted backslash followed by whatever
+              ;; the character was (because one layer of quoting will
+              ;; be stripped by `org-babel-read').
+              (t (append (list ch ?\\ ?\\) out))))
+         (cl-case ch
+           (?\[ (if (or in-double in-single)
+                    (cons ?\[ out)
+                  (cons ?\( out)))
+           (?\] (if (or in-double in-single)
+                    (cons ?\] out)
+                  (cons ?\) out)))
+           (?\{ (if (or in-double in-single)
+                    (cons ?\{ out)
+                  (cons ?\( out)))
+           (?\} (if (or in-double in-single)
+                    (cons ?\} out)
+                  (cons ?\) out)))
+           (?, (if (or in-double in-single)
+                   (cons ?, out) (cons ?\s out)))
+           (?\' (if in-double
+                    (cons ?\' out)
+                  (setq in-single (not in-single)) (cons ?\" out)))
+           (?\" (if in-single
+                    (append (list ?\" ?\\) out)
+                  (setq in-double (not in-double)) (cons ?\" out)))
+           (?\\ (unless (or in-single in-double)
+                  (error "Can't handle backslash outside string in 
`org-babel-script-escape'"))
+                (setq backslash t)
+                out)
+           (t  (cons ch out))))))
+     (string-to-list str))
+    (when (or in-single in-double)
+      (error "Unterminated string in `org-babel-script-escape'"))
+    (apply #'string (reverse out))))
+
 (defun org-babel-script-escape (str &optional force)
   "Safely convert tables into elisp lists."
+  (unless (stringp str)
+    (error "`org-babel-script-escape' expects a string"))
   (let ((escaped
-          (if (or force
-                  (and (stringp str)
-                       (> (length str) 2)
-                       (or (and (string-equal "[" (substring str 0 1))
-                                (string-equal "]" (substring str -1)))
-                           (and (string-equal "{" (substring str 0 1))
-                                (string-equal "}" (substring str -1)))
-                           (and (string-equal "(" (substring str 0 1))
-                                (string-equal ")" (substring str -1))))))
-              (org-babel-read
-               (concat
-                "'"
-                (let (in-single in-double out)
-                  (mapc
-                   (lambda (ch)
-                     (setq
-                      out
-                      (case ch
-                        (91 (if (or in-double in-single) ; [
-                                (cons 91 out)
-                              (cons 40 out)))
-                        (93 (if (or in-double in-single) ; ]
-                                (cons 93 out)
-                              (cons 41 out)))
-                        (123 (if (or in-double in-single) ; {
-                                 (cons 123 out)
-                               (cons 40 out)))
-                        (125 (if (or in-double in-single) ; }
-                                 (cons 125 out)
-                               (cons 41 out)))
-                        (44 (if (or in-double in-single) ; ,
-                                (cons 44 out) (cons 32 out)))
-                        (39 (if in-double ; '
-                                (cons 39 out)
-                              (setq in-single (not in-single)) (cons 34 out)))
-                        (34 (if in-single ; "
-                                (append (list 34 32) out)
-                              (setq in-double (not in-double)) (cons 34 out)))
-                        (t  (cons ch out)))))
-                   (string-to-list str))
-                  (apply #'string (reverse out)))))
-            str)))
+        (cond
+         ((and (> (length str) 2)
+               (or (and (string-equal "[" (substring str 0 1))
+                        (string-equal "]" (substring str -1)))
+                   (and (string-equal "{" (substring str 0 1))
+                        (string-equal "}" (substring str -1)))
+                   (and (string-equal "(" (substring str 0 1))
+                        (string-equal ")" (substring str -1)))))
+
+          (concat "'" (org-babel--script-escape-inner str)))
+         ((or force
+              (and (> (length str) 2)
+                   (or (and (string-equal "'" (substring str 0 1))
+                            (string-equal "'" (substring str -1)))
+                       ;; We need to pass double-quoted strings
+                       ;; through the backslash-twiddling bits, even
+                       ;; though we don't need to change their
+                       ;; delimiters.
+                       (and (string-equal "\"" (substring str 0 1))
+                            (string-equal "\"" (substring str -1))))))
+          (org-babel--script-escape-inner str))
+         (t str))))
     (condition-case nil (org-babel-read escaped) (error escaped))))
 
 (defun org-babel-read (cell &optional inhibit-lisp-eval)
   "Convert the string value of CELL to a number if appropriate.
-Otherwise if cell looks like lisp (meaning it starts with a
-\"(\", \"\\='\", \"\\=`\" or a \"[\") then read it as lisp,
-otherwise return it unmodified as a string.  Optional argument
-NO-LISP-EVAL inhibits lisp evaluation for situations in which is
-it not appropriate."
-  (if (and (stringp cell) (not (equal cell "")))
-      (or (org-babel-number-p cell)
-          (if (and (not inhibit-lisp-eval)
-                  (or (member (substring cell 0 1) '("(" "'" "`" "["))
-                      (string= cell "*this*")))
-              (eval (read cell))
-            (if (string= (substring cell 0 1) "\"")
-               (read cell)
-             (progn (set-text-properties 0 (length cell) nil cell) cell))))
-    cell))
-
-(defun org-babel-number-p (string)
-  "If STRING represents a number return its value."
-  (if (and (string-match "[0-9]+" string)
-          (string-match "^-?[0-9]*\\.?[0-9]*$" string)
-           (= (length (substring string (match-beginning 0)
-                                (match-end 0)))
-             (length string)))
-      (string-to-number string)))
+Otherwise if CELL looks like lisp (meaning it starts with a
+\"(\", \"\\='\", \"\\=`\" or a \"[\") then read and evaluate it as
+lisp, otherwise return it unmodified as a string.  Optional
+argument INHIBIT-LISP-EVAL inhibits lisp evaluation for
+situations in which is it not appropriate."
+  (cond ((not (org-string-nw-p cell)) cell)
+       ((org-babel--string-to-number cell))
+       ((and (not inhibit-lisp-eval)
+             (or (memq (string-to-char cell) '(?\( ?' ?` ?\[))
+                 (string= cell "*this*")))
+        (eval (read cell) t))
+       ((eq (string-to-char cell) ?\") (read cell))
+       (t (org-no-properties cell))))
+
+(defun org-babel--string-to-number (string)
+  "If STRING represents a number return its value.
+Otherwise return nil."
+  (and (string-match-p "\\`-?[0-9]*\\.?[0-9]*\\'" string)
+       (string-to-number string)))
 
 (defun org-babel-import-elisp-from-file (file-name &optional separator)
   "Read the results located at FILE-NAME into an elisp table.
@@ -2644,49 +2935,15 @@ If the table is trivial, then return it as a scalar."
                       cell) t))
 
 (defun org-babel-chomp (string &optional regexp)
-  "Strip trailing spaces and carriage returns from STRING.
-Default regexp used is \"[ \f\t\n\r\v]\" but can be
-overwritten by specifying a regexp as a second argument."
+  "Strip a trailing space or carriage return from STRING.
+The default regexp used is \"[ \\f\\t\\n\\r\\v]\" but another one
+can be specified as the REGEXP argument."
   (let ((regexp (or regexp "[ \f\t\n\r\v]")))
     (while (and (> (length string) 0)
                 (string-match regexp (substring string -1)))
       (setq string (substring string 0 -1)))
     string))
 
-(defun org-babel-trim (string &optional regexp)
-  "Strip leading and trailing spaces and carriage returns from STRING.
-Like `org-babel-chomp' only it runs on both the front and back
-of the string."
-  (org-babel-chomp (org-reverse-string
-                    (org-babel-chomp (org-reverse-string string) regexp))
-                   regexp))
-
-(defun org-babel-tramp-handle-call-process-region
-  (start end program &optional delete buffer display &rest args)
-  "Use Tramp to handle `call-process-region'.
-Fixes a bug in `tramp-handle-call-process-region'."
-  (if (file-remote-p default-directory)
-      (let ((tmpfile (tramp-compat-make-temp-file "")))
-       (write-region start end tmpfile)
-       (when delete (delete-region start end))
-       (unwind-protect
-           ;;  (apply 'call-process program tmpfile buffer display args)
-            ;; bug in tramp
-           (apply 'process-file program tmpfile buffer display args)
-         (delete-file tmpfile)))
-    ;; org-babel-call-process-region-original is the original emacs
-    ;; definition.  It is in scope from the let binding in
-    ;; org-babel-execute-src-block
-    (apply org-babel-call-process-region-original
-           start end program delete buffer display args)))
-
-(defalias 'org-babel-local-file-name
-  (if (fboundp 'file-local-name)
-      'file-local-name
-    (lambda (file)
-      "Return the local name component of FILE."
-      (or (file-remote-p file 'localname) file))))
-
 (defun org-babel-process-file-name (name &optional no-quote-p)
   "Prepare NAME to be used in an external process.
 If NAME specifies a remote location, the remote portion of the
@@ -2694,7 +2951,7 @@ name is removed, since in that case the process will be 
executing
 remotely.  The file name is then processed by `expand-file-name'.
 Unless second argument NO-QUOTE-P is non-nil, the file name is
 additionally processed by `shell-quote-argument'"
-  (let ((f (expand-file-name (org-babel-local-file-name name))))
+  (let ((f (org-babel-local-file-name (expand-file-name name))))
     (if no-quote-p f (shell-quote-argument f))))
 
 (defvar org-babel-temporary-directory)
@@ -2708,6 +2965,11 @@ additionally processed by `shell-quote-argument'"
 Used by `org-babel-temp-file'.  This directory will be removed on
 Emacs shutdown."))
 
+(defcustom org-babel-remote-temporary-directory "/tmp/"
+  "Directory to hold temporary files on remote hosts."
+  :group 'org-babel
+  :type 'string)
+
 (defmacro org-babel-result-cond (result-params scalar-form &rest table-forms)
   "Call the code to parse raw string results according to RESULT-PARAMS."
   (declare (indent 1)
@@ -2720,6 +2982,7 @@ Emacs shutdown."))
                 (member "html" ,params)
                 (member "code" ,params)
                 (member "pp" ,params)
+                (member "file" ,params)
                 (and (or (member "output" ,params)
                          (member "raw"    ,params)
                          (member "org"    ,params)
@@ -2737,7 +3000,8 @@ of `org-babel-temporary-directory'."
   (if (file-remote-p default-directory)
       (let ((prefix
              (concat (file-remote-p default-directory)
-                     (expand-file-name prefix temporary-file-directory))))
+                     (expand-file-name
+                     prefix org-babel-remote-temporary-directory))))
         (make-temp-file prefix nil suffix))
     (let ((temporary-file-directory
           (or (and (boundp 'org-babel-temporary-directory)
@@ -2772,6 +3036,96 @@ of `org-babel-temporary-directory'."
 
 (add-hook 'kill-emacs-hook 'org-babel-remove-temporary-directory)
 
+(defun org-babel-one-header-arg-safe-p (pair safe-list)
+  "Determine if the PAIR is a safe babel header arg according to SAFE-LIST.
+
+For the format of SAFE-LIST, see `org-babel-safe-header-args'."
+  (and (consp pair)
+       (keywordp (car pair))
+       (stringp (cdr pair))
+       (or
+       (memq (car pair) safe-list)
+       (let ((entry (assq (car pair) safe-list)))
+         (and entry
+              (consp entry)
+              (cond ((functionp (cdr entry))
+                      (funcall (cdr entry) (cdr pair)))
+                    ((listp (cdr entry))
+                     (member (cdr pair) (cdr entry)))
+                    (t nil)))))))
+
+(defun org-babel-generate-file-param (src-name params)
+  "Calculate the filename for source block results.
+
+The directory is calculated from the :output-dir property of the
+source block; if not specified, use the current directory.
+
+If the source block has a #+NAME and the :file parameter does not
+contain any period characters, then the :file parameter is
+treated as an extension, and the output file name is the
+concatenation of the directory (as calculated above), the block
+name, a period, and the parameter value as a file extension.
+Otherwise, the :file parameter is treated as a full file name,
+and the output file name is the directory (as calculated above)
+plus the parameter value."
+  (let* ((file-cons (assq :file params))
+          (file-ext-cons (assq :file-ext params))
+          (file-ext (cdr-safe file-ext-cons))
+          (dir (cdr-safe (assq :output-dir params)))
+          fname)
+    ;; create the output-dir if it does not exist
+    (when dir
+      (make-directory dir t))
+    (if file-cons
+       ;; :file given; add :output-dir if given
+       (when dir
+         (setcdr file-cons (concat (file-name-as-directory dir) (cdr 
file-cons))))
+      ;; :file not given; compute from name and :file-ext if possible
+      (when (and src-name file-ext)
+       (if dir
+           (setq fname (concat (file-name-as-directory (or dir ""))
+                               src-name "." file-ext))
+         (setq fname (concat src-name "." file-ext)))
+       (setq params (cons (cons :file fname) params))))
+    params))
+
+(defun org-babel-graphical-output-file (params)
+  "File where a babel block should send graphical output, per PARAMS.
+Return nil if no graphical output is expected.  Raise an error if
+the output file is ill-defined."
+  (let ((file (cdr (assq :file params))))
+    (cond (file (and (member "graphics" (cdr (assq :result-params params)))
+                    file))
+         ((assq :file-ext params)
+          (user-error ":file-ext given but no :file generated; did you forget \
+to name a block?"))
+         (t (user-error "No :file header argument given; cannot create \
+graphical result")))))
+
+(defun org-babel-make-language-alias (new old)
+  "Make source blocks of type NEW aliases for those of type OLD.
+
+NEW and OLD should be strings.  This function should be called
+after the babel API for OLD-type source blocks is fully defined.
+
+Callers of this function will probably want to add an entry to
+`org-src-lang-modes' as well."
+  (dolist (fn '("execute" "expand-body" "prep-session"
+               "variable-assignments" "load-session"))
+    (let ((sym (intern-soft (concat "org-babel-" fn ":" old))))
+      (when (and sym (fboundp sym))
+       (defalias (intern (concat "org-babel-" fn ":" new)) sym))))
+  ;; Technically we don't need a `dolist' for just one variable, but
+  ;; we keep it for symmetry/ease of future expansion.
+  (dolist (var '("default-header-args"))
+    (let ((sym (intern-soft (concat "org-babel-" var ":" old))))
+      (when (and sym (boundp sym))
+       (defvaralias (intern (concat "org-babel-" var ":" new)) sym)))))
+
+(defun org-babel-strip-quotes (string)
+  "Strip \\\"s from around a string, if applicable."
+  (org-unbracket-string "\"" "\"" string))
+
 (provide 'ob-core)
 
 ;; Local variables:
diff --git a/lisp/org/ob-css.el b/lisp/org/ob-css.el
index 70c66d4..4203b12 100644
--- a/lisp/org/ob-css.el
+++ b/lisp/org/ob-css.el
@@ -1,4 +1,4 @@
-;;; ob-css.el --- org-babel functions for css evaluation
+;;; ob-css.el --- Babel Functions for CSS            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -24,19 +24,19 @@
 ;;; Commentary:
 
 ;; Since CSS can't be executed, this file exists solely for tangling
-;; CSS from org-mode files.
+;; CSS from Org files.
 
 ;;; Code:
 (require 'ob)
 
 (defvar org-babel-default-header-args:css '())
 
-(defun org-babel-execute:css (body params)
+(defun org-babel-execute:css (body _params)
   "Execute a block of CSS code.
 This function is called by `org-babel-execute-src-block'."
   body)
 
-(defun org-babel-prep-session:css (session params)
+(defun org-babel-prep-session:css (_session _params)
   "Return an error if the :session header argument is set.
 CSS does not support sessions."
   (error "CSS sessions are nonsensical"))
diff --git a/lisp/org/ob-ditaa.el b/lisp/org/ob-ditaa.el
index 5eb8e2f..89b5d24 100644
--- a/lisp/org/ob-ditaa.el
+++ b/lisp/org/ob-ditaa.el
@@ -1,4 +1,4 @@
-;;; ob-ditaa.el --- org-babel functions for ditaa evaluation
+;;; ob-ditaa.el --- Babel Functions for ditaa        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -81,15 +81,21 @@ Do not leave leading or trailing spaces in this string."
 (defun org-babel-execute:ditaa (body params)
   "Execute a block of Ditaa code with org-babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
-        (out-file (let ((el (cdr (assoc :file params))))
-                     (or el
-                         (error
-                          "ditaa code block requires :file header argument"))))
-        (cmdline (cdr (assoc :cmdline params)))
-        (java (cdr (assoc :java params)))
+  (let* ((out-file (or (cdr (assq :file params))
+                      (error
+                       "ditaa code block requires :file header argument")))
+        (cmdline (cdr (assq :cmdline params)))
+        (java (cdr (assq :java params)))
         (in-file (org-babel-temp-file "ditaa-"))
-        (eps (cdr (assoc :eps params)))
+        (eps (cdr (assq :eps params)))
+        (eps-file (when eps
+                    (org-babel-process-file-name (concat in-file ".eps"))))
+        (pdf-cmd (when (and (or (string= (file-name-extension out-file) "pdf")
+                                (cdr (assq :pdf params))))
+                   (concat
+                    "epstopdf"
+                    " " eps-file
+                    " -o=" (org-babel-process-file-name out-file))))
         (cmd (concat org-babel-ditaa-java-cmd
                      " " java " " org-ditaa-jar-option " "
                      (shell-quote-argument
@@ -97,13 +103,9 @@ This function is called by `org-babel-execute-src-block'."
                        (if eps org-ditaa-eps-jar-path org-ditaa-jar-path)))
                      " " cmdline
                      " " (org-babel-process-file-name in-file)
-                     " " (org-babel-process-file-name out-file)))
-        (pdf-cmd (when (and (or (string= (file-name-extension out-file) "pdf")
-                                (cdr (assoc :pdf params))))
-                   (concat
-                    "epstopdf"
-                    " " (org-babel-process-file-name (concat in-file ".eps"))
-                    " -o=" (org-babel-process-file-name out-file)))))
+                     " " (if pdf-cmd
+                             eps-file
+                           (org-babel-process-file-name out-file)))))
     (unless (file-exists-p org-ditaa-jar-path)
       (error "Could not find ditaa.jar at %s" org-ditaa-jar-path))
     (with-temp-file in-file (insert body))
@@ -111,7 +113,7 @@ This function is called by `org-babel-execute-src-block'."
     (when pdf-cmd (message pdf-cmd) (shell-command pdf-cmd))
     nil)) ;; signal that output has already been written to file
 
-(defun org-babel-prep-session:ditaa (session params)
+(defun org-babel-prep-session:ditaa (_session _params)
   "Return an error because ditaa does not support sessions."
   (error "Ditaa does not support sessions"))
 
diff --git a/lisp/org/ob-dot.el b/lisp/org/ob-dot.el
index aa0445b..81442bf 100644
--- a/lisp/org/ob-dot.el
+++ b/lisp/org/ob-dot.el
@@ -1,4 +1,4 @@
-;;; ob-dot.el --- org-babel functions for dot evaluation
+;;; ob-dot.el --- Babel Functions for dot            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -46,7 +46,7 @@
 
 (defun org-babel-expand-body:dot (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (mapc
      (lambda (pair)
        (let ((name (symbol-name (car pair)))
@@ -55,19 +55,20 @@
               (replace-regexp-in-string
                (concat "$" (regexp-quote name))
                (if (stringp value) value (format "%S" value))
-               body))))
+               body
+               t
+               t))))
      vars)
     body))
 
 (defun org-babel-execute:dot (body params)
   "Execute a block of Dot code with org-babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (cdr (assoc :result-params params)))
-        (out-file (cdr (or (assoc :file params)
+  (let* ((out-file (cdr (or (assq :file params)
                            (error "You need to specify a :file parameter"))))
-        (cmdline (or (cdr (assoc :cmdline params))
+        (cmdline (or (cdr (assq :cmdline params))
                      (format "-T%s" (file-name-extension out-file))))
-        (cmd (or (cdr (assoc :cmd params)) "dot"))
+        (cmd (or (cdr (assq :cmd params)) "dot"))
         (in-file (org-babel-temp-file "dot-")))
     (with-temp-file in-file
       (insert (org-babel-expand-body:dot body params)))
@@ -78,7 +79,7 @@ This function is called by `org-babel-execute-src-block'."
             " -o " (org-babel-process-file-name out-file)) "")
     nil)) ;; signal that output has already been written to file
 
-(defun org-babel-prep-session:dot (session params)
+(defun org-babel-prep-session:dot (_session _params)
   "Return an error because Dot does not support sessions."
   (error "Dot does not support sessions"))
 
diff --git a/lisp/org/ob-ebnf.el b/lisp/org/ob-ebnf.el
new file mode 100644
index 0000000..410570b
--- /dev/null
+++ b/lisp/org/ob-ebnf.el
@@ -0,0 +1,83 @@
+;;; ob-ebnf.el --- Babel Functions for EBNF          -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+;; Author: Michael Gauland
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 1.00
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; Org-Babel support for using ebnf2ps to generate encapsulated postscript
+;;; railroad diagrams. It recogises these arguments:
+;;;
+;;;     :file is required; it must include the extension '.eps.' All the rules
+;;;           in the block will be drawn in the same file. This is done by
+;;;           inserting a '[<file>' comment at the start of the block (see the
+;;;           documentation for ebnf-eps-buffer for more information).
+;;;
+;;;     :style specifies a value in ebnf-style-database. This provides the
+;;;            ability to customise the output. The style can also specify the
+;;;            grammar syntax (by setting ebnf-syntax); note that only ebnf,
+;;;            iso-ebnf, and yacc are supported by this file.
+
+;;; Requirements:
+
+;;; Code:
+(require 'ob)
+(require 'ebnf2ps)
+
+;; optionally declare default header arguments for this language
+(defvar org-babel-default-header-args:ebnf '((:style . nil)))
+
+;; Use ebnf-eps-buffer to produce an encapsulated postscript file.
+;;
+(defun org-babel-execute:ebnf (body params)
+  "Execute a block of Ebnf code with org-babel.  This function is
+called by `org-babel-execute-src-block'"
+  (save-excursion
+    (let* ((dest-file (cdr (assq :file params)))
+          (dest-dir (file-name-directory dest-file))
+          (dest-root (file-name-sans-extension
+                      (file-name-nondirectory dest-file)))
+          (style (cdr (assq :style params)))
+          (result nil))
+      (with-temp-buffer
+       (when style (ebnf-push-style style))
+       (let ((comment-format
+              (cond ((string= ebnf-syntax 'yacc) "/*%s*/")
+                    ((string= ebnf-syntax 'ebnf) ";%s")
+                    ((string= ebnf-syntax 'iso-ebnf) "(*%s*)")
+                    (t (setq result
+                             (format "EBNF error: format %s not supported."
+                                     ebnf-syntax))))))
+         (setq ebnf-eps-prefix dest-dir)
+         (insert (format comment-format (format "[%s" dest-root)))
+         (newline)
+         (insert body)
+         (newline)
+         (insert (format comment-format (format "]%s" dest-root)))
+         (ebnf-eps-buffer)
+         (when style (ebnf-pop-style))))
+      result)))
+
+(provide 'ob-ebnf)
+;;; ob-ebnf.el ends here
diff --git a/lisp/org/ob-emacs-lisp.el b/lisp/org/ob-emacs-lisp.el
index d95c475..c0bd12a 100644
--- a/lisp/org/ob-emacs-lisp.el
+++ b/lisp/org/ob-emacs-lisp.el
@@ -1,4 +1,4 @@
-;;; ob-emacs-lisp.el --- org-babel functions for emacs-lisp code evaluation
+;;; ob-emacs-lisp.el --- Babel Functions for Emacs-lisp Code -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -28,17 +28,21 @@
 ;;; Code:
 (require 'ob)
 
-(defvar org-babel-default-header-args:emacs-lisp
-  '((:hlines . "yes") (:colnames . "no"))
-  "Default arguments for evaluating an emacs-lisp source block.")
+(defconst org-babel-header-args:emacs-lisp '((lexical . :any))
+  "Emacs-lisp specific header arguments.")
 
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
+(defvar org-babel-default-header-args:emacs-lisp '((:lexical . "no"))
+  "Default arguments for evaluating an emacs-lisp source block.
+
+A value of \"yes\" or t causes src blocks to be eval'd using
+lexical scoping.  It can also be an alist mapping symbols to
+their value.  It is used as the optional LEXICAL argument to
+`eval', which see.")
 
 (defun org-babel-expand-body:emacs-lisp (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-         (result-params (cdr (assoc :result-params params)))
+  (let* ((vars (org-babel--get-vars params))
+         (result-params (cdr (assq :result-params params)))
          (print-level nil) (print-length nil)
          (body (if (> (length vars) 0)
                   (concat "(let ("
@@ -55,26 +59,33 @@
 (defun org-babel-execute:emacs-lisp (body params)
   "Execute a block of emacs-lisp code with Babel."
   (save-window-excursion
-    (let ((result
-           (eval (read (format (if (member "output"
-                                           (cdr (assoc :result-params params)))
-                                   "(with-output-to-string %s)"
-                                 "(progn %s)")
-                               (org-babel-expand-body:emacs-lisp
-                                body params))))))
-      (org-babel-result-cond (cdr (assoc :result-params params))
+    (let* ((lexical (cdr (assq :lexical params)))
+          (result
+           (eval (read (format (if (member "output"
+                                           (cdr (assq :result-params params)))
+                                   "(with-output-to-string %s)"
+                                 "(progn %s)")
+                               (org-babel-expand-body:emacs-lisp
+                                body params)))
+
+                 (if (listp lexical)
+                     lexical
+                   (member lexical '("yes" "t"))))))
+      (org-babel-result-cond (cdr (assq :result-params params))
        (let ((print-level nil)
               (print-length nil))
-          (if (or (member "scalar" (cdr (assoc :result-params params)))
-                  (member "verbatim" (cdr (assoc :result-params params))))
+          (if (or (member "scalar" (cdr (assq :result-params params)))
+                  (member "verbatim" (cdr (assq :result-params params))))
               (format "%S" result)
             (format "%s" result)))
        (org-babel-reassemble-table
         result
-         (org-babel-pick-name (cdr (assoc :colname-names params))
-                              (cdr (assoc :colnames params)))
-         (org-babel-pick-name (cdr (assoc :rowname-names params))
-                              (cdr (assoc :rownames params))))))))
+         (org-babel-pick-name (cdr (assq :colname-names params))
+                              (cdr (assq :colnames params)))
+         (org-babel-pick-name (cdr (assq :rowname-names params))
+                              (cdr (assq :rownames params))))))))
+
+(org-babel-make-language-alias "elisp" "emacs-lisp")
 
 (provide 'ob-emacs-lisp)
 
diff --git a/lisp/org/ob-eval.el b/lisp/org/ob-eval.el
index 46d21c8..324cf5f 100644
--- a/lisp/org/ob-eval.el
+++ b/lisp/org/ob-eval.el
@@ -1,4 +1,4 @@
-;;; ob-eval.el --- org-babel functions for external code evaluation
+;;; ob-eval.el --- Babel Functions for External Code Evaluation -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -28,7 +28,6 @@
 
 ;;; Code:
 (require 'org-macs)
-(eval-when-compile (require 'cl))
 
 (defvar org-babel-error-buffer-name "*Org-Babel Error Output*")
 (declare-function org-babel-temp-file "ob-core" (prefix &optional suffix))
@@ -57,6 +56,13 @@ STDERR with `org-babel-eval-error-notify'."
          (progn
            (with-current-buffer err-buff
              (org-babel-eval-error-notify exit-code (buffer-string)))
+           (save-excursion
+             (when (get-buffer org-babel-error-buffer-name)
+               (with-current-buffer org-babel-error-buffer-name
+                 (unless (derived-mode-p 'compilation-mode)
+                   (compilation-mode))
+                 ;; Compilation-mode enforces read-only, but Babel expects the 
buffer modifiable.
+                 (setq buffer-read-only nil))))
            nil)
        (buffer-string)))))
 
@@ -114,18 +120,18 @@ function in various versions of Emacs.
       (delete-file input-file))
 
     (when (and error-file (file-exists-p error-file))
-      (if (< 0 (nth 7 (file-attributes error-file)))
-         (with-current-buffer (get-buffer-create error-buffer)
-           (let ((pos-from-end (- (point-max) (point))))
-             (or (bobp)
-                 (insert "\f\n"))
-             ;; Do no formatting while reading error file,
-             ;; because that can run a shell command, and we
-             ;; don't want that to cause an infinite recursion.
-             (format-insert-file error-file nil)
-             ;; Put point after the inserted errors.
-             (goto-char (- (point-max) pos-from-end)))
-           (current-buffer)))
+      (when (< 0 (nth 7 (file-attributes error-file)))
+       (with-current-buffer (get-buffer-create error-buffer)
+         (let ((pos-from-end (- (point-max) (point))))
+           (or (bobp)
+               (insert "\f\n"))
+           ;; Do no formatting while reading error file,
+           ;; because that can run a shell command, and we
+           ;; don't want that to cause an infinite recursion.
+           (format-insert-file error-file nil)
+           ;; Put point after the inserted errors.
+           (goto-char (- (point-max) pos-from-end)))
+         (current-buffer)))
       (delete-file error-file))
     exit-status))
 
diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el
index 2677fe5..2556362 100644
--- a/lisp/org/ob-exp.el
+++ b/lisp/org/ob-exp.el
@@ -1,4 +1,4 @@
-;;; ob-exp.el --- Exportation of org-babel source blocks
+;;; ob-exp.el --- Exportation of Babel Source Blocks -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -24,81 +24,49 @@
 
 ;;; Code:
 (require 'ob-core)
-(require 'org-src)
-(eval-when-compile
-  (require 'cl))
-
-(defvar org-current-export-file)
-(defvar org-babel-lob-one-liner-regexp)
-(defvar org-babel-ref-split-regexp)
-(defvar org-list-forbidden-blocks)
-
-(declare-function org-babel-lob-get-info "ob-lob" ())
-(declare-function org-babel-eval-wipe-error-buffer "ob-eval" ())
-(declare-function org-between-regexps-p "org"
-                 (start-re end-re &optional lim-up lim-down))
-(declare-function org-get-indentation "org" (&optional line))
-(declare-function org-heading-components "org" ())
-(declare-function org-in-block-p "org" (names))
-(declare-function org-in-verbatim-emphasis "org" ())
-(declare-function org-link-search "org" (s &optional type avoid-pos stealth))
-(declare-function org-fill-template "org" (template alist))
-(declare-function org-split-string "org" (string &optional separators))
-(declare-function org-element-at-point "org-element" (&optional keep-trail))
+
+(declare-function org-babel-lob-get-info "ob-lob" (&optional datum))
+(declare-function org-element-at-point "org-element" ())
 (declare-function org-element-context "org-element" (&optional element))
 (declare-function org-element-property "org-element" (property element))
 (declare-function org-element-type "org-element" (element))
 (declare-function org-escape-code-in-string "org-src" (s))
+(declare-function org-export-copy-buffer "ox" ())
+(declare-function org-fill-template "org" (template alist))
+(declare-function org-get-indentation "org" (&optional line))
+(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
+
+(defvar org-src-preserve-indentation)
 
 (defcustom org-export-babel-evaluate t
   "Switch controlling code evaluation during export.
 When set to nil no code will be evaluated as part of the export
-process.  When set to `inline-only', only inline code blocks will
-be executed."
+process and no header argumentss will be obeyed.  When set to
+`inline-only', only inline code blocks will be executed.  Users
+who wish to avoid evaluating code on export should use the header
+argument `:eval never-export'."
   :group 'org-babel
   :version "24.1"
   :type '(choice (const :tag "Never" nil)
                 (const :tag "Only inline code" inline-only)
                 (const :tag "Always" t)))
-(put 'org-export-babel-evaluate 'safe-local-variable (lambda (x) (eq x nil)))
-
-(defun org-babel-exp-get-export-buffer ()
-  "Return the current export buffer if possible."
-  (cond
-   ((bufferp org-current-export-file) org-current-export-file)
-   (org-current-export-file (get-file-buffer org-current-export-file))
-   ('otherwise
-    (error "Requested export buffer when `org-current-export-file' is nil"))))
-
-(defvar org-link-search-inhibit-query)
-
-(defmacro org-babel-exp-in-export-file (lang &rest body)
-  (declare (indent 1))
-  `(let* ((lang-headers (intern (concat "org-babel-default-header-args:" 
,lang)))
-         (heading (nth 4 (ignore-errors (org-heading-components))))
-         (export-buffer (current-buffer))
-         (original-buffer (org-babel-exp-get-export-buffer)) results)
-     (when original-buffer
-       ;; resolve parameters in the original file so that
-       ;; headline and file-wide parameters are included, attempt
-       ;; to go to the same heading in the original file
-       (set-buffer original-buffer)
-       (save-restriction
-        (when heading
-          (condition-case nil
-              (let ((org-link-search-inhibit-query t))
-                (org-link-search heading))
-            (error (when heading
-                     (goto-char (point-min))
-                     (re-search-forward (regexp-quote heading) nil t)))))
-        (setq results ,@body))
-       (set-buffer export-buffer)
-       results)))
-(def-edebug-spec org-babel-exp-in-export-file (form body))
-
-(defun org-babel-exp-src-block (&rest headers)
+(put 'org-export-babel-evaluate 'safe-local-variable #'null)
+
+(defmacro org-babel-exp--at-source (&rest body)
+  "Evaluate BODY at the source of the Babel block at point.
+Source is located in `org-babel-exp-reference-buffer'.  The value
+returned is the value of the last form in BODY.  Assume that
+point is at the beginning of the Babel block."
+  (declare (indent 1) (debug body))
+  `(let ((source (get-text-property (point) 'org-reference)))
+     (with-current-buffer org-babel-exp-reference-buffer
+       (org-with-wide-buffer
+       (goto-char source)
+       ,@body))))
+
+(defun org-babel-exp-src-block ()
   "Process source block for export.
-Depending on the `export' headers argument, replace the source
+Depending on the \":export\" header argument, replace the source
 code block like this:
 
 both ---- display the code and the results
@@ -107,29 +75,36 @@ code ---- the default, display the code inside the block 
but do
           not process
 
 results - just like none only the block is run on export ensuring
-          that it's results are present in the org-mode buffer
+          that its results are present in the Org mode buffer
 
 none ---- do not display either code or results upon export
 
-Assume point is at the beginning of block's starting line."
+Assume point is at block opening line."
   (interactive)
-  (unless noninteractive (message "org-babel-exp processing..."))
   (save-excursion
     (let* ((info (org-babel-get-src-block-info 'light))
           (lang (nth 0 info))
-          (raw-params (nth 2 info)) hash)
+          (raw-params (nth 2 info))
+          hash)
       ;; bail if we couldn't get any info from the block
+      (unless noninteractive
+       (message "org-babel-exp process %s at position %d..."
+                lang
+                (line-beginning-position)))
       (when info
        ;; if we're actually going to need the parameters
-       (when (member (cdr (assoc :exports (nth 2 info))) '("both" "results"))
-         (org-babel-exp-in-export-file lang
-           (setf (nth 2 info)
-                 (org-babel-process-params
-                  (apply #'org-babel-merge-params
-                         org-babel-default-header-args
-                         (if (boundp lang-headers) (eval lang-headers) nil)
-                         (append (org-babel-params-from-properties lang)
-                                 (list raw-params))))))
+       (when (member (cdr (assq :exports (nth 2 info))) '("both" "results"))
+         (let ((lang-headers (intern (concat "org-babel-default-header-args:"
+                                             lang))))
+           (org-babel-exp--at-source
+               (setf (nth 2 info)
+                     (org-babel-process-params
+                      (apply #'org-babel-merge-params
+                             org-babel-default-header-args
+                             (and (boundp lang-headers)
+                                  (symbol-value lang-headers))
+                             (append (org-babel-params-from-properties lang)
+                                     (list raw-params)))))))
          (setf hash (org-babel-sha1-hash info)))
        (org-babel-exp-do-export info 'block hash)))))
 
@@ -150,166 +125,180 @@ this template."
   :group 'org-babel
   :type 'string)
 
-(defvar org-babel-default-lob-header-args)
 (defun org-babel-exp-process-buffer ()
   "Execute all Babel blocks in current buffer."
   (interactive)
-  (save-window-excursion
-    (save-excursion
+  (when org-export-babel-evaluate
+    (save-window-excursion
       (let ((case-fold-search t)
-           (regexp (concat org-babel-inline-src-block-regexp "\\|"
-                           org-babel-lob-one-liner-regexp "\\|"
-                           "^[ \t]*#\\+BEGIN_SRC")))
-       (goto-char (point-min))
-       (while (re-search-forward regexp nil t)
-         (let* ((element (save-excursion
-                           ;; If match is inline, point is at its
-                           ;; end.  Move backward so
-                           ;; `org-element-context' can get the
-                           ;; object, not the following one.
-                           (backward-char)
-                           (save-match-data (org-element-context))))
-                (type (org-element-type element))
-                (begin (copy-marker (org-element-property :begin element)))
-                (end (copy-marker
-                      (save-excursion
-                        (goto-char (org-element-property :end element))
-                        (skip-chars-backward " \r\t\n")
-                        (point)))))
-           (case type
-             (inline-src-block
-              (let* ((info (org-babel-parse-inline-src-block-match))
-                     (params (nth 2 info)))
-                (setf (nth 1 info)
-                      (if (and (cdr (assoc :noweb params))
-                               (string= "yes" (cdr (assoc :noweb params))))
-                          (org-babel-expand-noweb-references
-                           info (org-babel-exp-get-export-buffer))
-                        (nth 1 info)))
-                (goto-char begin)
-                (let ((replacement (org-babel-exp-do-export info 'inline)))
-                  (if (equal replacement "")
-                      ;; Replacement code is empty: remove inline src
-                      ;; block, including extra white space that
-                      ;; might have been created when inserting
-                      ;; results.
-                      (delete-region begin
-                                     (progn (goto-char end)
-                                            (skip-chars-forward " \t")
-                                            (point)))
-                    ;; Otherwise: remove inline src block but
-                    ;; preserve following white spaces.  Then insert
-                    ;; value.
-                    (delete-region begin end)
-                    (insert replacement)))))
-             ((babel-call inline-babel-call)
-              (let* ((lob-info (org-babel-lob-get-info))
-                     (results
-                      (org-babel-exp-do-export
-                       (list "emacs-lisp" "results"
-                             (apply #'org-babel-merge-params
-                                    org-babel-default-header-args
-                                    org-babel-default-lob-header-args
-                                    (append
-                                     (org-babel-params-from-properties)
-                                     (list
-                                      (org-babel-parse-header-arguments
-                                       (org-no-properties
-                                        (concat
-                                         ":var results="
-                                         (mapconcat 'identity
-                                                    (butlast lob-info 2)
-                                                    " ")))))))
-                             "" (nth 3 lob-info) (nth 2 lob-info))
-                       'lob))
-                     (rep (org-fill-template
-                           org-babel-exp-call-line-template
-                           `(("line"  . ,(nth 0 lob-info))))))
-                ;; If replacement is empty, completely remove the
-                ;; object/element, including any extra white space
-                ;; that might have been created when including
-                ;; results.
-                (if (equal rep "")
-                    (delete-region
-                     begin
-                     (progn (goto-char end)
-                            (if (not (eq type 'babel-call))
-                                (progn (skip-chars-forward " \t") (point))
-                              (skip-chars-forward " \r\t\n")
-                              (line-beginning-position))))
-                  ;; Otherwise, preserve following white
-                  ;; spaces/newlines and then, insert replacement
-                  ;; string.
-                  (goto-char begin)
-                  (delete-region begin end)
-                  (insert rep))))
-             (src-block
-              (let* ((match-start (copy-marker (match-beginning 0)))
-                     (ind (org-get-indentation))
-                     (headers
-                      (cons
-                       (org-element-property :language element)
-                       (let ((params (org-element-property :parameters
-                                                           element)))
-                         (and params (org-split-string params "[ \t]+"))))))
-                ;; Take care of matched block: compute replacement
-                ;; string.  In particular, a nil REPLACEMENT means
-                ;; the block should be left as-is while an empty
-                ;; string should remove the block.
-                (let ((replacement (progn (goto-char match-start)
-                                          (org-babel-exp-src-block headers))))
-                  (cond ((not replacement) (goto-char end))
-                        ((equal replacement "")
-                         (goto-char end)
-                         (skip-chars-forward " \r\t\n")
-                         (beginning-of-line)
-                         (delete-region begin (point)))
-                        (t
-                         (goto-char match-start)
-                         (delete-region (point)
-                                        (save-excursion (goto-char end)
-                                                        (line-end-position)))
-                         (insert replacement)
-                         (if (or org-src-preserve-indentation
-                                 (org-element-property :preserve-indent
-                                                       element))
-                             ;; Indent only the code block markers.
-                             (save-excursion (skip-chars-backward " \r\t\n")
-                                             (indent-line-to ind)
-                                             (goto-char match-start)
-                                             (indent-line-to ind))
-                           ;; Indent everything.
-                           (indent-rigidly match-start (point) ind)))))
-                (set-marker match-start nil))))
-           (set-marker begin nil)
-           (set-marker end nil)))))))
-
-(defun org-babel-in-example-or-verbatim ()
-  "Return true if point is in example or verbatim code.
-Example and verbatim code include escaped portions of
-an org-mode buffer code that should be treated as normal
-org-mode text."
-  (or (save-match-data
-       (save-excursion
-         (goto-char (point-at-bol))
-         (looking-at "[ \t]*:[ \t]")))
-      (org-in-verbatim-emphasis)
-      (org-in-block-p org-list-forbidden-blocks)
-      (org-between-regexps-p "^[ \t]*#\\+begin_src" "^[ \t]*#\\+end_src")))
+           (regexp (if (eq org-export-babel-evaluate 'inline-only)
+                       "\\(call\\|src\\)_"
+                     "\\(call\\|src\\)_\\|^[ \t]*#\\+\\(BEGIN_SRC\\|CALL:\\)"))
+           ;; Get a pristine copy of current buffer so Babel
+           ;; references are properly resolved and source block
+           ;; context is preserved.
+           (org-babel-exp-reference-buffer (org-export-copy-buffer)))
+       (unwind-protect
+           (save-excursion
+             ;; First attach to every source block their original
+             ;; position, so that they can be retrieved within
+             ;; `org-babel-exp-reference-buffer', even after heavy
+             ;; modifications on current buffer.
+             ;;
+             ;; False positives are harmless, so we don't check if
+             ;; we're really at some Babel object.  Moreover,
+             ;; `line-end-position' ensures that we propertize
+             ;; a noticeable part of the object, without affecting
+             ;; multiple objects on the same line.
+             (goto-char (point-min))
+             (while (re-search-forward regexp nil t)
+               (let ((s (match-beginning 0)))
+                 (put-text-property s (line-end-position) 'org-reference s)))
+             ;; Evaluate from top to bottom every Babel block
+             ;; encountered.
+             (goto-char (point-min))
+             (while (re-search-forward regexp nil t)
+               (unless (save-match-data (org-in-commented-heading-p))
+                 (let* ((object? (match-end 1))
+                        (element (save-match-data
+                                   (if object? (org-element-context)
+                                     ;; No deep inspection if we're
+                                     ;; just looking for an element.
+                                     (org-element-at-point))))
+                        (type
+                         (pcase (org-element-type element)
+                           ;; Discard block elements if we're looking
+                           ;; for inline objects.  False results
+                           ;; happen when, e.g., "call_" syntax is
+                           ;; located within affiliated keywords:
+                           ;;
+                           ;; #+name: call_src
+                           ;; #+begin_src ...
+                           ((and (or `babel-call `src-block) (guard object?))
+                            nil)
+                           (type type)))
+                        (begin
+                         (copy-marker (org-element-property :begin element)))
+                        (end
+                         (copy-marker
+                          (save-excursion
+                            (goto-char (org-element-property :end element))
+                            (skip-chars-backward " \r\t\n")
+                            (point)))))
+                   (pcase type
+                     (`inline-src-block
+                      (let* ((info
+                              (org-babel-get-src-block-info nil element))
+                             (params (nth 2 info)))
+                        (setf (nth 1 info)
+                              (if (and (cdr (assq :noweb params))
+                                       (string= "yes"
+                                                (cdr (assq :noweb params))))
+                                  (org-babel-expand-noweb-references
+                                   info org-babel-exp-reference-buffer)
+                                (nth 1 info)))
+                        (goto-char begin)
+                        (let ((replacement
+                               (org-babel-exp-do-export info 'inline)))
+                          (if (equal replacement "")
+                              ;; Replacement code is empty: remove
+                              ;; inline source block, including extra
+                              ;; white space that might have been
+                              ;; created when inserting results.
+                              (delete-region begin
+                                             (progn (goto-char end)
+                                                    (skip-chars-forward " \t")
+                                                    (point)))
+                            ;; Otherwise: remove inline src block but
+                            ;; preserve following white spaces.  Then
+                            ;; insert value.
+                            (delete-region begin end)
+                            (insert replacement)))))
+                     ((or `babel-call `inline-babel-call)
+                      (org-babel-exp-do-export (org-babel-lob-get-info element)
+                                               'lob)
+                      (let ((rep
+                             (org-fill-template
+                              org-babel-exp-call-line-template
+                              `(("line"  .
+                                 ,(org-element-property :value element))))))
+                        ;; If replacement is empty, completely remove
+                        ;; the object/element, including any extra
+                        ;; white space that might have been created
+                        ;; when including results.
+                        (if (equal rep "")
+                            (delete-region
+                             begin
+                             (progn (goto-char end)
+                                    (if (not (eq type 'babel-call))
+                                        (progn (skip-chars-forward " \t")
+                                               (point))
+                                      (skip-chars-forward " \r\t\n")
+                                      (line-beginning-position))))
+                          ;; Otherwise, preserve trailing
+                          ;; spaces/newlines and then, insert
+                          ;; replacement string.
+                          (goto-char begin)
+                          (delete-region begin end)
+                          (insert rep))))
+                     (`src-block
+                      (let ((match-start (copy-marker (match-beginning 0)))
+                            (ind (org-get-indentation)))
+                        ;; Take care of matched block: compute
+                        ;; replacement string.  In particular, a nil
+                        ;; REPLACEMENT means the block is left as-is
+                        ;; while an empty string removes the block.
+                        (let ((replacement
+                               (progn (goto-char match-start)
+                                      (org-babel-exp-src-block))))
+                          (cond ((not replacement) (goto-char end))
+                                ((equal replacement "")
+                                 (goto-char end)
+                                 (skip-chars-forward " \r\t\n")
+                                 (beginning-of-line)
+                                 (delete-region begin (point)))
+                                (t
+                                 (goto-char match-start)
+                                 (delete-region (point)
+                                                (save-excursion
+                                                  (goto-char end)
+                                                  (line-end-position)))
+                                 (insert replacement)
+                                 (if (or org-src-preserve-indentation
+                                         (org-element-property
+                                          :preserve-indent element))
+                                     ;; Indent only code block
+                                     ;; markers.
+                                     (save-excursion
+                                       (skip-chars-backward " \r\t\n")
+                                       (indent-line-to ind)
+                                       (goto-char match-start)
+                                       (indent-line-to ind))
+                                   ;; Indent everything.
+                                   (indent-rigidly
+                                    match-start (point) ind)))))
+                        (set-marker match-start nil))))
+                   (set-marker begin nil)
+                   (set-marker end nil)))))
+         (kill-buffer org-babel-exp-reference-buffer)
+         (remove-text-properties (point-min) (point-max) '(org-reference)))))))
 
 (defun org-babel-exp-do-export (info type &optional hash)
   "Return a string with the exported content of a code block.
 The function respects the value of the :exports header argument."
-  (let ((silently (lambda () (let ((session (cdr (assoc :session (nth 2 
info)))))
-                              (when (not (and session (equal "none" session)))
-                                (org-babel-exp-results info type 'silent)))))
-       (clean (lambda () (unless (eq type 'inline) (org-babel-remove-result 
info)))))
-    (case (intern (or (cdr (assoc :exports (nth 2 info))) "code"))
-      ('none (funcall silently) (funcall clean) "")
-      ('code (funcall silently) (funcall clean) (org-babel-exp-code info))
-      ('results (org-babel-exp-results info type nil hash) "")
-      ('both (org-babel-exp-results info type nil hash)
-            (org-babel-exp-code info)))))
+  (let ((silently (lambda () (let ((session (cdr (assq :session (nth 2 
info)))))
+                         (unless (equal "none" session)
+                           (org-babel-exp-results info type 'silent)))))
+       (clean (lambda () (if (eq type 'inline)
+                        (org-babel-remove-inline-result)
+                      (org-babel-remove-result info)))))
+    (pcase (or (cdr (assq :exports (nth 2 info))) "code")
+      ("none" (funcall silently) (funcall clean) "")
+      ("code" (funcall silently) (funcall clean) (org-babel-exp-code info 
type))
+      ("results" (org-babel-exp-results info type nil hash) "")
+      ("both"
+       (org-babel-exp-results info type nil hash)
+       (org-babel-exp-code info type)))))
 
 (defcustom org-babel-exp-code-template
   "#+BEGIN_SRC %lang%switches%flags\n%body\n#+END_SRC"
@@ -331,18 +320,42 @@ replaced with its value."
   :group 'org-babel
   :type 'string)
 
-(defun org-babel-exp-code (info)
+(defcustom org-babel-exp-inline-code-template
+  "src_%lang[%switches%flags]{%body}"
+  "Template used to export the body of inline code blocks.
+This template may be customized to include additional information
+such as the code block name, or the values of particular header
+arguments.  The template is filled out using `org-fill-template',
+and the following %keys may be used.
+
+ lang ------ the language of the code block
+ name ------ the name of the code block
+ body ------ the body of the code block
+ switches -- the switches associated to the code block
+ flags ----- the flags passed to the code block
+
+In addition to the keys mentioned above, every header argument
+defined for the code block may be used as a key and will be
+replaced with its value."
+  :group 'org-babel
+  :type 'string
+  :version "26.1"
+  :package-version '(Org . "8.3"))
+
+(defun org-babel-exp-code (info type)
   "Return the original code block formatted for export."
   (setf (nth 1 info)
-       (if (string= "strip-export" (cdr (assoc :noweb (nth 2 info))))
+       (if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
            (replace-regexp-in-string
             (org-babel-noweb-wrap) "" (nth 1 info))
          (if (org-babel-noweb-p (nth 2 info) :export)
              (org-babel-expand-noweb-references
-              info (org-babel-exp-get-export-buffer))
+              info org-babel-exp-reference-buffer)
            (nth 1 info))))
   (org-fill-template
-   org-babel-exp-code-template
+   (if (eq type 'inline)
+       org-babel-exp-inline-code-template
+       org-babel-exp-code-template)
    `(("lang"  . ,(nth 0 info))
      ("body"  . ,(org-escape-code-in-string (nth 1 info)))
      ("switches" . ,(let ((f (nth 3 info)))
@@ -357,48 +370,41 @@ replaced with its value."
 
 (defun org-babel-exp-results (info type &optional silent hash)
   "Evaluate and return the results of the current code block for export.
-Results are prepared in a manner suitable for export by org-mode.
+Results are prepared in a manner suitable for export by Org mode.
 This function is called by `org-babel-exp-do-export'.  The code
 block will be evaluated.  Optional argument SILENT can be used to
 inhibit insertion of results into the buffer."
-  (when (and (or (eq org-export-babel-evaluate t)
-                (and (eq type 'inline)
-                     (eq org-export-babel-evaluate 'inline-only)))
-            (not (and hash (equal hash (org-babel-current-result-hash)))))
+  (unless (and hash (equal hash (org-babel-current-result-hash)))
     (let ((lang (nth 0 info))
          (body (if (org-babel-noweb-p (nth 2 info) :eval)
                    (org-babel-expand-noweb-references
-                    info (org-babel-exp-get-export-buffer))
+                    info org-babel-exp-reference-buffer)
                  (nth 1 info)))
          (info (copy-sequence info))
          (org-babel-current-src-block-location (point-marker)))
-      ;; skip code blocks which we can't evaluate
+      ;; Skip code blocks which we can't evaluate.
       (when (fboundp (intern (concat "org-babel-execute:" lang)))
        (org-babel-eval-wipe-error-buffer)
-       (prog1 nil
-         (setf (nth 1 info) body)
-         (setf (nth 2 info)
-               (org-babel-exp-in-export-file lang
-                 (org-babel-process-params
-                  (org-babel-merge-params
-                   (nth 2 info)
-                   `((:results . ,(if silent "silent" "replace")))))))
-         (cond
-          ((equal type 'block)
-           (org-babel-execute-src-block nil info))
-          ((equal type 'inline)
-           ;; position the point on the inline source block allowing
-           ;; `org-babel-insert-result' to check that the block is
-           ;; inline
-           (re-search-backward "[ \f\t\n\r\v]" nil t)
-           (re-search-forward org-babel-inline-src-block-regexp nil t)
-           (re-search-backward "src_" nil t)
+       (setf (nth 1 info) body)
+       (setf (nth 2 info)
+             (org-babel-exp--at-source
+               (org-babel-process-params
+                (org-babel-merge-params
+                 (nth 2 info)
+                 `((:results . ,(if silent "silent" "replace")))))))
+       (pcase type
+         (`block (org-babel-execute-src-block nil info))
+         (`inline
+           ;; Position the point on the inline source block
+           ;; allowing `org-babel-insert-result' to check that the
+           ;; block is inline.
+           (goto-char (nth 5 info))
            (org-babel-execute-src-block nil info))
-          ((equal type 'lob)
-           (save-excursion
-             (re-search-backward org-babel-lob-one-liner-regexp nil t)
-             (let (org-confirm-babel-evaluate)
-               (org-babel-execute-src-block nil info))))))))))
+         (`lob
+          (save-excursion
+            (goto-char (nth 5 info))
+            (let (org-confirm-babel-evaluate)
+              (org-babel-execute-src-block nil info)))))))))
 
 
 (provide 'ob-exp)
diff --git a/lisp/org/ob-forth.el b/lisp/org/ob-forth.el
new file mode 100644
index 0000000..152cf72
--- /dev/null
+++ b/lisp/org/ob-forth.el
@@ -0,0 +1,87 @@
+;;; ob-forth.el --- Babel Functions for Forth        -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research, forth
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Requires the gforth forth compiler and `forth-mode' (see below).
+;; https://www.gnu.org/software/gforth/
+
+;;; Requirements:
+
+;; Session evaluation requires the gforth forth compiler as well as
+;; `forth-mode' which is distributed with gforth (in gforth.el).
+
+;;; Code:
+(require 'ob)
+
+(declare-function forth-proc "ext:gforth" ())
+(declare-function org-trim "org" (s &optional keep-lead))
+
+(defvar org-babel-default-header-args:forth '((:session . "yes"))
+  "Default header arguments for forth code blocks.")
+
+(defun org-babel-execute:forth (body params)
+  "Execute a block of Forth code with org-babel.
+This function is called by `org-babel-execute-src-block'"
+  (if (string= "none" (cdr (assq :session params)))
+      (error "Non-session evaluation not supported for Forth code blocks")
+    (let ((all-results (org-babel-forth-session-execute body params)))
+      (if (member "output" (cdr (assq :result-params params)))
+         (mapconcat #'identity all-results "\n")
+       (car (last all-results))))))
+
+(defun org-babel-forth-session-execute (body params)
+  (require 'forth-mode)
+  (let ((proc (forth-proc))
+       (rx " \\(\n:\\|compiled\n\\\|ok\n\\)")
+       (result-start))
+    (with-current-buffer (process-buffer (forth-proc))
+      (mapcar (lambda (line)
+               (setq result-start (progn (goto-char (process-mark proc))
+                                         (point)))
+               (comint-send-string proc (concat line "\n"))
+               ;; wait for forth to say "ok"
+               (while (not (progn (goto-char result-start)
+                                  (re-search-forward rx nil t)))
+                 (accept-process-output proc 0.01))
+               (let ((case (match-string 1)))
+                 (cond
+                  ((string= "ok\n" case)
+                   ;; Collect intermediate output.
+                   (buffer-substring (+ result-start 1 (length line))
+                                     (match-beginning 0)))
+                  ((string= "compiled\n" case))
+                  ;; Ignore partial compilation.
+                  ((string= "\n:" case)
+                   ;; Report errors.
+                   (org-babel-eval-error-notify 1
+                    (buffer-substring
+                     (+ (match-beginning 0) 1) (point-max))) nil))))
+             (split-string (org-trim
+                            (org-babel-expand-body:generic body params))
+                           "\n"
+                           'omit-nulls)))))
+
+(provide 'ob-forth)
+
+;;; ob-forth.el ends here
diff --git a/lisp/org/ob-fortran.el b/lisp/org/ob-fortran.el
index 6a6112d..d059245 100644
--- a/lisp/org/ob-fortran.el
+++ b/lisp/org/ob-fortran.el
@@ -1,4 +1,4 @@
-;;; ob-fortran.el --- org-babel functions for fortran
+;;; ob-fortran.el --- Babel Functions for Fortran    -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -29,10 +29,12 @@
 ;;; Code:
 (require 'ob)
 (require 'cc-mode)
+(require 'cl-lib)
 
 (declare-function org-entry-get "org"
                  (pom property &optional inherit literal-nil))
-(declare-function org-every "org" (pred seq))
+(declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("fortran" . "F90"))
@@ -47,43 +49,42 @@
   "This function should only be called by `org-babel-execute:fortran'"
   (let* ((tmp-src-file (org-babel-temp-file "fortran-src-" ".F90"))
          (tmp-bin-file (org-babel-temp-file "fortran-bin-" org-babel-exeext))
-         (cmdline (cdr (assoc :cmdline params)))
-         (flags (cdr (assoc :flags params)))
-         (full-body (org-babel-expand-body:fortran body params))
-         (compile
-         (progn
-           (with-temp-file tmp-src-file (insert full-body))
-           (org-babel-eval
-            (format "%s -o %s %s %s"
-                    org-babel-fortran-compiler
-                    (org-babel-process-file-name tmp-bin-file)
-                    (mapconcat 'identity
-                               (if (listp flags) flags (list flags)) " ")
-                    (org-babel-process-file-name tmp-src-file)) ""))))
+         (cmdline (cdr (assq :cmdline params)))
+         (flags (cdr (assq :flags params)))
+         (full-body (org-babel-expand-body:fortran body params)))
+    (with-temp-file tmp-src-file (insert full-body))
+    (org-babel-eval
+     (format "%s -o %s %s %s"
+            org-babel-fortran-compiler
+            (org-babel-process-file-name tmp-bin-file)
+            (mapconcat 'identity
+                       (if (listp flags) flags (list flags)) " ")
+            (org-babel-process-file-name tmp-src-file)) "")
     (let ((results
-           (org-babel-trim
-            (org-babel-eval
-             (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) ""))))
+           (org-trim
+            (org-remove-indentation
+            (org-babel-eval
+             (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) "")))))
       (org-babel-reassemble-table
-       (org-babel-result-cond (cdr (assoc :result-params params))
+       (org-babel-result-cond (cdr (assq :result-params params))
         (org-babel-read results)
          (let ((tmp-file (org-babel-temp-file "f-")))
            (with-temp-file tmp-file (insert results))
            (org-babel-import-elisp-from-file tmp-file)))
        (org-babel-pick-name
-        (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+        (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
        (org-babel-pick-name
-        (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))))
+        (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
 
 (defun org-babel-expand-body:fortran (body params)
   "Expand a block of fortran or fortran code with org-babel according to
-it's header arguments."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-        (main-p (not (string= (cdr (assoc :main params)) "no")))
-        (includes (or (cdr (assoc :includes params))
+its header arguments."
+  (let ((vars (org-babel--get-vars params))
+        (main-p (not (string= (cdr (assq :main params)) "no")))
+        (includes (or (cdr (assq :includes params))
                       (org-babel-read (org-entry-get nil "includes" t))))
         (defines (org-babel-read
-                  (or (cdr (assoc :defines params))
+                  (or (cdr (assq :defines params))
                       (org-babel-read (org-entry-get nil "defines" t))))))
     (mapconcat 'identity
               (list
@@ -107,17 +108,17 @@ it's header arguments."
 (defun org-babel-fortran-ensure-main-wrap (body params)
   "Wrap body in a \"program ... end program\" block if none exists."
   (if (string-match "^[ \t]*program[ \t]*.*" (capitalize body))
-      (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+      (let ((vars (org-babel--get-vars params)))
        (if vars (error "Cannot use :vars if `program' statement is present"))
        body)
     (format "program main\n%s\nend program main\n" body)))
 
-(defun org-babel-prep-session:fortran (session params)
+(defun org-babel-prep-session:fortran (_session _params)
   "This function does nothing as fortran is a compiled language with no
 support for sessions"
   (error "Fortran is a compiled languages -- no support for sessions"))
 
-(defun org-babel-load-session:fortran (session body params)
+(defun org-babel-load-session:fortran (_session _body _params)
   "This function does nothing as fortran is a compiled language with no
 support for sessions"
   (error "Fortran is a compiled languages -- no support for sessions"))
@@ -145,7 +146,7 @@ of the same value."
       (format "character(len=%d), parameter ::  %S = '%s'\n"
               (length val) var val))
      ;; val is a matrix
-     ((and (listp val) (org-every #'listp val))
+     ((and (listp val) (cl-every #'listp val))
       (format "real, parameter :: %S(%d,%d) = transpose( reshape( %s , (/ %d, 
%d /) ) )\n"
              var (length val) (length (car val))
              (org-babel-fortran-transform-list val)
diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el
index 82b103e..400823b 100644
--- a/lisp/org/ob-gnuplot.el
+++ b/lisp/org/ob-gnuplot.el
@@ -1,4 +1,4 @@
-;;; ob-gnuplot.el --- org-babel functions for gnuplot evaluation
+;;; ob-gnuplot.el --- Babel Functions for Gnuplot    -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -39,12 +39,10 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function org-time-string-to-time "org" (s &optional buffer pos))
 (declare-function org-combine-plists "org" (&rest plists))
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
+(declare-function orgtbl-to-generic "org-table" (table params))
 (declare-function gnuplot-mode "ext:gnuplot-mode" ())
 (declare-function gnuplot-send-string-to-gnuplot "ext:gnuplot-mode" (str txt))
 (declare-function gnuplot-send-buffer-to-gnuplot "ext:gnuplot-mode" ())
@@ -65,7 +63,7 @@
     (term       . :any))
   "Gnuplot specific header args.")
 
-(defvar org-babel-gnuplot-timestamp-fmt nil)
+(defvar org-babel-gnuplot-timestamp-fmt nil) ; Dynamically scoped.
 
 (defvar *org-babel-gnuplot-missing* nil)
 
@@ -81,7 +79,7 @@
 Dumps all vectors into files and returns an association list
 of variable names and the related value to be used in the gnuplot
 code."
-  (let ((*org-babel-gnuplot-missing* (cdr (assoc :missing params))))
+  (let ((*org-babel-gnuplot-missing* (cdr (assq :missing params))))
     (mapcar
      (lambda (pair)
        (cons
@@ -95,38 +93,33 @@ code."
                 (if tablep val (mapcar 'list val)))
               (org-babel-temp-file "gnuplot-") params)
          val))))
-     (mapcar #'cdr (org-babel-get-header params :var)))))
+     (org-babel--get-vars params))))
 
 (defun org-babel-expand-body:gnuplot (body params)
   "Expand BODY according to PARAMS, return the expanded body."
   (save-window-excursion
     (let* ((vars (org-babel-gnuplot-process-vars params))
-           (out-file (cdr (assoc :file params)))
-          (prologue (cdr (assoc :prologue params)))
-          (epilogue (cdr (assoc :epilogue params)))
-          (term (or (cdr (assoc :term params))
+           (out-file (cdr (assq :file params)))
+          (prologue (cdr (assq :prologue params)))
+          (epilogue (cdr (assq :epilogue params)))
+          (term (or (cdr (assq :term params))
                      (when out-file
                       (let ((ext (file-name-extension out-file)))
                         (or (cdr (assoc (intern (downcase ext))
                                         *org-babel-gnuplot-terms*))
                             ext)))))
-           (cmdline (cdr (assoc :cmdline params)))
-           (title (cdr (assoc :title params)))
-           (lines (cdr (assoc :line params)))
-           (sets (cdr (assoc :set params)))
-           (x-labels (cdr (assoc :xlabels params)))
-           (y-labels (cdr (assoc :ylabels params)))
-           (timefmt (cdr (assoc :timefmt params)))
-           (time-ind (or (cdr (assoc :timeind params))
+           (title (cdr (assq :title params)))
+           (lines (cdr (assq :line params)))
+           (sets (cdr (assq :set params)))
+           (x-labels (cdr (assq :xlabels params)))
+           (y-labels (cdr (assq :ylabels params)))
+           (timefmt (cdr (assq :timefmt params)))
+           (time-ind (or (cdr (assq :timeind params))
                          (when timefmt 1)))
-          (missing (cdr (assoc :missing params)))
-          (add-to-body (lambda (text) (setq body (concat text "\n" body))))
-           output)
+          (add-to-body (lambda (text) (setq body (concat text "\n" body)))))
       ;; append header argument settings to body
       (when title (funcall add-to-body (format "set title '%s'" title)))
       (when lines (mapc (lambda (el) (funcall add-to-body el)) lines))
-      (when missing
-       (funcall add-to-body (format "set datafile missing '%s'" missing)))
       (when sets
        (mapc (lambda (el) (funcall add-to-body (format "set %s" el))) sets))
       (when x-labels
@@ -175,9 +168,8 @@ code."
   "Execute a block of Gnuplot code.
 This function is called by `org-babel-execute-src-block'."
   (require 'gnuplot)
-  (let ((session (cdr (assoc :session params)))
-        (result-type (cdr (assoc :results params)))
-        (out-file (cdr (assoc :file params)))
+  (let ((session (cdr (assq :session params)))
+        (result-type (cdr (assq :results params)))
         (body (org-babel-expand-body:gnuplot body params))
        output)
     (save-window-excursion
@@ -195,7 +187,7 @@ This function is called by `org-babel-execute-src-block'."
                     script-file
                     (if (member system-type '(cygwin windows-nt ms-dos))
                         t nil)))))
-            (message output))
+            (message "%s" output))
         (with-temp-buffer
           (insert (concat body "\n"))
           (gnuplot-mode)
@@ -210,10 +202,12 @@ This function is called by `org-babel-execute-src-block'."
          (var-lines (org-babel-variable-assignments:gnuplot params)))
     (message "%S" session)
     (org-babel-comint-in-buffer session
-      (mapc (lambda (var-line)
-              (insert var-line) (comint-send-input nil t)
-              (org-babel-comint-wait-for-output session)
-              (sit-for .1) (goto-char (point-max))) var-lines))
+      (dolist (var-line  var-lines)
+       (insert var-line)
+       (comint-send-input nil t)
+       (org-babel-comint-wait-for-output session)
+       (sit-for .1)
+       (goto-char (point-max))))
     session))
 
 (defun org-babel-load-session:gnuplot (session body params)
@@ -232,7 +226,7 @@ This function is called by `org-babel-execute-src-block'."
    (org-babel-gnuplot-process-vars params)))
 
 (defvar gnuplot-buffer)
-(defun org-babel-gnuplot-initiate-session (&optional session params)
+(defun org-babel-gnuplot-initiate-session (&optional session _params)
   "Initiate a gnuplot session.
 If there is not a current inferior-process-buffer in SESSION
 then create one.  Return the initialized session.  The current
@@ -268,15 +262,13 @@ then create one.  Return the initialized session.  The 
current
   "Export TABLE to DATA-FILE in a format readable by gnuplot.
 Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
   (with-temp-file data-file
-    (make-local-variable 'org-babel-gnuplot-timestamp-fmt)
-    (setq org-babel-gnuplot-timestamp-fmt (or
-                                           (plist-get params :timefmt)
-                                           "%Y-%m-%d-%H:%M:%S"))
-    (insert (orgtbl-to-generic
-            table
-            (org-combine-plists
-             '(:sep "\t" :fmt org-babel-gnuplot-quote-tsv-field)
-             params))))
+    (insert (let ((org-babel-gnuplot-timestamp-fmt
+                  (or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S")))
+             (orgtbl-to-generic
+              table
+              (org-combine-plists
+               '(:sep "\t" :fmt org-babel-gnuplot-quote-tsv-field)
+               params)))))
   data-file)
 
 (provide 'ob-gnuplot)
diff --git a/lisp/org/ob-groovy.el b/lisp/org/ob-groovy.el
new file mode 100644
index 0000000..69993c0
--- /dev/null
+++ b/lisp/org/ob-groovy.el
@@ -0,0 +1,116 @@
+;;; ob-groovy.el --- Babel Functions for Groovy      -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+;; Author: Miro Bezjak
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; Currently only supports the external execution.  No session support yet.
+
+;;; Requirements:
+;; - Groovy language :: http://groovy.codehaus.org
+;; - Groovy major mode :: Can be installed from MELPA or
+;;   https://github.com/russel/Emacs-Groovy-Mode
+
+;;; Code:
+(require 'ob)
+
+(defvar org-babel-tangle-lang-exts) ;; Autoloaded
+(add-to-list 'org-babel-tangle-lang-exts '("groovy" . "groovy"))
+(defvar org-babel-default-header-args:groovy '())
+(defcustom org-babel-groovy-command "groovy"
+  "Name of the command to use for executing Groovy code.
+May be either a command in the path, like groovy
+or an absolute path name, like /usr/local/bin/groovy
+parameters may be used, like groovy -v"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
+
+(defun org-babel-execute:groovy (body params)
+  "Execute a block of Groovy code with org-babel.  This function is
+called by `org-babel-execute-src-block'"
+  (message "executing Groovy source code block")
+  (let* ((processed-params (org-babel-process-params params))
+         (session (org-babel-groovy-initiate-session (nth 0 processed-params)))
+         (result-params (nth 2 processed-params))
+         (result-type (cdr (assq :result-type params)))
+         (full-body (org-babel-expand-body:generic
+                     body params))
+         (result (org-babel-groovy-evaluate
+                  session full-body result-type result-params)))
+
+    (org-babel-reassemble-table
+     result
+     (org-babel-pick-name
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+     (org-babel-pick-name
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
+
+(defvar org-babel-groovy-wrapper-method
+
+  "class Runner extends Script {
+    def out = new PrintWriter(new ByteArrayOutputStream())
+    def run() { %s }
+}
+
+println(new Runner().run())
+")
+
+
+(defun org-babel-groovy-evaluate
+    (session body &optional result-type result-params)
+  "Evaluate BODY in external Groovy process.
+If RESULT-TYPE equals `output' then return standard output as a string.
+If RESULT-TYPE equals `value' then return the value of the last statement
+in BODY as elisp."
+  (when session (error "Sessions are not (yet) supported for Groovy"))
+  (pcase result-type
+    (`output
+     (let ((src-file (org-babel-temp-file "groovy-")))
+       (progn (with-temp-file src-file (insert body))
+              (org-babel-eval
+               (concat org-babel-groovy-command " " src-file) ""))))
+    (`value
+     (let* ((src-file (org-babel-temp-file "groovy-"))
+            (wrapper (format org-babel-groovy-wrapper-method body)))
+       (with-temp-file src-file (insert wrapper))
+       (let ((raw (org-babel-eval
+                   (concat org-babel-groovy-command " " src-file) "")))
+         (org-babel-result-cond result-params
+          raw
+           (org-babel-script-escape raw)))))))
+
+
+(defun org-babel-prep-session:groovy (_session _params)
+  "Prepare SESSION according to the header arguments specified in PARAMS."
+  (error "Sessions are not (yet) supported for Groovy"))
+
+(defun org-babel-groovy-initiate-session (&optional _session)
+  "If there is not a current inferior-process-buffer in SESSION
+then create.  Return the initialized session.  Sessions are not
+supported in Groovy."
+  nil)
+
+(provide 'ob-groovy)
+
+
+
+;;; ob-groovy.el ends here
diff --git a/lisp/org/ob-haskell.el b/lisp/org/ob-haskell.el
index ce6b8ed..ecce6dc 100644
--- a/lisp/org/ob-haskell.el
+++ b/lisp/org/ob-haskell.el
@@ -1,4 +1,4 @@
-;;; ob-haskell.el --- org-babel functions for haskell evaluation
+;;; ob-haskell.el --- Babel Functions for Haskell    -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -41,9 +41,9 @@
 ;;; Code:
 (require 'ob)
 (require 'comint)
-(eval-when-compile (require 'cl))
 
 (declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function haskell-mode "ext:haskell-mode" ())
 (declare-function run-haskell "ext:inf-haskell" (&optional arg))
 (declare-function inferior-haskell-load-file
@@ -61,42 +61,35 @@
 
 (defun org-babel-execute:haskell (body params)
   "Execute a block of Haskell code."
-  (let* ((session (cdr (assoc :session params)))
-         (vars (mapcar #'cdr (org-babel-get-header params :var)))
-         (result-type (cdr (assoc :result-type params)))
+  (let* ((session (cdr (assq :session params)))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                     body params
                     (org-babel-variable-assignments:haskell params)))
          (session (org-babel-haskell-initiate-session session params))
          (raw (org-babel-comint-with-output
                  (session org-babel-haskell-eoe t full-body)
-                (insert (org-babel-trim full-body))
+                (insert (org-trim full-body))
                 (comint-send-input nil t)
                 (insert org-babel-haskell-eoe)
                 (comint-send-input nil t)))
          (results (mapcar
-                   #'org-babel-haskell-read-string
+                   #'org-babel-strip-quotes
                    (cdr (member org-babel-haskell-eoe
-                                (reverse (mapcar #'org-babel-trim raw)))))))
+                                (reverse (mapcar #'org-trim raw)))))))
     (org-babel-reassemble-table
      (let ((result
-            (case result-type
-              (output (mapconcat #'identity (reverse (cdr results)) "\n"))
-              (value (car results)))))
-       (org-babel-result-cond (cdr (assoc :result-params params))
-        result (org-babel-haskell-table-or-string result)))
-     (org-babel-pick-name (cdr (assoc :colname-names params))
-                         (cdr (assoc :colname-names params)))
-     (org-babel-pick-name (cdr (assoc :rowname-names params))
-                         (cdr (assoc :rowname-names params))))))
-
-(defun org-babel-haskell-read-string (string)
-  "Strip \\\"s from around a haskell string."
-  (if (string-match "^\"\\([^\000]+\\)\"$" string)
-      (match-string 1 string)
-    string))
-
-(defun org-babel-haskell-initiate-session (&optional session params)
+            (pcase result-type
+              (`output (mapconcat #'identity (reverse (cdr results)) "\n"))
+              (`value (car results)))))
+       (org-babel-result-cond (cdr (assq :result-params params))
+        result (org-babel-script-escape result)))
+     (org-babel-pick-name (cdr (assq :colname-names params))
+                         (cdr (assq :colname-names params)))
+     (org-babel-pick-name (cdr (assq :rowname-names params))
+                         (cdr (assq :rowname-names params))))))
+
+(defun org-babel-haskell-initiate-session (&optional _session _params)
   "Initiate a haskell session.
 If there is not a current inferior-process-buffer in SESSION
 then create one.  Return the initialized session."
@@ -131,13 +124,7 @@ then create one.  Return the initialized session."
            (format "let %s = %s"
                    (car pair)
                    (org-babel-haskell-var-to-haskell (cdr pair))))
-         (mapcar #'cdr (org-babel-get-header params :var))))
-
-(defun org-babel-haskell-table-or-string (results)
-  "Convert RESULTS to an Emacs-lisp table or string.
-If RESULTS look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
-  (org-babel-script-escape results))
+         (org-babel--get-vars params)))
 
 (defun org-babel-haskell-var-to-haskell (var)
   "Convert an elisp value VAR into a haskell variable.
@@ -157,7 +144,7 @@ specifying a variable of the same value."
 When called with a prefix argument the resulting
 .lhs file will be exported to a .tex file.  This function will
 create two new files, base-name.lhs and base-name.tex where
-base-name is the name of the current org-mode file.
+base-name is the name of the current Org file.
 
 Note that all standard Babel literate programming
 constructs (header arguments, no-web syntax etc...) are ignored."
@@ -185,12 +172,12 @@ constructs (header arguments, no-web syntax etc...) are 
ignored."
         (save-match-data (setq indentation (length (match-string 1))))
         (replace-match (save-match-data
                          (concat
-                          "#+begin_latex\n\\begin{code}\n"
+                          "#+begin_export latex\n\\begin{code}\n"
                           (if (or preserve-indentp
                                   (string-match "-i" (match-string 2)))
                               (match-string 3)
                             (org-remove-indentation (match-string 3)))
-                          "\n\\end{code}\n#+end_latex\n"))
+                          "\n\\end{code}\n#+end_export\n"))
                        t t)
         (indent-code-rigidly (match-beginning 0) (match-end 0) indentation)))
     (save-excursion
diff --git a/lisp/org/ob-io.el b/lisp/org/ob-io.el
index 1d3a42a..5dd6110 100644
--- a/lisp/org/ob-io.el
+++ b/lisp/org/ob-io.el
@@ -1,4 +1,4 @@
-;;; ob-io.el --- org-babel functions for Io evaluation
+;;; ob-io.el --- Babel Functions for Io              -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -33,7 +33,6 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (defvar org-babel-tangle-lang-exts) ;; Autoloaded
 (add-to-list 'org-babel-tangle-lang-exts '("io" . "io"))
@@ -47,9 +46,8 @@ called by `org-babel-execute-src-block'"
   (message "executing Io source code block")
   (let* ((processed-params (org-babel-process-params params))
          (session (org-babel-io-initiate-session (nth 0 processed-params)))
-         (vars (nth 1 processed-params))
          (result-params (nth 2 processed-params))
-         (result-type (cdr (assoc :result-type params)))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                      body params))
          (result (org-babel-io-evaluate
@@ -58,17 +56,9 @@ called by `org-babel-execute-src-block'"
     (org-babel-reassemble-table
      result
      (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
      (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
-
-
-(defun org-babel-io-table-or-string (results)
-  "Convert RESULTS into an appropriate elisp value.
-If RESULTS look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
-  (org-babel-script-escape results))
-
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
 
 (defvar org-babel-io-wrapper-method
   "(
@@ -79,33 +69,33 @@ Emacs-lisp table, otherwise return the results as a string."
 
 (defun org-babel-io-evaluate (session body &optional result-type result-params)
   "Evaluate BODY in external Io process.
-If RESULT-TYPE equals 'output then return standard output as a string.
-If RESULT-TYPE equals 'value then return the value of the last statement
+If RESULT-TYPE equals `output' then return standard output as a string.
+If RESULT-TYPE equals `value' then return the value of the last statement
 in BODY as elisp."
   (when session (error "Sessions are not (yet) supported for Io"))
-  (case result-type
-    (output
+  (pcase result-type
+    (`output
      (if (member "repl" result-params)
          (org-babel-eval org-babel-io-command body)
        (let ((src-file (org-babel-temp-file "io-")))
          (progn (with-temp-file src-file (insert body))
                 (org-babel-eval
                  (concat org-babel-io-command " " src-file) "")))))
-    (value (let* ((src-file (org-babel-temp-file "io-"))
-                  (wrapper (format org-babel-io-wrapper-method body)))
-             (with-temp-file src-file (insert wrapper))
-             (let ((raw (org-babel-eval
-                         (concat org-babel-io-command " " src-file) "")))
-               (org-babel-result-cond result-params
-                raw
-                 (org-babel-io-table-or-string raw)))))))
+    (`value (let* ((src-file (org-babel-temp-file "io-"))
+                  (wrapper (format org-babel-io-wrapper-method body)))
+             (with-temp-file src-file (insert wrapper))
+             (let ((raw (org-babel-eval
+                         (concat org-babel-io-command " " src-file) "")))
+               (org-babel-result-cond result-params
+                 raw
+                 (org-babel-script-escape raw)))))))
 
 
-(defun org-babel-prep-session:io (session params)
+(defun org-babel-prep-session:io (_session _params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
   (error "Sessions are not (yet) supported for Io"))
 
-(defun org-babel-io-initiate-session (&optional session)
+(defun org-babel-io-initiate-session (&optional _session)
   "If there is not a current inferior-process-buffer in SESSION
 then create.  Return the initialized session.  Sessions are not
 supported in Io."
diff --git a/lisp/org/ob-java.el b/lisp/org/ob-java.el
index 70a10e0..7e72023 100644
--- a/lisp/org/ob-java.el
+++ b/lisp/org/ob-java.el
@@ -1,4 +1,4 @@
-;;; ob-java.el --- org-babel functions for java evaluation
+;;; ob-java.el --- Babel Functions for Java          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -32,41 +32,51 @@
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("java" . "java"))
 
-(defvar org-babel-java-command "java"
-  "Name of the java command.")
-
-(defvar org-babel-java-compiler "javac"
-  "Name of the java compiler.")
+(defcustom org-babel-java-command "java"
+  "Name of the java command.
+May be either a command in the path, like java
+or an absolute path name, like /usr/local/bin/java
+parameters may be used, like java -verbose"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
+
+(defcustom org-babel-java-compiler "javac"
+  "Name of the java compiler.
+May be either a command in the path, like javac
+or an absolute path name, like /usr/local/bin/javac
+parameters may be used, like javac -verbose"
+  :group 'org-babel
+  :version "24.3"
+  :type 'string)
 
 (defun org-babel-execute:java (body params)
-  (let* ((classname (or (cdr (assoc :classname params))
+  (let* ((classname (or (cdr (assq :classname params))
                        (error
                         "Can't compile a java block without a classname")))
         (packagename (file-name-directory classname))
         (src-file (concat classname ".java"))
-        (cmpflag (or (cdr (assoc :cmpflag params)) ""))
-        (cmdline (or (cdr (assoc :cmdline params)) ""))
-        (full-body (org-babel-expand-body:generic body params))
-        (compile
-         (progn (with-temp-file src-file (insert full-body))
-                (org-babel-eval
-                 (concat org-babel-java-compiler
-                         " " cmpflag " " src-file) ""))))
+        (cmpflag (or (cdr (assq :cmpflag params)) ""))
+        (cmdline (or (cdr (assq :cmdline params)) ""))
+        (full-body (org-babel-expand-body:generic body params)))
+    (with-temp-file src-file (insert full-body))
+    (org-babel-eval
+     (concat org-babel-java-compiler " " cmpflag " " src-file) "")
     ;; created package-name directories if missing
     (unless (or (not packagename) (file-exists-p packagename))
       (make-directory packagename 'parents))
     (let ((results (org-babel-eval (concat org-babel-java-command
                                            " " cmdline " " classname) "")))
       (org-babel-reassemble-table
-       (org-babel-result-cond (cdr (assoc :result-params params))
+       (org-babel-result-cond (cdr (assq :result-params params))
         (org-babel-read results)
          (let ((tmp-file (org-babel-temp-file "c-")))
            (with-temp-file tmp-file (insert results))
            (org-babel-import-elisp-from-file tmp-file)))
        (org-babel-pick-name
-        (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+        (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
        (org-babel-pick-name
-        (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))))
+        (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
 
 (provide 'ob-java)
 
diff --git a/lisp/org/ob-js.el b/lisp/org/ob-js.el
index f4f8116..91be6b0 100644
--- a/lisp/org/ob-js.el
+++ b/lisp/org/ob-js.el
@@ -1,4 +1,4 @@
-;;; ob-js.el --- org-babel functions for Javascript
+;;; ob-js.el --- Babel Functions for Javascript      -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -39,7 +39,6 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function run-mozilla "ext:moz" (arg))
 
@@ -56,20 +55,20 @@
   :type 'string)
 
 (defvar org-babel-js-function-wrapper
-  "require('sys').print(require('sys').inspect(function(){%s}()));"
+  "require('sys').print(require('sys').inspect(function(){\n%s\n}()));"
   "Javascript code to print value of body.")
 
 (defun org-babel-execute:js (body params)
   "Execute a block of Javascript code with org-babel.
 This function is called by `org-babel-execute-src-block'"
-  (let* ((org-babel-js-cmd (or (cdr (assoc :cmd params)) org-babel-js-cmd))
-         (result-type (cdr (assoc :result-type params)))
+  (let* ((org-babel-js-cmd (or (cdr (assq :cmd params)) org-babel-js-cmd))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                     body params (org-babel-variable-assignments:js params)))
-        (result (if (not (string= (cdr (assoc :session params)) "none"))
+        (result (if (not (string= (cdr (assq :session params)) "none"))
                     ;; session evaluation
                     (let ((session (org-babel-prep-session:js
-                                    (cdr (assoc :session params)) params)))
+                                    (cdr (assq :session params)) params)))
                       (nth 1
                            (org-babel-comint-with-output
                                (session (format "%S" org-babel-js-eoe) t body)
@@ -89,7 +88,7 @@ This function is called by `org-babel-execute-src-block'"
                     (org-babel-eval
                      (format "%s %s" org-babel-js-cmd
                              (org-babel-process-file-name script-file)) "")))))
-    (org-babel-result-cond (cdr (assoc :result-params params))
+    (org-babel-result-cond (cdr (assq :result-params params))
       result (org-babel-js-read result))))
 
 (defun org-babel-js-read (results)
@@ -97,14 +96,17 @@ This function is called by `org-babel-execute-src-block'"
 If RESULTS look like a table, then convert them into an
 Emacs-lisp table, otherwise return the results as a string."
   (org-babel-read
-   (if (and (stringp results) (string-match "^\\[.+\\]$" results))
+   (if (and (stringp results)
+           (string-prefix-p "[" results)
+           (string-suffix-p "]" results))
        (org-babel-read
         (concat "'"
                 (replace-regexp-in-string
                  "\\[" "(" (replace-regexp-in-string
                             "\\]" ")" (replace-regexp-in-string
-                                       ", " " " (replace-regexp-in-string
-                                                "'" "\"" results))))))
+                                       ",[[:space:]]" " "
+                                      (replace-regexp-in-string
+                                       "'" "\"" results))))))
      results)))
 
 (defun org-babel-js-var-to-js (var)
@@ -113,7 +115,7 @@ Convert an elisp value into a string of js source code
 specifying a variable of the same value."
   (if (listp var)
       (concat "[" (mapconcat #'org-babel-js-var-to-js var ", ") "]")
-    (format "%S" var)))
+    (replace-regexp-in-string "\n" "\\\\n" (format "%S" var))))
 
 (defun org-babel-prep-session:js (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
@@ -133,7 +135,7 @@ specifying a variable of the same value."
   (mapcar
    (lambda (pair) (format "var %s=%s;"
                          (car pair) (org-babel-js-var-to-js (cdr pair))))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 (defun org-babel-js-initiate-session (&optional session)
   "If there is not a current inferior-process-buffer in SESSION
diff --git a/lisp/org/ob-keys.el b/lisp/org/ob-keys.el
index b71fba4..f5fb910 100644
--- a/lisp/org/ob-keys.el
+++ b/lisp/org/ob-keys.el
@@ -1,4 +1,4 @@
-;;; ob-keys.el --- key bindings for org-babel
+;;; ob-keys.el --- Key Bindings for Babel            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -23,8 +23,8 @@
 
 ;;; Commentary:
 
-;; Add org-babel keybindings to the org-mode keymap for exposing
-;; org-babel functions.  These will all share a common prefix.  See
+;; Add Org Babel keybindings to the Org mode keymap for exposing
+;; Org Babel functions.  These will all share a common prefix.  See
 ;; the value of `org-babel-key-bindings' for a list of interactive
 ;; functions and their associated keys.
 
@@ -89,6 +89,7 @@ functions which are assigned key bindings, and see
     ("h" . org-babel-describe-bindings)
     ("\C-x" . org-babel-do-key-sequence-in-edit-buffer)
     ("x" . org-babel-do-key-sequence-in-edit-buffer)
+    ("k" . org-babel-remove-result-one-or-many)
     ("\C-\M-h" . org-babel-mark-block))
   "Alist of key bindings and interactive Babel functions.
 This list associates interactive Babel functions
diff --git a/lisp/org/ob-latex.el b/lisp/org/ob-latex.el
index d008276..763ffb1 100644
--- a/lisp/org/ob-latex.el
+++ b/lisp/org/ob-latex.el
@@ -1,4 +1,4 @@
-;;; ob-latex.el --- org-babel functions for latex "evaluation"
+;;; ob-latex.el --- Babel Functions for LaTeX        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -32,12 +32,11 @@
 ;;; Code:
 (require 'ob)
 
-(declare-function org-create-formula-image "org"
-                  (string tofile options buffer &optional type))
-(declare-function org-splice-latex-header "org"
-                 (tpl def-pkg pkg snippets-p &optional extra))
-(declare-function org-latex-guess-inputenc "ox-latex" (header))
+(declare-function org-create-formula-image "org" (string tofile options buffer 
&optional type))
 (declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
+(declare-function org-latex-guess-inputenc "ox-latex" (header))
+(declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p 
&optional extra))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex"))
@@ -51,7 +50,22 @@
   '((:results . "latex") (:exports . "results"))
   "Default arguments to use when evaluating a LaTeX source block.")
 
-(defcustom org-babel-latex-htlatex ""
+(defconst org-babel-header-args:latex
+  '((border      . :any)
+    (fit          . :any)
+    (imagemagick  . ((nil t)))
+    (iminoptions  . :any)
+    (imoutoptions . :any)
+    (packages     . :any)
+    (pdfheight    . :any)
+    (pdfpng       . :any)
+    (pdfwidth     . :any)
+    (headers      . :any)
+    (packages     . :any)
+    (buffer       . ((yes no))))
+  "LaTeX-specific header arguments.")
+
+(defcustom org-babel-latex-htlatex "htlatex"
   "The htlatex command to enable conversion of latex to SVG or HTML."
   :group 'org-babel
   :type 'string)
@@ -70,37 +84,82 @@
                  (regexp-quote (format "%S" (car pair)))
                  (if (stringp (cdr pair))
                      (cdr pair) (format "%S" (cdr pair)))
-                 body))) (mapcar #'cdr (org-babel-get-header params :var)))
-  (org-babel-trim body))
+                 body))) (org-babel--get-vars params))
+  (org-trim body))
 
 (defun org-babel-execute:latex (body params)
   "Execute a block of Latex code with Babel.
 This function is called by `org-babel-execute-src-block'."
   (setq body (org-babel-expand-body:latex body params))
-  (if (cdr (assoc :file params))
-      (let* ((out-file (cdr (assoc :file params)))
+  (if (cdr (assq :file params))
+      (let* ((out-file (cdr (assq :file params)))
+            (extension (file-name-extension out-file))
             (tex-file (org-babel-temp-file "latex-" ".tex"))
-            (border (cdr (assoc :border params)))
-            (imagemagick (cdr (assoc :imagemagick params)))
-            (im-in-options (cdr (assoc :iminoptions params)))
-            (im-out-options (cdr (assoc :imoutoptions params)))
-            (pdfpng (cdr (assoc :pdfpng params)))
-            (fit (or (cdr (assoc :fit params)) border))
-            (height (and fit (cdr (assoc :pdfheight params))))
-            (width (and fit (cdr (assoc :pdfwidth params))))
-            (headers (cdr (assoc :headers params)))
-            (in-buffer (not (string= "no" (cdr (assoc :buffer params)))))
+            (border (cdr (assq :border params)))
+            (imagemagick (cdr (assq :imagemagick params)))
+            (im-in-options (cdr (assq :iminoptions params)))
+            (im-out-options (cdr (assq :imoutoptions params)))
+            (fit (or (cdr (assq :fit params)) border))
+            (height (and fit (cdr (assq :pdfheight params))))
+            (width (and fit (cdr (assq :pdfwidth params))))
+            (headers (cdr (assq :headers params)))
+            (in-buffer (not (string= "no" (cdr (assq :buffer params)))))
             (org-latex-packages-alist
-             (append (cdr (assoc :packages params)) org-latex-packages-alist)))
+             (append (cdr (assq :packages params)) org-latex-packages-alist)))
         (cond
-         ((and (string-match "\\.png$" out-file) (not imagemagick))
+         ((and (string-suffix-p ".png" out-file) (not imagemagick))
           (org-create-formula-image
            body out-file org-format-latex-options in-buffer))
-         ((string-match "\\.tikz$" out-file)
+         ((string-suffix-p ".tikz" out-file)
          (when (file-exists-p out-file) (delete-file out-file))
          (with-temp-file out-file
            (insert body)))
-        ((or (string-match "\\.pdf$" out-file) imagemagick)
+        ((and (or (string= "svg" extension)
+                  (string= "html" extension))
+              (executable-find org-babel-latex-htlatex))
+         ;; TODO: this is a very different way of generating the
+         ;; frame latex document than in the pdf case.  Ideally, both
+         ;; would be unified.  This would prevent bugs creeping in
+         ;; such as the one fixed on Aug 16 2014 whereby :headers was
+         ;; not included in the SVG/HTML case.
+         (with-temp-file tex-file
+           (insert (concat
+                    "\\documentclass[preview]{standalone}
+\\def\\pgfsysdriver{pgfsys-tex4ht.def}
+"
+                    (mapconcat (lambda (pkg)
+                                 (concat "\\usepackage" pkg))
+                               org-babel-latex-htlatex-packages
+                               "\n")
+                    (if headers
+                        (concat "\n"
+                                (if (listp headers)
+                                    (mapconcat #'identity headers "\n")
+                                  headers) "\n")
+                      "")
+                    "\\begin{document}"
+                    body
+                    "\\end{document}")))
+         (when (file-exists-p out-file) (delete-file out-file))
+         (let ((default-directory (file-name-directory tex-file)))
+           (shell-command (format "%s %s" org-babel-latex-htlatex tex-file)))
+         (cond
+          ((file-exists-p (concat (file-name-sans-extension tex-file) 
"-1.svg"))
+           (if (string-suffix-p ".svg" out-file)
+               (progn
+                 (shell-command "pwd")
+                 (shell-command (format "mv %s %s"
+                                        (concat (file-name-sans-extension 
tex-file) "-1.svg")
+                                        out-file)))
+             (error "SVG file produced but HTML file requested")))
+          ((file-exists-p (concat (file-name-sans-extension tex-file) ".html"))
+           (if (string-suffix-p ".html" out-file)
+               (shell-command "mv %s %s"
+                              (concat (file-name-sans-extension tex-file)
+                                      ".html")
+                              out-file)
+             (error "HTML file produced but SVG file requested")))))
+        ((or (string= "pdf" extension) imagemagick)
          (with-temp-file tex-file
            (require 'ox-latex)
            (insert
@@ -133,54 +192,20 @@ This function is called by `org-babel-execute-src-block'."
           (when (file-exists-p out-file) (delete-file out-file))
          (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file)))
            (cond
-            ((string-match "\\.pdf$" out-file)
+            ((string= "pdf" extension)
              (rename-file transient-pdf-file out-file))
             (imagemagick
-             (convert-pdf
+             (org-babel-latex-convert-pdf
               transient-pdf-file out-file im-in-options im-out-options)
              (when (file-exists-p transient-pdf-file)
-               (delete-file transient-pdf-file))))))
-        ((and (or (string-match "\\.svg$" out-file)
-                  (string-match "\\.html$" out-file))
-              (not (string= "" org-babel-latex-htlatex)))
-         (with-temp-file tex-file
-           (insert (concat
-                    "\\documentclass[preview]{standalone}
-\\def\\pgfsysdriver{pgfsys-tex4ht.def}
-"
-                    (mapconcat (lambda (pkg)
-                                 (concat "\\usepackage" pkg))
-                               org-babel-latex-htlatex-packages
-                               "\n")
-                    "\\begin{document}"
-                    body
-                    "\\end{document}")))
-         (when (file-exists-p out-file) (delete-file out-file))
-         (let ((default-directory (file-name-directory tex-file)))
-           (shell-command (format "%s %s" org-babel-latex-htlatex tex-file)))
-         (cond
-          ((file-exists-p (concat (file-name-sans-extension tex-file) 
"-1.svg"))
-           (if (string-match "\\.svg$" out-file)
-               (progn
-                 (shell-command "pwd")
-                 (shell-command (format "mv %s %s"
-                                        (concat (file-name-sans-extension 
tex-file) "-1.svg")
-                                        out-file)))
-             (error "SVG file produced but HTML file requested.")))
-          ((file-exists-p (concat (file-name-sans-extension tex-file) ".html"))
-           (if (string-match "\\.html$" out-file)
-               (shell-command "mv %s %s"
-                              (concat (file-name-sans-extension tex-file)
-                                      ".html")
-                              out-file)
-             (error "HTML file produced but SVG file requested.")))))
-         ((string-match "\\.\\([^\\.]+\\)$" out-file)
-          (error "Can not create %s files, please specify a .png or .pdf file 
or try the :imagemagick header argument"
-                (match-string 1 out-file))))
+               (delete-file transient-pdf-file)))
+            (t
+             (error "Can not create %s files, please specify a .png or .pdf 
file or try the :imagemagick header argument"
+                    extension))))))
         nil) ;; signal that output has already been written to file
     body))
 
-(defun convert-pdf (pdffile out-file im-in-options im-out-options)
+(defun org-babel-latex-convert-pdf (pdffile out-file im-in-options 
im-out-options)
   "Generate a file from a pdf file using imagemagick."
   (let ((cmd (concat "convert " im-in-options " " pdffile " "
                     im-out-options " " out-file)))
@@ -192,7 +217,7 @@ This function is called by `org-babel-execute-src-block'."
   (require 'ox-latex)
   (org-latex-compile file))
 
-(defun org-babel-prep-session:latex (session params)
+(defun org-babel-prep-session:latex (_session _params)
   "Return an error because LaTeX doesn't support sessions."
   (error "LaTeX does not support sessions"))
 
diff --git a/lisp/org/ob-ledger.el b/lisp/org/ob-ledger.el
index 154e75c..c02069e 100644
--- a/lisp/org/ob-ledger.el
+++ b/lisp/org/ob-ledger.el
@@ -1,4 +1,4 @@
-;;; ob-ledger.el --- org-babel functions for ledger evaluation
+;;; ob-ledger.el --- Babel Functions for Ledger      -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -46,8 +46,7 @@
   "Execute a block of Ledger entries with org-babel.  This function is
 called by `org-babel-execute-src-block'."
   (message "executing Ledger source code block")
-  (let ((result-params (split-string (or (cdr (assoc :results params)) "")))
-       (cmdline (cdr (assoc :cmdline params)))
+  (let ((cmdline (cdr (assq :cmdline params)))
         (in-file (org-babel-temp-file "ledger-"))
        (out-file (org-babel-temp-file "ledger-output-")))
     (with-temp-file in-file (insert body))
@@ -61,7 +60,7 @@ called by `org-babel-execute-src-block'."
                             " > " (org-babel-process-file-name out-file))))
     (with-temp-buffer (insert-file-contents out-file) (buffer-string))))
 
-(defun org-babel-prep-session:ledger (session params)
+(defun org-babel-prep-session:ledger (_session _params)
   (error "Ledger does not support sessions"))
 
 (provide 'ob-ledger)
diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el
index b37ecd8..37a7a6b 100644
--- a/lisp/org/ob-lilypond.el
+++ b/lisp/org/ob-lilypond.el
@@ -1,4 +1,4 @@
-;;; ob-lilypond.el --- org-babel functions for lilypond evaluation
+;;; ob-lilypond.el --- Babel Functions for Lilypond  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -28,6 +28,8 @@
 ;;
 ;; Lilypond documentation can be found at
 ;; http://lilypond.org/manuals.html
+;;
+;; This depends on epstopdf --- See http://www.ctan.org/pkg/epstopdf.
 
 ;;; Code:
 (require 'ob)
@@ -60,51 +62,68 @@ org-babel-lilypond-play-midi-post-tangle determines whether 
to automate the
 playing of the resultant midi file.  If the value is nil,
 the midi file is not automatically played.  Default value is t")
 
-(defvar org-babel-lilypond-OSX-ly-path
-  "/Applications/lilypond.app/Contents/Resources/bin/lilypond")
-(defvar org-babel-lilypond-OSX-pdf-path "open")
-(defvar org-babel-lilypond-OSX-midi-path "open")
-
-(defvar org-babel-lilypond-nix-ly-path "/usr/bin/lilypond")
-(defvar org-babel-lilypond-nix-pdf-path "evince")
-(defvar org-babel-lilypond-nix-midi-path "timidity")
-
-(defvar org-babel-lilypond-w32-ly-path "lilypond")
-(defvar org-babel-lilypond-w32-pdf-path "")
-(defvar org-babel-lilypond-w32-midi-path "")
+(defvar org-babel-lilypond-ly-command ""
+  "Command to execute lilypond on your system.
+Do not set it directly.  Customize `org-babel-lilypond-commands' instead.")
+(defvar org-babel-lilypond-pdf-command ""
+  "Command to show a PDF file on your system.
+Do not set it directly.  Customize `org-babel-lilypond-commands' instead.")
+(defvar org-babel-lilypond-midi-command ""
+  "Command to play a MIDI file on your system.
+Do not set it directly.  Customize `org-babel-lilypond-commands' instead.")
+(defcustom org-babel-lilypond-commands
+  (cond
+   ((eq system-type 'darwin)
+    '("/Applications/lilypond.app/Contents/Resources/bin/lilypond" "open" 
"open"))
+   ((eq system-type 'windows-nt)
+    '("lilypond" "" ""))
+   (t
+    '("lilypond" "xdg-open" "xdg-open")))
+  "Commands to run lilypond and view or play the results.
+These should be executables that take a filename as an argument.
+On some system it is possible to specify the filename directly
+and the viewer or player will be determined from the file type;
+you can leave the string empty on this case."
+  :group 'org-babel
+  :type '(list
+         (string :tag "Lilypond   ")
+         (string :tag "PDF Viewer ")
+         (string :tag "MIDI Player"))
+  :version "24.3"
+  :package-version '(Org . "8.2.7")
+  :set
+  (lambda (_symbol value)
+    (setq
+     org-babel-lilypond-ly-command   (nth 0 value)
+     org-babel-lilypond-pdf-command  (nth 1 value)
+     org-babel-lilypond-midi-command (nth 2 value))))
 
 (defvar org-babel-lilypond-gen-png nil
-  "Image generation (png) can be turned on by default by setting
-ORG-BABEL-LILYPOND-GEN-PNG to t")
+  "Non-nil means image generation (PNG) is turned on by default.")
 
 (defvar org-babel-lilypond-gen-svg nil
-  "Image generation (SVG) can be turned on by default by setting
-ORG-BABEL-LILYPOND-GEN-SVG to t")
+  "Non-nil means image generation (SVG) is be turned on by default.")
 
 (defvar org-babel-lilypond-gen-html nil
-  "HTML generation can be turned on by default by setting
-ORG-BABEL-LILYPOND-GEN-HTML to t")
+  "Non-nil means HTML generation is turned on by default.")
 
 (defvar org-babel-lilypond-gen-pdf nil
-  "PDF generation can be turned on by default by setting
-ORG-BABEL-LILYPOND-GEN-PDF to t")
+  "Non-nil means PDF generation is be turned on by default.")
 
 (defvar org-babel-lilypond-use-eps nil
-  "You can force the compiler to use the EPS backend by setting
-ORG-BABEL-LILYPOND-USE-EPS to t")
+  "Non-nil forces the compiler to use the EPS backend.")
 
 (defvar org-babel-lilypond-arrange-mode nil
-  "Arrange mode is turned on by setting ORG-BABEL-LILYPOND-ARRANGE-MODE
-to t.  In Arrange mode the following settings are altered
-from default...
+  "Non-nil turns Arrange mode on.
+In Arrange mode the following settings are altered from default:
 :tangle yes,    :noweb yes
 :results silent :comments yes.
 In addition lilypond block execution causes tangling of all lilypond
-blocks")
+blocks.")
 
 (defun org-babel-expand-body:lilypond (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (mapc
      (lambda (pair)
        (let ((name (symbol-name (car pair)))
@@ -138,9 +157,8 @@ specific arguments to =org-babel-tangle="
 
 (defun org-babel-lilypond-process-basic (body params)
   "Execute a lilypond block in basic mode."
-  (let* ((result-params (cdr (assoc :result-params params)))
-        (out-file (cdr (assoc :file params)))
-        (cmdline (or (cdr (assoc :cmdline params))
+  (let* ((out-file (cdr (assq :file params)))
+        (cmdline (or (cdr (assq :cmdline params))
                      ""))
         (in-file (org-babel-temp-file "lilypond-")))
 
@@ -148,7 +166,7 @@ specific arguments to =org-babel-tangle="
       (insert (org-babel-expand-body:generic body params)))
     (org-babel-eval
      (concat
-      (org-babel-lilypond-determine-ly-path)
+      org-babel-lilypond-ly-command
       " -dbackend=eps "
       "-dno-gs-load-fonts "
       "-dinclude-eps-fonts "
@@ -163,7 +181,7 @@ specific arguments to =org-babel-tangle="
       cmdline
       in-file) "")) nil)
 
-(defun org-babel-prep-session:lilypond (session params)
+(defun org-babel-prep-session:lilypond (_session _params)
   "Return an error because LilyPond exporter does not support sessions."
   (error "Sorry, LilyPond does not currently support sessions!"))
 
@@ -175,29 +193,27 @@ If error in compilation, attempt to mark the error in 
lilypond org file"
                             (buffer-file-name) ".lilypond"))
           (org-babel-lilypond-temp-file (org-babel-lilypond-switch-extension
                          (buffer-file-name) ".ly")))
-      (if (file-exists-p org-babel-lilypond-tangled-file)
-          (progn
-            (when (file-exists-p org-babel-lilypond-temp-file)
-              (delete-file org-babel-lilypond-temp-file))
-            (rename-file org-babel-lilypond-tangled-file
-                         org-babel-lilypond-temp-file))
-        (error "Error: Tangle Failed!") t)
+      (if (not (file-exists-p org-babel-lilypond-tangled-file))
+         (error "Error: Tangle Failed!")
+       (when (file-exists-p org-babel-lilypond-temp-file)
+         (delete-file org-babel-lilypond-temp-file))
+       (rename-file org-babel-lilypond-tangled-file
+                    org-babel-lilypond-temp-file))
       (switch-to-buffer-other-window "*lilypond*")
       (erase-buffer)
       (org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file)
       (goto-char (point-min))
-      (if (not (org-babel-lilypond-check-for-compile-error 
org-babel-lilypond-temp-file))
-          (progn
-            (other-window -1)
-            (org-babel-lilypond-attempt-to-open-pdf 
org-babel-lilypond-temp-file)
-            (org-babel-lilypond-attempt-to-play-midi 
org-babel-lilypond-temp-file))
-        (error "Error in Compilation!")))) nil)
+      (if (org-babel-lilypond-check-for-compile-error 
org-babel-lilypond-temp-file)
+         (error "Error in Compilation!")
+       (other-window -1)
+       (org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file)
+       (org-babel-lilypond-attempt-to-play-midi 
org-babel-lilypond-temp-file)))))
 
 (defun org-babel-lilypond-compile-lilyfile (file-name &optional test)
   "Compile lilypond file and check for compile errors
 FILE-NAME is full path to lilypond (.ly) file"
   (message "Compiling LilyPond...")
-  (let ((arg-1 (org-babel-lilypond-determine-ly-path)) ;program
+  (let ((arg-1 org-babel-lilypond-ly-command) ;program
         (arg-2 nil)                    ;infile
         (arg-3 "*lilypond*")           ;buffer
        (arg-4 t)                      ;display
@@ -223,11 +239,10 @@ FILE-NAME is full path to lilypond file.
 If TEST is t just return nil if no error found, and pass
 nil as file-name since it is unused in this context"
   (let ((is-error (search-forward "error:" nil t)))
-    (if (not test)
-        (if (not is-error)
-            nil
-          (org-babel-lilypond-process-compile-error file-name))
-      is-error)))
+    (if test
+       is-error
+      (when is-error
+       (org-babel-lilypond-process-compile-error file-name)))))
 
 (defun org-babel-lilypond-process-compile-error (file-name)
   "Process the compilation error that has occurred.
@@ -249,32 +264,26 @@ LINE is the erroneous line"
     (setq case-fold-search nil)
     (if (search-forward line nil t)
         (progn
-          (show-all)
+          (outline-show-all)
           (set-mark (point))
           (goto-char (- (point) (length line))))
       (goto-char temp))))
 
 (defun org-babel-lilypond-parse-line-num (&optional buffer)
   "Extract error line number."
-  (when buffer
-    (set-buffer buffer))
+  (when buffer (set-buffer buffer))
   (let ((start
          (and (search-backward ":" nil t)
               (search-backward ":" nil t)
               (search-backward ":" nil t)
-              (search-backward ":" nil t)))
-        (num nil))
-    (if start
-        (progn
-          (forward-char)
-          (let ((num (buffer-substring
-                      (+ 1 start)
-                      (- (search-forward ":" nil t) 1))))
-            (setq num (string-to-number num))
-            (if (numberp num)
-                num
-              nil)))
-      nil)))
+              (search-backward ":" nil t))))
+    (when start
+      (forward-char)
+      (let ((num (string-to-number
+                 (buffer-substring
+                  (+ 1 start)
+                  (- (search-forward ":" nil t) 1)))))
+       (and (numberp num) num)))))
 
 (defun org-babel-lilypond-parse-error-line (file-name lineNo)
   "Extract the erroneous line from the tangled .ly file
@@ -298,13 +307,13 @@ If TEST is non-nil, the shell command is returned and is 
not run"
     (let ((pdf-file (org-babel-lilypond-switch-extension file-name ".pdf")))
       (if (file-exists-p pdf-file)
           (let ((cmd-string
-                 (concat (org-babel-lilypond-determine-pdf-path) " " 
pdf-file)))
+                 (concat org-babel-lilypond-pdf-command " " pdf-file)))
             (if test
                 cmd-string
              (start-process
               "\"Audition pdf\""
               "*lilypond*"
-              (org-babel-lilypond-determine-pdf-path)
+              org-babel-lilypond-pdf-command
               pdf-file)))
        (message  "No pdf file generated so can't display!")))))
 
@@ -316,49 +325,16 @@ If TEST is non-nil, the shell command is returned and is 
not run"
     (let ((midi-file (org-babel-lilypond-switch-extension file-name ".midi")))
       (if (file-exists-p midi-file)
           (let ((cmd-string
-                 (concat (org-babel-lilypond-determine-midi-path) " " 
midi-file)))
+                 (concat org-babel-lilypond-midi-command " " midi-file)))
             (if test
                 cmd-string
               (start-process
                "\"Audition midi\""
                "*lilypond*"
-               (org-babel-lilypond-determine-midi-path)
+               org-babel-lilypond-midi-command
                midi-file)))
         (message "No midi file generated so can't play!")))))
 
-(defun org-babel-lilypond-determine-ly-path (&optional test)
-  "Return correct path to ly binary depending on OS
-If TEST is non-nil, it contains a simulation of the OS for test purposes"
-  (let ((sys-type
-         (or test system-type)))
-    (cond ((string= sys-type  "darwin")
-           org-babel-lilypond-OSX-ly-path)
-          ((string= sys-type "windows-nt")
-           org-babel-lilypond-w32-ly-path)
-          (t org-babel-lilypond-nix-ly-path))))
-
-(defun org-babel-lilypond-determine-pdf-path (&optional test)
-  "Return correct path to pdf viewer depending on OS
-If TEST is non-nil, it contains a simulation of the OS for test purposes"
-  (let ((sys-type
-         (or test system-type)))
-    (cond ((string= sys-type  "darwin")
-           org-babel-lilypond-OSX-pdf-path)
-          ((string= sys-type "windows-nt")
-           org-babel-lilypond-w32-pdf-path)
-          (t org-babel-lilypond-nix-pdf-path))))
-
-(defun org-babel-lilypond-determine-midi-path (&optional test)
-  "Return correct path to midi player depending on OS
-If TEST is non-nil, it contains a simulation of the OS for test purposes"
-  (let ((sys-type
-         (or test test system-type)))
-    (cond ((string= sys-type  "darwin")
-           org-babel-lilypond-OSX-midi-path)
-          ((string= sys-type "windows-nt")
-           org-babel-lilypond-w32-midi-path)
-          (t org-babel-lilypond-nix-midi-path))))
-
 (defun org-babel-lilypond-toggle-midi-play ()
   "Toggle whether midi will be played following a successful compilation."
   (interactive)
diff --git a/lisp/org/ob-lisp.el b/lisp/org/ob-lisp.el
index 2f66549..1e381d0 100644
--- a/lisp/org/ob-lisp.el
+++ b/lisp/org/ob-lisp.el
@@ -1,4 +1,4 @@
-;;; ob-lisp.el --- org-babel functions for common lisp evaluation
+;;; ob-lisp.el --- Babel Functions for Common Lisp   -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -25,17 +25,22 @@
 
 ;;; Commentary:
 
-;;; support for evaluating common lisp code, relies on slime for all eval
+;;; Support for evaluating Common Lisp code, relies on SLY or SLIME
+;;; for all eval.
 
 ;;; Requirements:
 
-;; Requires SLIME (Superior Lisp Interaction Mode for Emacs.)
-;; See http://common-lisp.net/project/slime/
+;; Requires SLY (Sylvester the Cat's Common Lisp IDE) or SLIME
+;; (Superior Lisp Interaction Mode for Emacs).  See:
+;; - https://github.com/capitaomorte/sly
+;; - http://common-lisp.net/project/slime/
 
 ;;; Code:
 (require 'ob)
 
+(declare-function sly-eval "ext:sly" (sexp &optional package))
 (declare-function slime-eval "ext:slime" (sexp &optional package))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("lisp" . "lisp"))
@@ -43,8 +48,16 @@
 (defvar org-babel-default-header-args:lisp '())
 (defvar org-babel-header-args:lisp '((package . :any)))
 
+(defcustom org-babel-lisp-eval-fn #'slime-eval
+  "The function to be called to evaluate code on the Lisp side.
+Valid values include `slime-eval' and `sly-eval'."
+  :group 'org-babel
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type 'function)
+
 (defcustom org-babel-lisp-dir-fmt
-  "(let ((*default-pathname-defaults* #P%S)) %%s)"
+  "(let ((*default-pathname-defaults* #P%S\n)) %%s\n)"
   "Format string used to wrap code bodies to set the current directory.
 For example a value of \"(progn ;; %s\\n   %%s)\" would ignore the
 current directory string."
@@ -54,49 +67,54 @@ current directory string."
 
 (defun org-babel-expand-body:lisp (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-        (result-params (cdr (assoc :result-params params)))
+  (let* ((vars (org-babel--get-vars params))
+        (result-params (cdr (assq :result-params params)))
         (print-level nil) (print-length nil)
-        (body (org-babel-trim
-               (if (> (length vars) 0)
-                   (concat "(let ("
-                           (mapconcat
-                            (lambda (var)
-                              (format "(%S (quote %S))" (car var) (cdr var)))
-                            vars "\n      ")
-                           ")\n" body ")")
-                 body))))
+        (body (if (null vars) (org-trim body)
+                (concat "(let ("
+                        (mapconcat
+                         (lambda (var)
+                           (format "(%S (quote %S))" (car var) (cdr var)))
+                         vars "\n      ")
+                        ")\n" body ")"))))
     (if (or (member "code" result-params)
            (member "pp" result-params))
        (format "(pprint %s)" body)
       body)))
 
 (defun org-babel-execute:lisp (body params)
-  "Execute a block of Common Lisp code with Babel."
-  (require 'slime)
+  "Execute a block of Common Lisp code with Babel.
+BODY is the contents of the block, as a string.  PARAMS is
+a property list containing the parameters of the block."
+  (require (pcase org-babel-lisp-eval-fn
+            (`slime-eval 'slime)
+            (`sly-eval 'sly)))
   (org-babel-reassemble-table
    (let ((result
-          (with-temp-buffer
-            (insert (org-babel-expand-body:lisp body params))
-            (slime-eval `(swank:eval-and-grab-output
-                          ,(let ((dir (if (assoc :dir params)
-                                          (cdr (assoc :dir params))
-                                        default-directory)))
-                             (format
-                              (if dir (format org-babel-lisp-dir-fmt dir)
-                                "(progn %s)")
-                              (buffer-substring-no-properties
-                               (point-min) (point-max)))))
-                        (cdr (assoc :package params))))))
-     (org-babel-result-cond (cdr (assoc :result-params params))
-       (car result)
+          (funcall (if (member "output" (cdr (assq :result-params params)))
+                       #'car #'cadr)
+                   (with-temp-buffer
+                     (insert (org-babel-expand-body:lisp body params))
+                     (funcall org-babel-lisp-eval-fn
+                              `(swank:eval-and-grab-output
+                                ,(let ((dir (if (assq :dir params)
+                                                (cdr (assq :dir params))
+                                              default-directory)))
+                                   (format
+                                    (if dir (format org-babel-lisp-dir-fmt dir)
+                                      "(progn %s\n)")
+                                    (buffer-substring-no-properties
+                                     (point-min) (point-max)))))
+                              (cdr (assq :package params)))))))
+     (org-babel-result-cond (cdr (assq :result-params params))
+       result
        (condition-case nil
-           (read (org-babel-lisp-vector-to-list (cadr result)))
-         (error (cadr result)))))
-   (org-babel-pick-name (cdr (assoc :colname-names params))
-                       (cdr (assoc :colnames params)))
-   (org-babel-pick-name (cdr (assoc :rowname-names params))
-                       (cdr (assoc :rownames params)))))
+           (read (org-babel-lisp-vector-to-list result))
+         (error result))))
+   (org-babel-pick-name (cdr (assq :colname-names params))
+                       (cdr (assq :colnames params)))
+   (org-babel-pick-name (cdr (assq :rowname-names params))
+                       (cdr (assq :rownames params)))))
 
 (defun org-babel-lisp-vector-to-list (results)
   ;; TODO: better would be to replace #(...) with [...]
diff --git a/lisp/org/ob-lob.el b/lisp/org/ob-lob.el
index ddfac2a..b6f50d3 100644
--- a/lisp/org/ob-lob.el
+++ b/lisp/org/ob-lob.el
@@ -1,4 +1,4 @@
-;;; ob-lob.el --- functions supporting the Library of Babel
+;;; ob-lob.el --- Functions Supporting the Library of Babel -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -23,27 +23,27 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Code:
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'ob-core)
 (require 'ob-table)
 
-(declare-function org-babel-in-example-or-verbatim "ob-exp" nil)
+(declare-function org-babel-ref-split-args "ob-ref" (arg-string))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
 
 (defvar org-babel-library-of-babel nil
   "Library of source-code blocks.
-This is an association list.  Populate the library by adding
-files to `org-babel-lob-files'.")
-
-(defcustom org-babel-lob-files nil
-  "Files used to populate the `org-babel-library-of-babel'.
-To add files to this list use the `org-babel-lob-ingest' command."
-  :group 'org-babel
-  :version "24.1"
-  :type '(repeat file))
+This is an association list.  Populate the library by calling
+`org-babel-lob-ingest' on files containing source blocks.")
 
 (defvar org-babel-default-lob-header-args '((:exports . "results"))
-  "Default header arguments to use when exporting #+lob/call lines.")
+  "Default header arguments to use when exporting Babel calls.
+By default, a Babel call inherits its arguments from the source
+block being called.  Header arguments defined in this variable
+take precedence over these.  It is useful for properties that
+should not be inherited from a source block.")
 
 (defun org-babel-lob-ingest (&optional file)
   "Add all named source blocks defined in FILE to 
`org-babel-library-of-babel'."
@@ -62,24 +62,7 @@ To add files to this list use the `org-babel-lob-ingest' 
command."
             lob-ingest-count (if (> lob-ingest-count 1) "s" ""))
     lob-ingest-count))
 
-(defconst org-babel-block-lob-one-liner-regexp
-  (concat
-   "^\\([ \t]*?\\)#\\+call:[ \t]+\\([^()\n]+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)"
-   "(\\([^\n]*?\\))\\(\\[.+\\]\\|\\)[ \t]*\\(\\([^\n]*\\)\\)?")
-  "Regexp to match non-inline calls to predefined source block functions.")
-
-(defconst org-babel-inline-lob-one-liner-regexp
-  (concat
-   "\\([^\n]*?\\)call_\\([^()\n]+?\\)\\(\\[\\(.*?\\)\\]\\|\\(\\)\\)"
-   "(\\([^\n]*?\\))\\(\\[\\(.*?\\)\\]\\)?")
-  "Regexp to match inline calls to predefined source block functions.")
-
-(defconst org-babel-lob-one-liner-regexp
-  (concat "\\(" org-babel-block-lob-one-liner-regexp
-         "\\|" org-babel-inline-lob-one-liner-regexp "\\)")
-  "Regexp to match calls to predefined source block functions.")
-
-;; functions for executing lob one-liners
+;; Functions for executing lob one-liners.
 
 ;;;###autoload
 (defun org-babel-lob-execute-maybe ()
@@ -88,72 +71,76 @@ Detect if this is context for a Library Of Babel source 
block and
 if so then run the appropriate source block from the Library."
   (interactive)
   (let ((info (org-babel-lob-get-info)))
-    (if (and (nth 0 info) (not (org-babel-in-example-or-verbatim)))
-       (progn (org-babel-lob-execute info) t)
-      nil)))
+    (when info
+      (org-babel-execute-src-block nil info)
+      t)))
+
+(defun org-babel-lob--src-info (name)
+  "Return internal representation for Babel data named NAME.
+NAME is a string.  This function looks into the current document
+for a Babel call or source block.  If none is found, it looks
+after NAME in the Library of Babel.  Eventually, if that also
+fails, it returns nil."
+  ;; During export, look into the pristine copy of the document being
+  ;; exported instead of the current one, which could miss some data.
+  (with-current-buffer (or org-babel-exp-reference-buffer (current-buffer))
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (catch :found
+       (let ((case-fold-search t)
+            (regexp (org-babel-named-data-regexp-for-name name)))
+        (while (re-search-forward regexp nil t)
+          (let ((element (org-element-at-point)))
+            (when (equal name (org-element-property :name element))
+              (throw :found
+                     (pcase (org-element-type element)
+                       (`src-block (org-babel-get-src-block-info t element))
+                       (`babel-call (org-babel-lob-get-info element))
+                       ;; Non-executable data found.  Since names are
+                       ;; supposed to be unique throughout a document,
+                       ;; bail out.
+                       (_ nil))))))
+        ;; No element named NAME in buffer.  Try Library of Babel.
+        (cdr (assoc-string name org-babel-library-of-babel)))))))
 
 ;;;###autoload
-(defun org-babel-lob-get-info ()
-  "Return a Library of Babel function call as a string."
-  (let ((case-fold-search t)
-       (nonempty (lambda (a b)
-                   (let ((it (match-string a)))
-                     (if (= (length it) 0) (match-string b) it)))))
-    (save-excursion
-      (beginning-of-line 1)
-      (when (looking-at org-babel-lob-one-liner-regexp)
-       (append
-        (mapcar #'org-no-properties
-                (list
-                 (format "%s%s(%s)%s"
-                         (funcall nonempty 3 12)
-                         (if (not (= 0 (length (funcall nonempty 5 14))))
-                             (concat "[" (funcall nonempty 5 14) "]") "")
-                         (or (funcall nonempty 7 16) "")
-                         (or (funcall nonempty 8 19) ""))
-                 (funcall nonempty 9 18)))
-        (list (length (if (= (length (match-string 12)) 0)
-                          (match-string 2) (match-string 11)))
-              (save-excursion
-                (forward-line -1)
-                (and (looking-at (concat org-babel-src-name-regexp
-                                         "\\([^\n]*\\)$"))
-                     (org-no-properties (match-string 1))))))))))
-
-(defvar org-babel-default-header-args:emacs-lisp) ; Defined in ob-emacs-lisp.el
-(defun org-babel-lob-execute (info)
-  "Execute the lob call specified by INFO."
-  (let* ((mkinfo (lambda (p)
-                  (list "emacs-lisp" "results" p nil
-                        (nth 3 info) ;; name
-                        (nth 2 info))))
-        (pre-params (apply #'org-babel-merge-params
-                           org-babel-default-header-args
-                           org-babel-default-header-args:emacs-lisp
-                           (append
-                            (org-babel-params-from-properties)
-                            (list
-                             (org-babel-parse-header-arguments
-                              (org-no-properties
-                               (concat
-                                ":var results="
-                                (mapconcat #'identity (butlast info 2)
-                                           " "))))))))
-        (pre-info (funcall mkinfo pre-params))
-        (cache-p (and (cdr (assoc :cache pre-params))
-                      (string= "yes" (cdr (assoc :cache pre-params)))))
-        (new-hash (when cache-p (org-babel-sha1-hash pre-info)))
-        (old-hash (when cache-p (org-babel-current-result-hash)))
-        (org-babel-current-src-block-location (point-marker)))
-    (if (and cache-p (equal new-hash old-hash))
-       (save-excursion (goto-char (org-babel-where-is-src-block-result))
-                       (forward-line 1)
-                       (message "%S" (org-babel-read-result)))
-      (prog1 (let* ((proc-params (org-babel-process-params pre-params))
-                    org-confirm-babel-evaluate)
-              (org-babel-execute-src-block nil (funcall mkinfo proc-params)))
-       ;; update the hash
-       (when new-hash (org-babel-set-current-result-hash new-hash))))))
+(defun org-babel-lob-get-info (&optional datum)
+  "Return internal representation for Library of Babel function call.
+Consider DATUM, when provided, or element at point.  Return nil
+when not on an appropriate location.  Otherwise return a list
+compatible with `org-babel-get-src-block-info', which see."
+  (let* ((context (or datum (org-element-context)))
+        (type (org-element-type context)))
+    (when (memq type '(babel-call inline-babel-call))
+      (pcase (org-babel-lob--src-info (org-element-property :call context))
+       (`(,language ,body ,header ,_ ,_ ,_ ,coderef)
+        (let ((begin (org-element-property (if (eq type 'inline-babel-call)
+                                               :begin
+                                             :post-affiliated)
+                                           context)))
+          (list language
+                body
+                (apply #'org-babel-merge-params
+                       header
+                       org-babel-default-lob-header-args
+                       (append
+                        (org-with-wide-buffer
+                         (goto-char begin)
+                         (org-babel-params-from-properties language))
+                        (list
+                         (org-babel-parse-header-arguments
+                          (org-element-property :inside-header context))
+                         (let ((args (org-element-property :arguments 
context)))
+                           (and args
+                                (mapcar (lambda (ref) (cons :var ref))
+                                        (org-babel-ref-split-args args))))
+                         (org-babel-parse-header-arguments
+                          (org-element-property :end-header context)))))
+                nil
+                (org-element-property :name context)
+                begin
+                coderef)))
+       (_ nil)))))
 
 (provide 'ob-lob)
 
diff --git a/lisp/org/ob-lua.el b/lisp/org/ob-lua.el
new file mode 100644
index 0000000..fa60b0e
--- /dev/null
+++ b/lisp/org/ob-lua.el
@@ -0,0 +1,403 @@
+;;; ob-lua.el --- Org Babel functions for Lua evaluation -*- lexical-binding: 
t; -*-
+
+;; Copyright (C) 2014, 2016, 2017 Free Software Foundation, Inc.
+
+;; Authors: Dieter Schoen
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;; Requirements:
+;; for session support, lua-mode is needed.
+;; lua-mode is not part of GNU Emacs/orgmode, but can be obtained
+;; from marmalade or melpa.
+;; The source respository is here:
+;; https://github.com/immerrr/lua-mode
+
+;; However, sessions are not yet working.
+
+;; Org-Babel support for evaluating lua source code.
+
+;;; Code:
+(require 'ob)
+(require 'cl-lib)
+
+(declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function lua-shell "ext:lua-mode" (&optional argprompt))
+(declare-function lua-toggle-shells "ext:lua-mode" (arg))
+(declare-function run-lua "ext:lua" (cmd &optional dedicated show))
+
+(defvar org-babel-tangle-lang-exts)
+(add-to-list 'org-babel-tangle-lang-exts '("lua" . "lua"))
+
+(defvar org-babel-default-header-args:lua '())
+
+(defcustom org-babel-lua-command "lua"
+  "Name of the command for executing Lua code."
+  :version "24.5"
+  :package-version '(Org . "8.3")
+  :group 'org-babel
+  :type 'string)
+
+(defcustom org-babel-lua-mode 'lua-mode
+  "Preferred lua mode for use in running lua interactively.
+This will typically be 'lua-mode."
+  :group 'org-babel
+  :version "24.5"
+  :package-version '(Org . "8.3")
+  :type 'symbol)
+
+(defcustom org-babel-lua-hline-to "None"
+  "Replace hlines in incoming tables with this when translating to lua."
+  :group 'org-babel
+  :version "24.5"
+  :package-version '(Org . "8.3")
+  :type 'string)
+
+(defcustom org-babel-lua-None-to 'hline
+  "Replace 'None' in lua tables with this before returning."
+  :group 'org-babel
+  :version "24.5"
+  :package-version '(Org . "8.3")
+  :type 'symbol)
+
+(defun org-babel-execute:lua (body params)
+  "Execute a block of Lua code with Babel.
+This function is called by `org-babel-execute-src-block'."
+  (let* ((session (org-babel-lua-initiate-session
+                  (cdr (assq :session params))))
+         (result-params (cdr (assq :result-params params)))
+         (result-type (cdr (assq :result-type params)))
+        (return-val (when (and (eq result-type 'value) (not session))
+                      (cdr (assq :return params))))
+        (preamble (cdr (assq :preamble params)))
+         (full-body
+         (org-babel-expand-body:generic
+          (concat body (if return-val (format "\nreturn %s" return-val) ""))
+          params (org-babel-variable-assignments:lua params)))
+         (result (org-babel-lua-evaluate
+                 session full-body result-type result-params preamble)))
+    (org-babel-reassemble-table
+     result
+     (org-babel-pick-name (cdr (assq :colname-names params))
+                         (cdr (assq :colnames params)))
+     (org-babel-pick-name (cdr (assq :rowname-names params))
+                         (cdr (assq :rownames params))))))
+
+(defun org-babel-prep-session:lua (session params)
+  "Prepare SESSION according to the header arguments in PARAMS.
+VARS contains resolved variable references"
+  (let* ((session (org-babel-lua-initiate-session session))
+        (var-lines
+         (org-babel-variable-assignments:lua params)))
+    (org-babel-comint-in-buffer session
+      (mapc (lambda (var)
+              (end-of-line 1) (insert var) (comint-send-input)
+              (org-babel-comint-wait-for-output session)) var-lines))
+    session))
+
+(defun org-babel-load-session:lua (session body params)
+  "Load BODY into SESSION."
+  (save-window-excursion
+    (let ((buffer (org-babel-prep-session:lua session params)))
+      (with-current-buffer buffer
+        (goto-char (process-mark (get-buffer-process (current-buffer))))
+        (insert (org-babel-chomp body)))
+      buffer)))
+
+;; helper functions
+
+(defun org-babel-variable-assignments:lua (params)
+  "Return a list of Lua statements assigning the block's variables."
+  (mapcar
+   (lambda (pair)
+     (format "%s=%s"
+            (car pair)
+            (org-babel-lua-var-to-lua (cdr pair))))
+   (org-babel--get-vars params)))
+
+(defun org-babel-lua-var-to-lua (var)
+  "Convert an elisp value to a lua variable.
+Convert an elisp value, VAR, into a string of lua source code
+specifying a variable of the same value."
+  (if (listp var)
+      (if (and (= 1 (length var)) (not (listp (car var))))
+          (org-babel-lua-var-to-lua (car var))
+        (if (and
+             (= 2 (length var))
+             (not (listp (car var))))
+            (concat
+             (substring-no-properties (car var))
+             "="
+             (org-babel-lua-var-to-lua (cdr var)))
+          (concat "{" (mapconcat #'org-babel-lua-var-to-lua var ", ") "}")))
+    (if (eq var 'hline)
+        org-babel-lua-hline-to
+      (format
+       (if (and (stringp var) (string-match "[\n\r]" var)) "\"\"%S\"\"" "%S")
+       (if (stringp var) (substring-no-properties var) var)))))
+
+(defun org-babel-lua-table-or-string (results)
+  "Convert RESULTS into an appropriate elisp value.
+If the results look like a list or tuple, then convert them into an
+Emacs-lisp table, otherwise return the results as a string."
+  (let ((res (org-babel-script-escape results)))
+    (if (listp res)
+        (mapcar (lambda (el) (if (eq el 'None)
+                                org-babel-lua-None-to el))
+                res)
+      res)))
+
+(defvar org-babel-lua-buffers '((:default . "*Lua*")))
+
+(defun org-babel-lua-session-buffer (session)
+  "Return the buffer associated with SESSION."
+  (cdr (assoc session org-babel-lua-buffers)))
+
+(defun org-babel-lua-with-earmuffs (session)
+  (let ((name (if (stringp session) session (format "%s" session))))
+    (if (and (string= "*" (substring name 0 1))
+            (string= "*" (substring name (- (length name) 1))))
+       name
+      (format "*%s*" name))))
+
+(defun org-babel-lua-without-earmuffs (session)
+  (let ((name (if (stringp session) session (format "%s" session))))
+    (if (and (string= "*" (substring name 0 1))
+            (string= "*" (substring name (- (length name) 1))))
+       (substring name 1 (- (length name) 1))
+      name)))
+
+(defvar lua-default-interpreter)
+(defvar lua-which-bufname)
+(defvar lua-shell-buffer-name)
+(defun org-babel-lua-initiate-session-by-key (&optional session)
+  "Initiate a lua session.
+If there is not a current inferior-process-buffer in SESSION
+then create.  Return the initialized session."
+  ;; (require org-babel-lua-mode)
+  (save-window-excursion
+    (let* ((session (if session (intern session) :default))
+           (lua-buffer (org-babel-lua-session-buffer session))
+          ;; (cmd (if (member system-type '(cygwin windows-nt ms-dos))
+          ;;       (concat org-babel-lua-command " -i")
+          ;;     org-babel-lua-command))
+          )
+      (cond
+       ((and (eq 'lua-mode org-babel-lua-mode)
+             (fboundp 'lua-start-process)) ; lua-mode.el
+        ;; Make sure that lua-which-bufname is initialized, as otherwise
+        ;; it will be overwritten the first time a Lua buffer is
+        ;; created.
+        ;;(lua-toggle-shells lua-default-interpreter)
+        ;; `lua-shell' creates a buffer whose name is the value of
+        ;; `lua-which-bufname' with '*'s at the beginning and end
+        (let* ((bufname (if (and lua-buffer (buffer-live-p lua-buffer))
+                            (replace-regexp-in-string ;; zap surrounding *
+                             "^\\*\\([^*]+\\)\\*$" "\\1" (buffer-name 
lua-buffer))
+                          (concat "Lua-" (symbol-name session))))
+               (lua-which-bufname bufname))
+          (lua-start-process)
+          (setq lua-buffer (org-babel-lua-with-earmuffs bufname))))
+       (t
+       (error "No function available for running an inferior Lua")))
+      (setq org-babel-lua-buffers
+            (cons (cons session lua-buffer)
+                  (assq-delete-all session org-babel-lua-buffers)))
+      session)))
+
+(defun org-babel-lua-initiate-session (&optional session _params)
+  "Create a session named SESSION according to PARAMS."
+  (unless (string= session "none")
+    (error "Sessions currently not supported, work in progress")
+    (org-babel-lua-session-buffer
+     (org-babel-lua-initiate-session-by-key session))))
+
+(defvar org-babel-lua-eoe-indicator "--eoe"
+  "A string to indicate that evaluation has completed.")
+
+(defvar org-babel-lua-wrapper-method
+  "
+function main()
+%s
+end
+
+fd=io.open(\"%s\", \"w\")
+fd:write( main() )
+fd:close()")
+(defvar org-babel-lua-pp-wrapper-method
+  "
+-- table to string
+function t2s(t, indent)
+   if indent == nil then
+      indent = \"\"
+   end
+   if type(t) == \"table\" then
+      ts = \"\"
+      for k,v in pairs(t) do
+         if type(v) == \"table\" then
+            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \\n\" ..
+               t2s(v, indent .. \"  \")
+         else
+            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \" ..
+               t2s(v, indent .. \"  \") .. \"\\n\"
+         end
+      end
+      return ts
+   else
+      return tostring(t)
+   end
+end
+
+
+function main()
+%s
+end
+
+fd=io.open(\"%s\", \"w\")
+fd:write(t2s(main()))
+fd:close()")
+
+(defun org-babel-lua-evaluate
+    (session body &optional result-type result-params preamble)
+  "Evaluate BODY as Lua code."
+  (if session
+      (org-babel-lua-evaluate-session
+       session body result-type result-params)
+    (org-babel-lua-evaluate-external-process
+     body result-type result-params preamble)))
+
+(defun org-babel-lua-evaluate-external-process
+    (body &optional result-type result-params preamble)
+  "Evaluate BODY in external lua process.
+If RESULT-TYPE equals 'output then return standard output as a
+string.  If RESULT-TYPE equals 'value then return the value of the
+last statement in BODY, as elisp."
+  (let ((raw
+         (pcase result-type
+           (`output (org-babel-eval org-babel-lua-command
+                                   (concat (if preamble (concat preamble "\n"))
+                                           body)))
+           (`value (let ((tmp-file (org-babel-temp-file "lua-")))
+                    (org-babel-eval
+                     org-babel-lua-command
+                     (concat
+                      (if preamble (concat preamble "\n") "")
+                      (format
+                       (if (member "pp" result-params)
+                           org-babel-lua-pp-wrapper-method
+                         org-babel-lua-wrapper-method)
+                       (mapconcat
+                        (lambda (line) (format "\t%s" line))
+                        (split-string
+                         (org-remove-indentation
+                          (org-trim body))
+                         "[\r\n]") "\n")
+                       (org-babel-process-file-name tmp-file 'noquote))))
+                    (org-babel-eval-read-file tmp-file))))))
+    (org-babel-result-cond result-params
+      raw
+      (org-babel-lua-table-or-string (org-trim raw)))))
+
+(defun org-babel-lua-evaluate-session
+    (session body &optional result-type result-params)
+  "Pass BODY to the Lua process in SESSION.
+If RESULT-TYPE equals 'output then return standard output as a
+string.  If RESULT-TYPE equals 'value then return the value of the
+last statement in BODY, as elisp."
+  (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
+        (dump-last-value
+         (lambda
+           (tmp-file pp)
+           (mapc
+            (lambda (statement) (insert statement) (funcall send-wait))
+            (if pp
+                (list
+                 "-- table to string
+function t2s(t, indent)
+   if indent == nil then
+      indent = \"\"
+   end
+   if type(t) == \"table\" then
+      ts = \"\"
+      for k,v in pairs(t) do
+         if type(v) == \"table\" then
+            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \\n\" ..
+               t2s(v, indent .. \"  \")
+         else
+            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \" ..
+               t2s(v, indent .. \"  \") .. \"\\n\"
+         end
+      end
+      return ts
+   else
+      return tostring(t)
+   end
+end
+"
+                 (concat "fd:write(_))
+fd:close()"
+                         (org-babel-process-file-name tmp-file 'noquote)))
+              (list (format "fd=io.open(\"%s\", \"w\")
+fd:write( _ )
+fd:close()"
+                            (org-babel-process-file-name tmp-file
+                                                          'noquote)))))))
+        (input-body (lambda (body)
+                      (mapc (lambda (line) (insert line) (funcall send-wait))
+                            (split-string body "[\r\n]"))
+                      (funcall send-wait)))
+         (results
+          (pcase result-type
+            (`output
+             (mapconcat
+              #'org-trim
+              (butlast
+               (org-babel-comint-with-output
+                   (session org-babel-lua-eoe-indicator t body)
+                 (funcall input-body body)
+                 (funcall send-wait) (funcall send-wait)
+                 (insert org-babel-lua-eoe-indicator)
+                 (funcall send-wait))
+               2) "\n"))
+            (`value
+             (let ((tmp-file (org-babel-temp-file "lua-")))
+               (org-babel-comint-with-output
+                   (session org-babel-lua-eoe-indicator nil body)
+                 (let ((comint-process-echoes nil))
+                   (funcall input-body body)
+                   (funcall dump-last-value tmp-file
+                            (member "pp" result-params))
+                   (funcall send-wait) (funcall send-wait)
+                   (insert org-babel-lua-eoe-indicator)
+                   (funcall send-wait)))
+               (org-babel-eval-read-file tmp-file))))))
+    (unless (string= (substring org-babel-lua-eoe-indicator 1 -1) results)
+      (org-babel-result-cond result-params
+       results
+        (org-babel-lua-table-or-string results)))))
+
+(defun org-babel-lua-read-string (string)
+  "Strip 's from around Lua string."
+  (org-unbracket-string "'" "'" string))
+
+(provide 'ob-lua)
+
+
+
+;;; ob-lua.el ends here
diff --git a/lisp/org/ob-makefile.el b/lisp/org/ob-makefile.el
index a292800..2aa04fd 100644
--- a/lisp/org/ob-makefile.el
+++ b/lisp/org/ob-makefile.el
@@ -1,4 +1,4 @@
-;;; ob-makefile.el --- org-babel functions for makefile evaluation
+;;; ob-makefile.el --- Babel Functions for Makefile  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -24,19 +24,19 @@
 
 ;;; Commentary:
 
-;; This file exists solely for tangling a Makefile from org-mode files.
+;; This file exists solely for tangling a Makefile from Org files.
 
 ;;; Code:
 (require 'ob)
 
 (defvar org-babel-default-header-args:makefile '())
 
-(defun org-babel-execute:makefile (body params)
+(defun org-babel-execute:makefile (body _params)
   "Execute a block of makefile code.
 This function is called by `org-babel-execute-src-block'."
   body)
 
-(defun org-babel-prep-session:makefile (session params)
+(defun org-babel-prep-session:makefile (_session _params)
   "Return an error if the :session header argument is set.  Make
 does not support sessions."
   (error "Makefile sessions are nonsensical"))
diff --git a/lisp/org/ob-matlab.el b/lisp/org/ob-matlab.el
index 42bbd2b..23cfa36 100644
--- a/lisp/org/ob-matlab.el
+++ b/lisp/org/ob-matlab.el
@@ -1,4 +1,4 @@
-;;; ob-matlab.el --- org-babel support for matlab evaluation
+;;; ob-matlab.el --- Babel support for Matlab        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
diff --git a/lisp/org/ob-maxima.el b/lisp/org/ob-maxima.el
index b567fd4..0a4d835 100644
--- a/lisp/org/ob-maxima.el
+++ b/lisp/org/ob-maxima.el
@@ -1,4 +1,4 @@
-;;; ob-maxima.el --- org-babel functions for maxima evaluation
+;;; ob-maxima.el --- Babel Functions for Maxima      -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -48,11 +48,11 @@
 
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (mapconcat 'identity
               (list
                ;; graphic output
-               (let ((graphic-file (org-babel-maxima-graphical-output-file 
params)))
+               (let ((graphic-file (ignore-errors 
(org-babel-graphical-output-file params))))
                  (if graphic-file
                      (format
                       "set_plot_option ([gnuplot_term, png]); set_plot_option 
([gnuplot_out_file, %S]);"
@@ -69,9 +69,9 @@
   "Execute a block of Maxima entries with org-babel.
 This function is called by `org-babel-execute-src-block'."
   (message "executing Maxima source code block")
-  (let ((result-params (split-string (or (cdr (assoc :results params)) "")))
+  (let ((result-params (split-string (or (cdr (assq :results params)) "")))
        (result
-        (let* ((cmdline (or (cdr (assoc :cmdline params)) ""))
+        (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
                (in-file (org-babel-temp-file "maxima-" ".max"))
                (cmd (format "%s --very-quiet -r 'batchload(%S)$' %s"
                             org-babel-maxima-command in-file cmdline)))
@@ -89,7 +89,7 @@ This function is called by `org-babel-execute-src-block'."
                                           (= 0 (length line)))
                                 line))
                             (split-string raw "[\r\n]"))) "\n")))))
-    (if (org-babel-maxima-graphical-output-file params)
+    (if (ignore-errors (org-babel-graphical-output-file params))
        nil
       (org-babel-result-cond result-params
        result
@@ -98,7 +98,7 @@ This function is called by `org-babel-execute-src-block'."
          (org-babel-import-elisp-from-file tmp-file))))))
 
 
-(defun org-babel-prep-session:maxima (session params)
+(defun org-babel-prep-session:maxima (_session _params)
   (error "Maxima does not support sessions"))
 
 (defun org-babel-maxima-var-to-maxima (pair)
@@ -113,11 +113,6 @@ of the same value."
     (format "%S: %s$" var
            (org-babel-maxima-elisp-to-maxima val))))
 
-(defun org-babel-maxima-graphical-output-file (params)
-  "Name of file to which maxima should send graphical output."
-  (and (member "graphics" (cdr (assq :result-params params)))
-       (cdr (assq :file params))))
-
 (defun org-babel-maxima-elisp-to-maxima (val)
   "Return a string of maxima code which evaluates to VAL."
   (if (listp val)
diff --git a/lisp/org/ob-mscgen.el b/lisp/org/ob-mscgen.el
index b764475..5c9dccc 100644
--- a/lisp/org/ob-mscgen.el
+++ b/lisp/org/ob-mscgen.el
@@ -1,4 +1,4 @@
-;;; ob-msc.el --- org-babel functions for mscgen evaluation
+;;; ob-msc.el --- Babel Functions for Mscgen         -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -65,15 +65,15 @@
 This function is called by `org-babel-execute-src-block'.
 Default filetype is png.  Modify by setting :filetype parameter to
 mscgen supported formats."
-  (let* ((out-file (or (cdr (assoc :file params)) "output.png" ))
-         (filetype (or (cdr (assoc :filetype params)) "png" )))
-    (unless (cdr (assoc :file params))
+  (let* ((out-file (or (cdr (assq :file params)) "output.png" ))
+         (filetype (or (cdr (assq :filetype params)) "png" )))
+    (unless (cdr (assq :file params))
       (error "
 ERROR: no output file specified.  Add \":file name.png\" to the src header"))
     (org-babel-eval (concat "mscgen -T " filetype " -o " out-file) body)
     nil)) ;; signal that output has already been written to file
 
-(defun org-babel-prep-session:mscgen (session params)
+(defun org-babel-prep-session:mscgen (_session _params)
   "Raise an error because Mscgen doesn't support sessions."
   (error "Mscgen does not support sessions"))
 
diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el
index 31f0d01..7997ff0 100644
--- a/lisp/org/ob-ocaml.el
+++ b/lisp/org/ob-ocaml.el
@@ -1,4 +1,4 @@
-;;; ob-ocaml.el --- org-babel functions for ocaml evaluation
+;;; ob-ocaml.el --- Babel Functions for Ocaml        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -37,11 +37,11 @@
 ;;; Code:
 (require 'ob)
 (require 'comint)
-(eval-when-compile (require 'cl))
 
 (declare-function tuareg-run-caml "ext:tuareg" ())
 (declare-function tuareg-run-ocaml "ext:tuareg" ())
 (declare-function tuareg-interactive-send-input "ext:tuareg" ())
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("ocaml" . "ml"))
@@ -60,17 +60,17 @@
 
 (defun org-babel-execute:ocaml (body params)
   "Execute a block of Ocaml code with Babel."
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-         (full-body (org-babel-expand-body:generic
+  (let* ((full-body (org-babel-expand-body:generic
                     body params
                     (org-babel-variable-assignments:ocaml params)))
          (session (org-babel-prep-session:ocaml
-                  (cdr (assoc :session params)) params))
+                  (cdr (assq :session params)) params))
          (raw (org-babel-comint-with-output
-                 (session org-babel-ocaml-eoe-output t full-body)
+                 (session org-babel-ocaml-eoe-output nil full-body)
                (insert
                 (concat
-                 (org-babel-chomp 
full-body)";;\n"org-babel-ocaml-eoe-indicator))
+                 (org-babel-chomp full-body) ";;\n"
+                 org-babel-ocaml-eoe-indicator))
                (tuareg-interactive-send-input)))
         (clean
          (car (let ((re (regexp-quote org-babel-ocaml-eoe-output)) out)
@@ -79,23 +79,31 @@
                                         (progn (setq out nil) line)
                                       (when (string-match re line)
                                         (progn (setq out t) nil))))
-                                  (mapcar #'org-babel-trim (reverse raw))))))))
-    (org-babel-reassemble-table
-     (let ((raw (org-babel-trim clean))
-          (result-params (cdr (assoc :result-params params))))
+                                  (mapcar #'org-trim (reverse raw)))))))
+        (raw (org-trim clean))
+        (result-params (cdr (assq :result-params params))))
+    (string-match
+     "\\(\\(.*\n\\)*\\)[^:\n]+ : \\([^=\n]+\\) =\\(\n\\| \\)\\(.+\\)$"
+     raw)
+    (let ((output (match-string 1 raw))
+         (type (match-string 3 raw))
+         (value (match-string 5 raw)))
+      (org-babel-reassemble-table
        (org-babel-result-cond result-params
-        ;; strip type information from output unless verbatim is specified
-        (if (and (not (member "verbatim" result-params))
-                 (string-match "= \\(.+\\)$" raw))
-            (match-string 1 raw) raw)
-        (org-babel-ocaml-parse-output raw)))
-     (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
-     (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
+        (cond
+         ((member "verbatim" result-params) raw)
+         ((member "output" result-params) output)
+         (t raw))
+        (if (and value type)
+            (org-babel-ocaml-parse-output value type)
+          raw))
+       (org-babel-pick-name
+       (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+       (org-babel-pick-name
+       (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
 
 (defvar tuareg-interactive-buffer-name)
-(defun org-babel-prep-session:ocaml (session params)
+(defun org-babel-prep-session:ocaml (session _params)
   "Prepare SESSION according to the header arguments in PARAMS."
   (require 'tuareg)
   (let ((tuareg-interactive-buffer-name (if (and (not (string= session "none"))
@@ -113,7 +121,7 @@
   (mapcar
    (lambda (pair) (format "let %s = %s;;" (car pair)
                          (org-babel-ocaml-elisp-to-ocaml (cdr pair))))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 (defun org-babel-ocaml-elisp-to-ocaml (val)
   "Return a string of ocaml code which evaluates to VAL."
@@ -121,26 +129,29 @@
       (concat "[|" (mapconcat #'org-babel-ocaml-elisp-to-ocaml val "; ") "|]")
     (format "%S" val)))
 
-(defun org-babel-ocaml-parse-output (output)
-  "Parse OUTPUT.
-OUTPUT is string output from an ocaml process."
-  (let ((regexp "[^:]+ : %s = \\(.+\\)$"))
-    (cond
-     ((string-match (format regexp "string") output)
-      (org-babel-read (match-string 1 output)))
-     ((or (string-match (format regexp "int") output)
-          (string-match (format regexp "float") output))
-      (string-to-number (match-string 1 output)))
-     ((string-match (format regexp "list") output)
-      (org-babel-ocaml-read-list (match-string 1 output)))
-     ((string-match (format regexp "array") output)
-      (org-babel-ocaml-read-array (match-string 1 output)))
-     (t (message "don't recognize type of %s" output) output))))
+(defun org-babel-ocaml-parse-output (value type)
+  "Parse VALUE of type TYPE.
+VALUE and TYPE are string output from an ocaml process."
+  (cond
+   ((string= "string" type)
+    (org-babel-read value))
+   ((or (string= "int" type)
+       (string= "float" type))
+    (string-to-number value))
+   ((string-match "list" type)
+    (org-babel-ocaml-read-list value))
+   ((string-match "array" type)
+    (org-babel-ocaml-read-array value))
+   (t (message "don't recognize type %s" type) value)))
 
 (defun org-babel-ocaml-read-list (results)
   "Convert RESULTS into an elisp table or string.
 If the results look like a table, then convert them into an
 Emacs-lisp table, otherwise return the results as a string."
+  ;; XXX: This probably does not behave as expected when a semicolon
+  ;; is in a string in a list.  The same comment applies to
+  ;; `org-babel-ocaml-read-array' below (with even more failure
+  ;; modes).
   (org-babel-script-escape (replace-regexp-in-string ";" "," results)))
 
 (defun org-babel-ocaml-read-array (results)
diff --git a/lisp/org/ob-octave.el b/lisp/org/ob-octave.el
index 4a96cdb..90735b1 100644
--- a/lisp/org/ob-octave.el
+++ b/lisp/org/ob-octave.el
@@ -1,4 +1,4 @@
-;;; ob-octave.el --- org-babel functions for octave and matlab evaluation
+;;; ob-octave.el --- Babel Functions for Octave and Matlab -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -30,10 +30,10 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function matlab-shell "ext:matlab-mode")
 (declare-function matlab-shell-run-region "ext:matlab-mode")
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-default-header-args:matlab '())
 (defvar org-babel-default-header-args:octave '())
@@ -74,33 +74,31 @@ end")
   (let* ((session
          (funcall (intern (format "org-babel-%s-initiate-session"
                                   (if matlabp "matlab" "octave")))
-                  (cdr (assoc :session params)) params))
-         (vars (mapcar #'cdr (org-babel-get-header params :var)))
-         (result-params (cdr (assoc :result-params params)))
-         (result-type (cdr (assoc :result-type params)))
-        (out-file (cdr (assoc :file params)))
+                  (cdr (assq :session params)) params))
+         (result-type (cdr (assq :result-type params)))
         (full-body
          (org-babel-expand-body:generic
           body params (org-babel-variable-assignments:octave params)))
+        (gfx-file (ignore-errors (org-babel-graphical-output-file params)))
         (result (org-babel-octave-evaluate
                  session
-                 (if (org-babel-octave-graphical-output-file params)
+                 (if gfx-file
                      (mapconcat 'identity
                                 (list
                                  "set (0, \"defaultfigurevisible\", \"off\");"
                                  full-body
-                                 (format "print -dpng %s" 
(org-babel-octave-graphical-output-file params)))
+                                 (format "print -dpng %s" gfx-file))
                                 "\n")
                    full-body)
                  result-type matlabp)))
-    (if (org-babel-octave-graphical-output-file params)
+    (if gfx-file
        nil
       (org-babel-reassemble-table
        result
        (org-babel-pick-name
-       (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+       (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
        (org-babel-pick-name
-       (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))))
+       (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
 
 (defun org-babel-prep-session:matlab (session params)
   "Prepare SESSION according to PARAMS."
@@ -113,7 +111,7 @@ end")
      (format "%s=%s;"
             (car pair)
             (org-babel-octave-var-to-octave (cdr pair))))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 (defalias 'org-babel-variable-assignments:matlab
   'org-babel-variable-assignments:octave)
@@ -147,7 +145,7 @@ If there is not a current inferior-process-buffer in 
SESSION then
 create.  Return the initialized session."
   (org-babel-octave-initiate-session session params 'matlab))
 
-(defun org-babel-octave-initiate-session (&optional session params matlabp)
+(defun org-babel-octave-initiate-session (&optional session _params matlabp)
   "Create an octave inferior process buffer.
 If there is not a current inferior-process-buffer in SESSION then
 create.  Return the initialized session."
@@ -167,8 +165,8 @@ create.  Return the initialized session."
 (defun org-babel-octave-evaluate
   (session body result-type &optional matlabp)
   "Pass BODY to the octave process in SESSION.
-If RESULT-TYPE equals 'output then return the outputs of the
-statements in BODY, if RESULT-TYPE equals 'value then return the
+If RESULT-TYPE equals `output' then return the outputs of the
+statements in BODY, if RESULT-TYPE equals `value' then return the
 value of the last statement in BODY, as elisp."
   (if session
       (org-babel-octave-evaluate-session session body result-type matlabp)
@@ -179,9 +177,9 @@ value of the last statement in BODY, as elisp."
   (let ((cmd (if matlabp
                 org-babel-matlab-shell-command
               org-babel-octave-shell-command)))
-    (case result-type
-      (output (org-babel-eval cmd body))
-      (value (let ((tmp-file (org-babel-temp-file "octave-")))
+    (pcase result-type
+      (`output (org-babel-eval cmd body))
+      (`value (let ((tmp-file (org-babel-temp-file "octave-")))
               (org-babel-eval
                cmd
                (format org-babel-octave-wrapper-method body
@@ -190,17 +188,17 @@ value of the last statement in BODY, as elisp."
               (org-babel-octave-import-elisp-from-file tmp-file))))))
 
 (defun org-babel-octave-evaluate-session
-  (session body result-type &optional matlabp)
+    (session body result-type &optional matlabp)
   "Evaluate BODY in SESSION."
   (let* ((tmp-file (org-babel-temp-file (if matlabp "matlab-" "octave-")))
         (wait-file (org-babel-temp-file "matlab-emacs-link-wait-signal-"))
         (full-body
-         (case result-type
-           (output
+         (pcase result-type
+           (`output
             (mapconcat
              #'org-babel-chomp
              (list body org-babel-octave-eoe-indicator) "\n"))
-           (value
+           (`value
             (if (and matlabp org-babel-matlab-with-emacs-link)
                 (concat
                  (format org-babel-matlab-emacs-link-wrapper-method
@@ -233,21 +231,20 @@ value of the last statement in BODY, as elisp."
                       org-babel-octave-eoe-output)
                     t full-body)
                  (insert full-body) (comint-send-input nil t)))) results)
-    (case result-type
-      (value
+    (pcase result-type
+      (`value
        (org-babel-octave-import-elisp-from-file tmp-file))
-      (output
-       (progn
-        (setq results
-              (if matlabp
-                  (cdr (reverse (delq "" (mapcar
-                                          #'org-babel-octave-read-string
-                                          (mapcar #'org-babel-trim raw)))))
-                (cdr (member org-babel-octave-eoe-output
-                             (reverse (mapcar
-                                       #'org-babel-octave-read-string
-                                       (mapcar #'org-babel-trim raw)))))))
-        (mapconcat #'identity (reverse results) "\n"))))))
+      (`output
+       (setq results
+            (if matlabp
+                (cdr (reverse (delq "" (mapcar
+                                        #'org-babel-strip-quotes
+                                        (mapcar #'org-trim raw)))))
+              (cdr (member org-babel-octave-eoe-output
+                           (reverse (mapcar
+                                     #'org-babel-strip-quotes
+                                     (mapcar #'org-trim raw)))))))
+       (mapconcat #'identity (reverse results) "\n")))))
 
 (defun org-babel-octave-import-elisp-from-file (file-name)
   "Import data from FILE-NAME.
@@ -262,17 +259,6 @@ This removes initial blank and comment lines and then calls
          (delete-region beg end)))
     (org-babel-import-elisp-from-file temp-file '(16))))
 
-(defun org-babel-octave-read-string (string)
-  "Strip \\\"s from around octave string."
-  (if (string-match "^\"\\([^\000]+\\)\"$" string)
-      (match-string 1 string)
-    string))
-
-(defun org-babel-octave-graphical-output-file (params)
-  "Name of file to which maxima should send graphical output."
-  (and (member "graphics" (cdr (assq :result-params params)))
-       (cdr (assq :file params))))
-
 (provide 'ob-octave)
 
 
diff --git a/lisp/org/ob-org.el b/lisp/org/ob-org.el
index 3535891..5683b96 100644
--- a/lisp/org/ob-org.el
+++ b/lisp/org/ob-org.el
@@ -1,4 +1,4 @@
-;;; ob-org.el --- org-babel functions for org code block evaluation
+;;; ob-org.el --- Babel Functions for Org Code Blocks -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -41,7 +41,7 @@
   "Default header inserted during export of org blocks.")
 
 (defun org-babel-expand-body:org (body params)
-  (dolist (var (mapcar #'cdr (org-babel-get-header params :var)))
+  (dolist (var (org-babel--get-vars params))
     (setq body (replace-regexp-in-string
                (regexp-quote (format "$%s" (car var)))
                (format "%s" (cdr var))
@@ -51,7 +51,7 @@
 (defun org-babel-execute:org (body params)
   "Execute a block of Org code with.
 This function is called by `org-babel-execute-src-block'."
-  (let ((result-params (split-string (or (cdr (assoc :results params)) "")))
+  (let ((result-params (split-string (or (cdr (assq :results params)) "")))
        (body (org-babel-expand-body:org
               (replace-regexp-in-string "^," "" body) params)))
     (cond
@@ -61,7 +61,7 @@ This function is called by `org-babel-execute-src-block'."
      ((member "ascii" result-params) (org-export-string-as body 'ascii t))
      (t body))))
 
-(defun org-babel-prep-session:org (session params)
+(defun org-babel-prep-session:org (_session _params)
   "Return an error because org does not support sessions."
   (error "Org does not support sessions"))
 
diff --git a/lisp/org/ob-perl.el b/lisp/org/ob-perl.el
index 4e4407d..62df8c5 100644
--- a/lisp/org/ob-perl.el
+++ b/lisp/org/ob-perl.el
@@ -1,4 +1,4 @@
-;;; ob-perl.el --- org-babel functions for perl evaluation
+;;; ob-perl.el --- Babel Functions for Perl          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -28,7 +28,6 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("perl" . "pl"))
@@ -41,20 +40,20 @@
 (defun org-babel-execute:perl (body params)
   "Execute a block of Perl code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((session (cdr (assoc :session params)))
-         (result-params (cdr (assoc :result-params params)))
-         (result-type (cdr (assoc :result-type params)))
+  (let* ((session (cdr (assq :session params)))
+         (result-params (cdr (assq :result-params params)))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                     body params (org-babel-variable-assignments:perl params)))
         (session (org-babel-perl-initiate-session session)))
     (org-babel-reassemble-table
      (org-babel-perl-evaluate session full-body result-type result-params)
      (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
      (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
 
-(defun org-babel-prep-session:perl (session params)
+(defun org-babel-prep-session:perl (_session _params)
   "Prepare SESSION according to the header arguments in PARAMS."
   (error "Sessions are not supported for Perl"))
 
@@ -63,7 +62,7 @@ This function is called by `org-babel-execute-src-block'."
   (mapcar
    (lambda (pair)
      (org-babel-perl--var-to-perl (cdr pair) (car pair)))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 ;; helper functions
 
@@ -76,7 +75,7 @@ This function is called by `org-babel-execute-src-block'."
 The elisp value, VAR, is converted to a string of perl source code
 specifying a var of the same value."
   (if varn
-      (let ((org-babel-perl--lvl 0) (lvar (listp var)) prefix)
+      (let ((org-babel-perl--lvl 0) (lvar (listp var)))
        (concat "my $" (symbol-name varn) "=" (when lvar "\n")
                (org-babel-perl--var-to-perl var)
                ";\n"))
@@ -92,7 +91,7 @@ specifying a var of the same value."
 
 (defvar org-babel-perl-buffers '(:default . nil))
 
-(defun org-babel-perl-initiate-session (&optional session params)
+(defun org-babel-perl-initiate-session (&optional _session _params)
   "Return nil because sessions are not supported by perl."
   nil)
 
@@ -127,8 +126,8 @@ specifying a var of the same value."
 
 (defun org-babel-perl-evaluate (session ibody &optional result-type 
result-params)
   "Pass BODY to the Perl process in SESSION.
-If RESULT-TYPE equals 'output then return a list of the outputs
-of the statements in BODY, if RESULT-TYPE equals 'value then
+If RESULT-TYPE equals `output' then return a list of the outputs
+of the statements in BODY, if RESULT-TYPE equals `value' then
 return the value of the last statement in BODY, as elisp."
   (when session (error "Sessions are not supported for Perl"))
   (let* ((body (concat org-babel-perl-preface ibody))
@@ -136,13 +135,13 @@ return the value of the last statement in BODY, as elisp."
         (tmp-babel-file (org-babel-process-file-name
                          tmp-file 'noquote)))
     (let ((results
-           (case result-type
-             (output
+           (pcase result-type
+             (`output
               (with-temp-file tmp-file
                 (insert
                  (org-babel-eval org-babel-perl-command body))
                 (buffer-string)))
-             (value
+             (`value
               (org-babel-eval org-babel-perl-command
                               (format org-babel-perl-wrapper-method
                                       body tmp-babel-file))))))
diff --git a/lisp/org/ob-picolisp.el b/lisp/org/ob-picolisp.el
index a87c15e..f577381 100644
--- a/lisp/org/ob-picolisp.el
+++ b/lisp/org/ob-picolisp.el
@@ -1,4 +1,4 @@
-;;; ob-picolisp.el --- org-babel functions for picolisp evaluation
+;;; ob-picolisp.el --- Babel Functions for Picolisp  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -55,7 +55,6 @@
 ;;; Code:
 (require 'ob)
 (require 'comint)
-(eval-when-compile (require 'cl))
 
 (declare-function run-picolisp "ext:inferior-picolisp" (cmd))
 (defvar org-babel-tangle-lang-exts) ;; Autoloaded
@@ -80,9 +79,9 @@
 
 (defun org-babel-expand-body:picolisp (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))
-        (result-params (cdr (assoc :result-params params)))
-        (print-level nil) (print-length nil))
+  (let ((vars (org-babel--get-vars params))
+        (print-level nil)
+       (print-length nil))
     (if (> (length vars) 0)
         (concat "(prog (let ("
                 (mapconcat
@@ -100,12 +99,11 @@
   (message "executing Picolisp source code block")
   (let* (
         ;; Name of the session or "none".
-        (session-name (cdr (assoc :session params)))
+        (session-name (cdr (assq :session params)))
         ;; Set the session if the session variable is non-nil.
         (session (org-babel-picolisp-initiate-session session-name))
         ;; Either OUTPUT or VALUE which should behave as described above.
-        (result-type (cdr (assoc :result-type params)))
-        (result-params (cdr (assoc :result-params params)))
+        (result-params (cdr (assq :result-params params)))
         ;; Expand the body with `org-babel-expand-body:picolisp'.
         (full-body (org-babel-expand-body:picolisp body params))
          ;; Wrap body appropriately for the type of evaluation and results.
diff --git a/lisp/org/ob-plantuml.el b/lisp/org/ob-plantuml.el
index e05565e..e90021a 100644
--- a/lisp/org/ob-plantuml.el
+++ b/lisp/org/ob-plantuml.el
@@ -1,4 +1,4 @@
-;;; ob-plantuml.el --- org-babel functions for plantuml evaluation
+;;; ob-plantuml.el --- Babel Functions for Plantuml  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -49,21 +49,36 @@
 (defun org-babel-execute:plantuml (body params)
   "Execute a block of plantuml code with org-babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
-        (out-file (or (cdr (assoc :file params))
+  (let* ((out-file (or (cdr (assq :file params))
                       (error "PlantUML requires a \":file\" header argument")))
-        (cmdline (cdr (assoc :cmdline params)))
+        (cmdline (cdr (assq :cmdline params)))
         (in-file (org-babel-temp-file "plantuml-"))
-        (java (or (cdr (assoc :java params)) ""))
+        (java (or (cdr (assq :java params)) ""))
         (cmd (if (string= "" org-plantuml-jar-path)
                  (error "`org-plantuml-jar-path' is not set")
                (concat "java " java " -jar "
                        (shell-quote-argument
                         (expand-file-name org-plantuml-jar-path))
+                       (if (string= (file-name-extension out-file) "png")
+                           " -tpng" "")
                        (if (string= (file-name-extension out-file) "svg")
                            " -tsvg" "")
                        (if (string= (file-name-extension out-file) "eps")
                            " -teps" "")
+                       (if (string= (file-name-extension out-file) "pdf")
+                           " -tpdf" "")
+                       (if (string= (file-name-extension out-file) "vdx")
+                           " -tvdx" "")
+                       (if (string= (file-name-extension out-file) "xmi")
+                           " -txmi" "")
+                       (if (string= (file-name-extension out-file) "scxml")
+                           " -tscxml" "")
+                       (if (string= (file-name-extension out-file) "html")
+                           " -thtml" "")
+                       (if (string= (file-name-extension out-file) "txt")
+                           " -ttxt" "")
+                       (if (string= (file-name-extension out-file) "utxt")
+                           " -utxt" "")
                        " -p " cmdline " < "
                        (org-babel-process-file-name in-file)
                        " > "
@@ -74,7 +89,7 @@ This function is called by `org-babel-execute-src-block'."
     (message "%s" cmd) (org-babel-eval cmd "")
     nil)) ;; signal that output has already been written to file
 
-(defun org-babel-prep-session:plantuml (session params)
+(defun org-babel-prep-session:plantuml (_session _params)
   "Return an error because plantuml does not support sessions."
   (error "Plantuml does not support sessions"))
 
diff --git a/lisp/org/ob-processing.el b/lisp/org/ob-processing.el
new file mode 100644
index 0000000..a18a53c
--- /dev/null
+++ b/lisp/org/ob-processing.el
@@ -0,0 +1,195 @@
+;;; ob-processing.el --- Babel functions for processing -*- lexical-binding: 
t; -*-
+
+;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+;; Author: Jarmo Hurri (adapted from ob-asymptote.el written by Eric Schulte)
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Babel support for evaluating processing source code.
+;;
+;; This differs from most standard languages in that
+;;
+;; 1) there is no such thing as a "session" in processing
+;;
+;; 2) results can only be exported as html; in this case, the
+;;    processing code is embedded via a file into a javascript block
+;;    using the processing.js module; the script then draws the
+;;    resulting output when the web page is viewed in a browser; note
+;;    that the user is responsible for making sure that processing.js
+;;    is available on the website
+;;
+;; 3) it is possible to interactively view the sketch of the
+;;    Processing code block via Processing 2.0 Emacs mode, using
+;;    `org-babel-processing-view-sketch'.  You can bind this command
+;;    to, e.g., C-c C-v C-k with
+;;
+;;      (define-key org-babel-map (kbd "C-k") 
'org-babel-processing-view-sketch)
+
+
+;;; Requirements:
+
+;; - processing2-emacs mode :: https://github.com/ptrv/processing2-emacs
+;; - Processing.js module :: http://processingjs.org/
+
+;;; Code:
+(require 'ob)
+(require 'sha1)
+
+(declare-function processing-sketch-run "ext:processing-mode" ())
+
+(defvar org-babel-temporary-directory)
+
+(defvar org-babel-tangle-lang-exts)
+(add-to-list 'org-babel-tangle-lang-exts '("processing" . "pde"))
+
+;; Default header tags depend on whether exporting html or not; if not
+;; exporting html, then no results are produced; otherwise results are
+;; HTML.
+(defvar org-babel-default-header-args:processing
+  '((:results . "html") (:exports . "results"))
+  "Default arguments when evaluating a Processing source block.")
+
+(defvar org-babel-processing-processing-js-filename "processing.js"
+  "Filename of the processing.js file.")
+
+(defun org-babel-processing-view-sketch ()
+  "Show the sketch of the Processing block under point in an external viewer."
+  (interactive)
+  (require 'processing-mode)
+  (let ((info (org-babel-get-src-block-info)))
+    (if (string= (nth 0 info) "processing")
+       (let* ((body (nth 1 info))
+              (params (org-babel-process-params (nth 2 info)))
+              (sketch-code
+               (org-babel-expand-body:generic
+                body
+                params
+                (org-babel-variable-assignments:processing params))))
+         ;; Note: sketch filename can not contain a hyphen, since it
+         ;; has to be a valid java class name; for this reason
+         ;; make-temp-file is repeated until no hyphen is in the
+         ;; name; also sketch dir name must be the same as the
+         ;; basename of the sketch file.
+         (let* ((temporary-file-directory org-babel-temporary-directory)
+                (sketch-dir
+                 (let (sketch-dir-candidate)
+                   (while
+                       (progn
+                         (setq sketch-dir-candidate
+                               (make-temp-file "processing" t))
+                         (when (string-match-p
+                                "-"
+                                (file-name-nondirectory sketch-dir-candidate))
+                           (delete-directory sketch-dir-candidate)
+                           t)))
+                   sketch-dir-candidate))
+                (sketch-filename
+                 (concat sketch-dir
+                         "/"
+                         (file-name-nondirectory sketch-dir)
+                         ".pde")))
+           (with-temp-file sketch-filename (insert sketch-code))
+           (find-file sketch-filename)
+           (processing-sketch-run)
+           (kill-buffer)))
+      (message "Not inside a Processing source block."))))
+
+(defun org-babel-execute:processing (body params)
+  "Execute a block of Processing code.
+This function is called by `org-babel-execute-src-block'."
+  (let ((sketch-code
+        (org-babel-expand-body:generic
+         body
+         params
+         (org-babel-variable-assignments:processing params))))
+    ;; Results are HTML.
+    (let ((sketch-canvas-id (concat "ob-" (sha1 sketch-code))))
+      (concat "<script src=\""
+             org-babel-processing-processing-js-filename
+             "\"></script>\n <script type=\"text/processing\""
+             " data-processing-target=\""
+             sketch-canvas-id
+             "\">\n"
+             sketch-code
+             "\n</script> <canvas id=\""
+             sketch-canvas-id
+             "\"></canvas>"))))
+
+(defun org-babel-prep-session:processing (_session _params)
+  "Return an error if the :session header argument is set.
+Processing does not support sessions"
+  (error "Processing does not support sessions"))
+
+(defun org-babel-variable-assignments:processing (params)
+  "Return list of processing statements assigning the block's variables."
+  (mapcar #'org-babel-processing-var-to-processing
+         (org-babel--get-vars params)))
+
+(defun org-babel-processing-var-to-processing (pair)
+  "Convert an elisp value into a Processing variable.
+The elisp value PAIR is converted into Processing code specifying
+a variable of the same value."
+  (let ((var (car pair))
+        (val (let ((v (cdr pair)))
+              (if (symbolp v) (symbol-name v) v))))
+    (cond
+     ((integerp val)
+      (format "int %S=%S;" var val))
+     ((floatp val)
+      (format "float %S=%S;" var val))
+     ((stringp val)
+      (format "String %S=\"%s\";" var val))
+     ((and (listp val) (not (listp (car val))))
+      (let* ((type (org-babel-processing-define-type val))
+            (fmt (if (eq 'String type) "\"%s\"" "%s"))
+            (vect (mapconcat (lambda (e) (format fmt e)) val ", ")))
+       (format "%s[] %S={%s};" type var vect)))
+     ((listp val)
+      (let* ((type (org-babel-processing-define-type val))
+            (fmt (if (eq 'String type) "\"%s\"" "%s"))
+             (array (mapconcat (lambda (row)
+                                (concat "{"
+                                        (mapconcat (lambda (e) (format fmt e))
+                                                   row ", ")
+                                        "}"))
+                              val ",")))
+        (format "%S[][] %S={%s};" type var array))))))
+
+(defun org-babel-processing-define-type (data)
+  "Determine type of DATA.
+
+DATA is a list.  Return type as a symbol.
+
+The type is `String' if any element in DATA is a string.
+Otherwise, it is either `float', if some elements are floats, or
+`int'."
+  (letrec ((type 'int)
+          (find-type
+           (lambda (row)
+             (dolist (e row type)
+               (cond ((listp e) (setq type (funcall find-type e)))
+                     ((stringp e) (throw 'exit 'String))
+                     ((floatp e) (setq type 'float)))))))
+    (catch 'exit (funcall find-type data))))
+
+(provide 'ob-processing)
+
+;;; ob-processing.el ends here
diff --git a/lisp/org/ob-python.el b/lisp/org/ob-python.el
index dfad47b..302f8bd 100644
--- a/lisp/org/ob-python.el
+++ b/lisp/org/ob-python.el
@@ -1,4 +1,4 @@
-;;; ob-python.el --- org-babel functions for python evaluation
+;;; ob-python.el --- Babel Functions for Python      -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -28,9 +28,9 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function org-remove-indentation "org" )
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function py-shell "ext:python-mode" (&optional argprompt))
 (declare-function py-toggle-shells "ext:python-mode" (arg))
 (declare-function run-python "ext:python" (&optional cmd dedicated show))
@@ -48,9 +48,9 @@
   :type 'string)
 
 (defcustom org-babel-python-mode
-  (if (or (featurep 'xemacs) (featurep 'python-mode)) 'python-mode 'python)
+  (if (featurep 'python-mode) 'python-mode 'python)
   "Preferred python mode for use in running python interactively.
-This will typically be either 'python or 'python-mode."
+This will typically be either `python' or `python-mode'."
   :group 'org-babel
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -73,13 +73,16 @@ This will typically be either 'python or 'python-mode."
 (defun org-babel-execute:python (body params)
   "Execute a block of Python code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((session (org-babel-python-initiate-session
-                  (cdr (assoc :session params))))
-         (result-params (cdr (assoc :result-params params)))
-         (result-type (cdr (assoc :result-type params)))
+  (let* ((org-babel-python-command
+         (or (cdr (assq :python params))
+             org-babel-python-command))
+        (session (org-babel-python-initiate-session
+                  (cdr (assq :session params))))
+         (result-params (cdr (assq :result-params params)))
+         (result-type (cdr (assq :result-type params)))
         (return-val (when (and (eq result-type 'value) (not session))
-                      (cdr (assoc :return params))))
-        (preamble (cdr (assoc :preamble params)))
+                      (cdr (assq :return params))))
+        (preamble (cdr (assq :preamble params)))
          (full-body
          (org-babel-expand-body:generic
           (concat body (if return-val (format "\nreturn %s" return-val) ""))
@@ -88,10 +91,10 @@ This function is called by `org-babel-execute-src-block'."
                  session full-body result-type result-params preamble)))
     (org-babel-reassemble-table
      result
-     (org-babel-pick-name (cdr (assoc :colname-names params))
-                         (cdr (assoc :colnames params)))
-     (org-babel-pick-name (cdr (assoc :rowname-names params))
-                         (cdr (assoc :rownames params))))))
+     (org-babel-pick-name (cdr (assq :colname-names params))
+                         (cdr (assq :colnames params)))
+     (org-babel-pick-name (cdr (assq :rowname-names params))
+                         (cdr (assq :rownames params))))))
 
 (defun org-babel-prep-session:python (session params)
   "Prepare SESSION according to the header arguments in PARAMS.
@@ -123,7 +126,7 @@ VARS contains resolved variable references"
      (format "%s=%s"
             (car pair)
             (org-babel-python-var-to-python (cdr pair))))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 (defun org-babel-python-var-to-python (var)
   "Convert an elisp value to a python variable.
@@ -131,7 +134,7 @@ Convert an elisp value, VAR, into a string of python source 
code
 specifying a variable of the same value."
   (if (listp var)
       (concat "[" (mapconcat #'org-babel-python-var-to-python var ", ") "]")
-    (if (equal var 'hline)
+    (if (eq var 'hline)
        org-babel-python-hline-to
       (format
        (if (and (stringp var) (string-match "[\n\r]" var)) "\"\"%S\"\"" "%S")
@@ -143,7 +146,7 @@ If the results look like a list or tuple, then convert them 
into an
 Emacs-lisp table, otherwise return the results as a string."
   (let ((res (org-babel-script-escape results)))
     (if (listp res)
-        (mapcar (lambda (el) (if (equal el 'None)
+        (mapcar (lambda (el) (if (eq el 'None)
                             org-babel-python-None-to el))
                 res)
       res)))
@@ -214,7 +217,7 @@ then create.  Return the initialized session."
                  (assq-delete-all session org-babel-python-buffers)))
       session)))
 
-(defun org-babel-python-initiate-session (&optional session params)
+(defun org-babel-python-initiate-session (&optional session _params)
   "Create a session named SESSION according to PARAMS."
   (unless (string= session "none")
     (org-babel-python-session-buffer
@@ -222,13 +225,13 @@ then create.  Return the initialized session."
 
 (defvar org-babel-python-eoe-indicator "'org_babel_python_eoe'"
   "A string to indicate that evaluation has completed.")
-(defvar org-babel-python-wrapper-method
+(defconst org-babel-python-wrapper-method
   "
 def main():
 %s
 
 open('%s', 'w').write( str(main()) )")
-(defvar org-babel-python-pp-wrapper-method
+(defconst org-babel-python-pp-wrapper-method
   "
 import pprint
 def main():
@@ -246,42 +249,41 @@ open('%s', 'w').write( pprint.pformat(main()) )")
      body result-type result-params preamble)))
 
 (defun org-babel-python-evaluate-external-process
-  (body &optional result-type result-params preamble)
+    (body &optional result-type result-params preamble)
   "Evaluate BODY in external python process.
-If RESULT-TYPE equals 'output then return standard output as a
-string.  If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string.  If RESULT-TYPE equals `value' then return the value of the
 last statement in BODY, as elisp."
   (let ((raw
-         (case result-type
-           (output (org-babel-eval org-babel-python-command
-                                   (concat (if preamble (concat preamble "\n"))
-                                           body)))
-           (value (let ((tmp-file (org-babel-temp-file "python-")))
-                    (org-babel-eval
-                     org-babel-python-command
-                     (concat
-                      (if preamble (concat preamble "\n") "")
-                      (format
-                       (if (member "pp" result-params)
-                           org-babel-python-pp-wrapper-method
-                         org-babel-python-wrapper-method)
-                       (mapconcat
-                        (lambda (line) (format "\t%s" line))
-                        (split-string
-                         (org-remove-indentation
-                          (org-babel-trim body))
-                         "[\r\n]") "\n")
-                       (org-babel-process-file-name tmp-file 'noquote))))
-                    (org-babel-eval-read-file tmp-file))))))
+         (pcase result-type
+           (`output (org-babel-eval org-babel-python-command
+                                   (concat (if preamble (concat preamble "\n"))
+                                           body)))
+           (`value (let ((tmp-file (org-babel-temp-file "python-")))
+                    (org-babel-eval
+                     org-babel-python-command
+                     (concat
+                      (if preamble (concat preamble "\n") "")
+                      (format
+                       (if (member "pp" result-params)
+                           org-babel-python-pp-wrapper-method
+                         org-babel-python-wrapper-method)
+                       (mapconcat
+                        (lambda (line) (format "\t%s" line))
+                        (split-string (org-remove-indentation (org-trim body))
+                                      "[\r\n]")
+                        "\n")
+                       (org-babel-process-file-name tmp-file 'noquote))))
+                    (org-babel-eval-read-file tmp-file))))))
     (org-babel-result-cond result-params
       raw
-      (org-babel-python-table-or-string (org-babel-trim raw)))))
+      (org-babel-python-table-or-string (org-trim raw)))))
 
 (defun org-babel-python-evaluate-session
     (session body &optional result-type result-params)
   "Pass BODY to the Python process in SESSION.
-If RESULT-TYPE equals 'output then return standard output as a
-string.  If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string.  If RESULT-TYPE equals `value' then return the value of the
 last statement in BODY, as elisp."
   (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
         (dump-last-value
@@ -302,10 +304,10 @@ last statement in BODY, as elisp."
                             (split-string body "[\r\n]"))
                       (funcall send-wait)))
          (results
-          (case result-type
-            (output
+          (pcase result-type
+            (`output
              (mapconcat
-              #'org-babel-trim
+              #'org-trim
               (butlast
                (org-babel-comint-with-output
                    (session org-babel-python-eoe-indicator t body)
@@ -314,7 +316,7 @@ last statement in BODY, as elisp."
                  (insert org-babel-python-eoe-indicator)
                  (funcall send-wait))
                2) "\n"))
-            (value
+            (`value
              (let ((tmp-file (org-babel-temp-file "python-")))
                (org-babel-comint-with-output
                    (session org-babel-python-eoe-indicator nil body)
@@ -332,9 +334,10 @@ last statement in BODY, as elisp."
         (org-babel-python-table-or-string results)))))
 
 (defun org-babel-python-read-string (string)
-  "Strip 's from around Python string."
-  (if (string-match "^'\\([^\000]+\\)'$" string)
-      (match-string 1 string)
+  "Strip \\='s from around Python string."
+  (if (and (string-prefix-p "'" string)
+          (string-suffix-p "'" string))
+      (substring string 1 -1)
     string))
 
 (provide 'ob-python)
diff --git a/lisp/org/ob-ref.el b/lisp/org/ob-ref.el
index 1d26403..f8b9ea4 100644
--- a/lisp/org/ob-ref.el
+++ b/lisp/org/ob-ref.el
@@ -1,4 +1,4 @@
-;;; ob-ref.el --- org-babel functions for referencing external data
+;;; ob-ref.el --- Babel Functions for Referencing External Data -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -50,19 +50,20 @@
 
 ;;; Code:
 (require 'ob-core)
-(eval-when-compile
-  (require 'cl))
-
-(declare-function org-remove-if-not "org" (predicate seq))
-(declare-function org-at-table-p "org" (&optional table-type))
-(declare-function org-count "org" (CL-ITEM CL-SEQ))
-(declare-function org-at-item-p "org-list" ())
-(declare-function org-narrow-to-subtree "org" ())
-(declare-function org-id-find-id-in-file "org-id" (id file &optional markerp))
+(require 'cl-lib)
+
+(declare-function org-babel-lob-get-info "ob-lob" (&optional datum))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-end-of-meta-data "org" (&optional full))
+(declare-function org-find-property "org" (property &optional value))
 (declare-function org-id-find-id-file "org-id" (id))
+(declare-function org-id-find-id-in-file "org-id" (id file &optional markerp))
+(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
+(declare-function org-narrow-to-subtree "org" ())
 (declare-function org-show-context "org" (&optional key))
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
+(declare-function org-trim "org" (s &optional keep-lead))
 
 (defvar org-babel-ref-split-regexp
   "[ \f\t\n\r\v]*\\(.+?\\)[ \f\t\n\r\v]*=[ \f\t\n\r\v]*\\(.+\\)[ \f\t\n\r\v]*")
@@ -90,35 +91,31 @@ the variable."
                                        org-babel-current-src-block-location)))
                         (org-babel-read ref))))
              (if (equal out ref)
-                 (if (string-match "^\".*\"$" ref)
+                 (if (and (string-prefix-p "\"" ref)
+                          (string-suffix-p "\"" ref))
                      (read ref)
                    (org-babel-ref-resolve ref))
                out))))))
 
 (defun org-babel-ref-goto-headline-id (id)
-  (goto-char (point-min))
-  (let ((rx (regexp-quote id)))
-    (or (re-search-forward
-        (concat "^[ \t]*:CUSTOM_ID:[ \t]+" rx "[ \t]*$") nil t)
-       (let* ((file (org-id-find-id-file id))
-              (m (when file (org-id-find-id-in-file id file 'marker))))
-         (when (and file m)
-           (message "file:%S" file)
-           (org-pop-to-buffer-same-window (marker-buffer m))
-           (goto-char m)
-           (move-marker m nil)
-           (org-show-context)
-           t)))))
+  (or (let ((h (org-find-property "CUSTOM_ID" id)))
+       (when h (goto-char h)))
+      (let* ((file (org-id-find-id-file id))
+            (m (when file (org-id-find-id-in-file id file 'marker))))
+       (when (and file m)
+         (message "file:%S" file)
+         (pop-to-buffer-same-window (marker-buffer m))
+         (goto-char m)
+         (move-marker m nil)
+         (org-show-context)
+         t))))
 
 (defun org-babel-ref-headline-body ()
   (save-restriction
     (org-narrow-to-subtree)
     (buffer-substring
      (save-excursion (goto-char (point-min))
-                    (forward-line 1)
-                    (when (looking-at "[ \t]*:PROPERTIES:")
-                      (re-search-forward ":END:" nil)
-                      (forward-char))
+                    (org-end-of-meta-data)
                     (point))
      (point-max))))
 
@@ -126,89 +123,82 @@ the variable."
 (defun org-babel-ref-resolve (ref)
   "Resolve the reference REF and return its value."
   (save-window-excursion
-    (save-excursion
-      (let ((case-fold-search t)
-           type args new-refere new-header-args new-referent result
-           lob-info split-file split-ref index index-row index-col id)
-       ;; if ref is indexed grab the indices -- beware nested indices
-       (when (and (string-match "\\[\\([^\\[]+\\)\\]$" ref)
-                  (let ((str (substring ref 0 (match-beginning 0))))
-                    (= (org-count ?\( str) (org-count ?\) str))))
-         (setq index (match-string 1 ref))
-         (setq ref (substring ref 0 (match-beginning 0))))
-       ;; assign any arguments to pass to source block
-       (when (string-match
-              "^\\(.+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)(\\(.*\\))$" ref)
-         (setq new-refere      (match-string 1 ref))
-         (setq new-header-args (match-string 3 ref))
-         (setq new-referent    (match-string 5 ref))
-         (when (> (length new-refere) 0)
-           (when (> (length new-referent) 0)
-             (setq args (mapcar (lambda (ref) (cons :var ref))
-                                (org-babel-ref-split-args new-referent))))
-           (when (> (length new-header-args) 0)
-             (setq args (append (org-babel-parse-header-arguments
-                                 new-header-args) args)))
-           (setq ref new-refere)))
-       (when (string-match "^\\(.+\\):\\(.+\\)$" ref)
-         (setq split-file (match-string 1 ref))
-         (setq split-ref (match-string 2 ref))
-         (find-file split-file) (setq ref split-ref))
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (if (let ((src-rx (org-babel-named-src-block-regexp-for-name ref))
-                   (res-rx (org-babel-named-data-regexp-for-name ref)))
-               ;; goto ref in the current buffer
-               (or
-                ;; check for code blocks
-                (re-search-forward src-rx nil t)
-                ;; check for named data
-                (re-search-forward res-rx nil t)
-                ;; check for local or global headlines by id
-                (setq id (org-babel-ref-goto-headline-id ref))
-                ;; check the Library of Babel
-                (setq lob-info (cdr (assoc (intern ref)
-                                           org-babel-library-of-babel)))))
-             (unless (or lob-info id) (goto-char (match-beginning 0)))
-           ;; ;; TODO: allow searching for names in other buffers
-           ;; (setq id-loc (org-id-find ref 'marker)
-           ;;       buffer (marker-buffer id-loc)
-           ;;       loc (marker-position id-loc))
-           ;; (move-marker id-loc nil)
-           (error "Reference `%s' not found in this buffer" ref))
-         (cond
-          (lob-info (setq type 'lob))
-          (id (setq type 'id))
-          ((and (looking-at org-babel-src-name-regexp)
-                (save-excursion
-                  (forward-line 1)
-                  (or (looking-at org-babel-src-block-regexp)
-                      (looking-at org-babel-multi-line-header-regexp))))
-           (setq type 'source-block))
-          (t (while (not (setq type (org-babel-ref-at-ref-p)))
-               (forward-line 1)
-               (beginning-of-line)
-               (if (or (= (point) (point-min)) (= (point) (point-max)))
-                   (error "Reference not found")))))
-         (let ((params (append args '((:results . "silent")))))
-           (setq result
-                 (case type
-                   (results-line (org-babel-read-result))
-                   (table        (org-babel-read-table))
-                   (list         (org-babel-read-list))
-                   (file         (org-babel-read-link))
-                   (source-block (org-babel-execute-src-block
-                                  nil nil (if org-babel-update-intermediate
-                                              nil params)))
-                   (lob          (org-babel-execute-src-block
-                                  nil lob-info params))
-                   (id           (org-babel-ref-headline-body)))))
-         (if (symbolp result)
-             (format "%S" result)
-           (if (and index (listp result))
-               (org-babel-ref-index-list index result)
-             result)))))))
+    (with-current-buffer (or org-babel-exp-reference-buffer (current-buffer))
+      (save-excursion
+       (let ((case-fold-search t)
+             args new-refere new-header-args new-referent split-file split-ref
+             index)
+         ;; if ref is indexed grab the indices -- beware nested indices
+         (when (and (string-match "\\[\\([^\\[]+\\)\\]$" ref)
+                    (let ((str (substring ref 0 (match-beginning 0))))
+                      (= (cl-count ?\( str) (cl-count ?\) str))))
+           (setq index (match-string 1 ref))
+           (setq ref (substring ref 0 (match-beginning 0))))
+         ;; assign any arguments to pass to source block
+         (when (string-match
+                "^\\(.+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)(\\(.*\\))$" ref)
+           (setq new-refere      (match-string 1 ref))
+           (setq new-header-args (match-string 3 ref))
+           (setq new-referent    (match-string 5 ref))
+           (when (> (length new-refere) 0)
+             (when (> (length new-referent) 0)
+               (setq args (mapcar (lambda (ref) (cons :var ref))
+                                  (org-babel-ref-split-args new-referent))))
+             (when (> (length new-header-args) 0)
+               (setq args (append (org-babel-parse-header-arguments
+                                   new-header-args) args)))
+             (setq ref new-refere)))
+         (when (string-match "^\\(.+\\):\\(.+\\)$" ref)
+           (setq split-file (match-string 1 ref))
+           (setq split-ref (match-string 2 ref))
+           (find-file split-file)
+           (setq ref split-ref))
+         (org-with-wide-buffer
+          (goto-char (point-min))
+          (let* ((params (append args '((:results . "silent"))))
+                 (regexp (org-babel-named-data-regexp-for-name ref))
+                 (result
+                  (catch :found
+                    ;; Check for code blocks or named data.
+                    (while (re-search-forward regexp nil t)
+                      ;; Ignore COMMENTed headings and orphaned
+                      ;; affiliated keywords.
+                      (unless (org-in-commented-heading-p)
+                        (let ((e (org-element-at-point)))
+                          (when (equal (org-element-property :name e) ref)
+                            (goto-char
+                             (org-element-property :post-affiliated e))
+                            (pcase (org-element-type e)
+                              (`babel-call
+                               (throw :found
+                                      (org-babel-execute-src-block
+                                       nil (org-babel-lob-get-info e) params)))
+                              (`src-block
+                               (throw :found
+                                      (org-babel-execute-src-block
+                                       nil nil
+                                       (and
+                                        (not org-babel-update-intermediate)
+                                        params))))
+                              ((and (let v (org-babel-read-element e))
+                                    (guard v))
+                               (throw :found v))
+                              (_ (error "Reference not found")))))))
+                    ;; Check for local or global headlines by ID.
+                    (when (org-babel-ref-goto-headline-id ref)
+                      (throw :found (org-babel-ref-headline-body)))
+                    ;; Check the Library of Babel.
+                    (let ((info (cdr (assq (intern ref)
+                                           org-babel-library-of-babel))))
+                      (when info
+                        (throw :found
+                               (org-babel-execute-src-block nil info params))))
+                    (error "Reference `%s' not found in this buffer" ref))))
+            (cond
+             ((symbolp result) (format "%S" result))
+             ((and index (listp result))
+              (org-babel-ref-index-list index result))
+             (t result)))))))))
 
 (defun org-babel-ref-index-list (index lis)
   "Return the subset of LIS indexed by INDEX.
@@ -251,21 +241,9 @@ to \"0:-1\"."
 
 (defun org-babel-ref-split-args (arg-string)
   "Split ARG-STRING into top-level arguments of balanced parenthesis."
-  (mapcar #'org-babel-trim (org-babel-balanced-split arg-string 44)))
+  (mapcar #'org-trim (org-babel-balanced-split arg-string 44)))
 
-(defvar org-bracket-link-regexp)
-(defun org-babel-ref-at-ref-p ()
-  "Return the type of reference located at point.
-Return nil if none of the supported reference types are found.
-Supported reference types are tables and source blocks."
-  (cond ((org-at-table-p) 'table)
-       ((org-at-item-p) 'list)
-        ((looking-at "^[ \t]*#\\+BEGIN_SRC") 'source-block)
-        ((looking-at org-bracket-link-regexp) 'file)
-        ((looking-at org-babel-result-regexp) 'results-line)))
 
 (provide 'ob-ref)
 
-
-
 ;;; ob-ref.el ends here
diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el
index 88a9987..d055783 100644
--- a/lisp/org/ob-ruby.el
+++ b/lisp/org/ob-ruby.el
@@ -1,4 +1,4 @@
-;;; ob-ruby.el --- org-babel functions for ruby evaluation
+;;; ob-ruby.el --- Babel Functions for Ruby          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -37,11 +37,14 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function run-ruby "ext:inf-ruby" (&optional command name))
 (declare-function xmp "ext:rcodetools" (&optional option))
 
+(defvar inf-ruby-default-implementation)
+(defvar inf-ruby-implementations)
+
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("ruby" . "rb"))
 
@@ -68,16 +71,16 @@
   "Execute a block of Ruby code with Babel.
 This function is called by `org-babel-execute-src-block'."
   (let* ((session (org-babel-ruby-initiate-session
-                  (cdr (assoc :session params))))
-         (result-params (cdr (assoc :result-params params)))
-         (result-type (cdr (assoc :result-type params)))
+                  (cdr (assq :session params))))
+         (result-params (cdr (assq :result-params params)))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                     body params (org-babel-variable-assignments:ruby params)))
          (result (if (member "xmp" result-params)
                     (with-temp-buffer
                       (require 'rcodetools)
                       (insert full-body)
-                      (xmp (cdr (assoc :xmp-option params)))
+                      (xmp (cdr (assq :xmp-option params)))
                       (buffer-string))
                   (org-babel-ruby-evaluate
                    session full-body result-type result-params))))
@@ -85,10 +88,10 @@ This function is called by `org-babel-execute-src-block'."
      (org-babel-result-cond result-params
        result
        (org-babel-ruby-table-or-string result))
-     (org-babel-pick-name (cdr (assoc :colname-names params))
-                         (cdr (assoc :colnames params)))
-     (org-babel-pick-name (cdr (assoc :rowname-names params))
-                         (cdr (assoc :rownames params))))))
+     (org-babel-pick-name (cdr (assq :colname-names params))
+                         (cdr (assq :colnames params)))
+     (org-babel-pick-name (cdr (assq :rowname-names params))
+                         (cdr (assq :rownames params))))))
 
 (defun org-babel-prep-session:ruby (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
@@ -121,7 +124,7 @@ This function is called by `org-babel-execute-src-block'."
      (format "%s=%s"
             (car pair)
             (org-babel-ruby-var-to-ruby (cdr pair))))
-   (mapcar #'cdr (org-babel-get-header params :var))))
+   (org-babel--get-vars params)))
 
 (defun org-babel-ruby-var-to-ruby (var)
   "Convert VAR into a ruby variable.
@@ -129,7 +132,7 @@ Convert an elisp value into a string of ruby source code
 specifying a variable of the same value."
   (if (listp var)
       (concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var ", ") "]")
-    (if (equal var 'hline)
+    (if (eq var 'hline)
        org-babel-ruby-hline-to
       (format "%S" var))))
 
@@ -139,23 +142,27 @@ If RESULTS look like a table, then convert them into an
 Emacs-lisp table, otherwise return the results as a string."
   (let ((res (org-babel-script-escape results)))
     (if (listp res)
-        (mapcar (lambda (el) (if (equal el 'nil)
-                            org-babel-ruby-nil-to el))
+        (mapcar (lambda (el) (if (not el)
+                                org-babel-ruby-nil-to el))
                 res)
       res)))
 
-(defun org-babel-ruby-initiate-session (&optional session params)
+(defun org-babel-ruby-initiate-session (&optional session _params)
   "Initiate a ruby session.
 If there is not a current inferior-process-buffer in SESSION
 then create one.  Return the initialized session."
   (unless (string= session "none")
     (require 'inf-ruby)
-    (let ((session-buffer (save-window-excursion
-                           (run-ruby nil session) (current-buffer))))
+    (let* ((cmd (cdr (assoc inf-ruby-default-implementation
+                           inf-ruby-implementations)))
+          (buffer (get-buffer (format "*%s*" session)))
+          (session-buffer (or buffer (save-window-excursion
+                                       (run-ruby cmd session)
+                                       (current-buffer)))))
       (if (org-babel-comint-buffer-livep session-buffer)
          (progn (sit-for .25) session-buffer)
-        (sit-for .5)
-        (org-babel-ruby-initiate-session session)))))
+       (sit-for .5)
+       (org-babel-ruby-initiate-session session)))))
 
 (defvar org-babel-ruby-eoe-indicator ":org_babel_ruby_eoe"
   "String to indicate that evaluation has completed.")
@@ -185,46 +192,53 @@ end
 ")
 
 (defun org-babel-ruby-evaluate
-  (buffer body &optional result-type result-params)
+    (buffer body &optional result-type result-params)
   "Pass BODY to the Ruby process in BUFFER.
-If RESULT-TYPE equals 'output then return a list of the outputs
-of the statements in BODY, if RESULT-TYPE equals 'value then
+If RESULT-TYPE equals `output' then return a list of the outputs
+of the statements in BODY, if RESULT-TYPE equals `value' then
 return the value of the last statement in BODY, as elisp."
   (if (not buffer)
       ;; external process evaluation
-      (case result-type
-       (output (org-babel-eval org-babel-ruby-command body))
-       (value (let ((tmp-file (org-babel-temp-file "ruby-")))
-                (org-babel-eval
-                 org-babel-ruby-command
-                 (format (if (member "pp" result-params)
-                             org-babel-ruby-pp-wrapper-method
-                           org-babel-ruby-wrapper-method)
-                         body (org-babel-process-file-name tmp-file 'noquote)))
-                (let ((raw (org-babel-eval-read-file tmp-file)))
-                   (if (or (member "code" result-params)
-                           (member "pp" result-params))
-                       raw
-                     (org-babel-ruby-table-or-string raw))))))
+      (pcase result-type
+       (`output (org-babel-eval org-babel-ruby-command body))
+       (`value (let ((tmp-file (org-babel-temp-file "ruby-")))
+                 (org-babel-eval
+                  org-babel-ruby-command
+                  (format (if (member "pp" result-params)
+                              org-babel-ruby-pp-wrapper-method
+                            org-babel-ruby-wrapper-method)
+                          body (org-babel-process-file-name tmp-file 
'noquote)))
+                 (org-babel-eval-read-file tmp-file))))
     ;; comint session evaluation
-    (case result-type
-      (output
-       (mapconcat
-       #'identity
-       (butlast
-        (split-string
-         (mapconcat
-          #'org-babel-trim
-          (butlast
-           (org-babel-comint-with-output
-               (buffer org-babel-ruby-eoe-indicator t body)
-             (mapc
-              (lambda (line)
-                (insert (org-babel-chomp line)) (comint-send-input nil t))
-              (list body org-babel-ruby-eoe-indicator))
-             (comint-send-input nil t)) 2)
-          "\n") "[\r\n]")) "\n"))
-      (value
+    (pcase result-type
+      (`output
+       (let ((eoe-string (format "puts \"%s\"" org-babel-ruby-eoe-indicator)))
+        ;; Force the session to be ready before the actual session
+        ;; code is run.  There is some problem in comint that will
+        ;; sometimes show the prompt after the the input has already
+        ;; been inserted and that throws off the extraction of the
+        ;; result for Babel.
+        (org-babel-comint-with-output
+            (buffer org-babel-ruby-eoe-indicator t eoe-string)
+          (insert eoe-string) (comint-send-input nil t))
+        ;; Now we can start the evaluation.
+        (mapconcat
+         #'identity
+         (butlast
+          (split-string
+           (mapconcat
+            #'org-trim
+            (org-babel-comint-with-output
+                (buffer org-babel-ruby-eoe-indicator t body)
+              (mapc
+               (lambda (line)
+                 (insert (org-babel-chomp line)) (comint-send-input nil t))
+               (list 
"conf.echo=false;_org_prompt_mode=conf.prompt_mode;conf.prompt_mode=:NULL"
+                     body
+                     "conf.prompt_mode=_org_prompt_mode;conf.echo=true"
+                     eoe-string)))
+            "\n") "[\r\n]") 4) "\n")))
+      (`value
        (let* ((tmp-file (org-babel-temp-file "ruby-"))
              (ppp (or (member "code" result-params)
                       (member "pp" result-params))))
@@ -247,12 +261,6 @@ return the value of the last statement in BODY, as elisp."
           (comint-send-input nil t))
         (org-babel-eval-read-file tmp-file))))))
 
-(defun org-babel-ruby-read-string (string)
-  "Strip \\\"s from around a ruby string."
-  (if (string-match "^\"\\([^\000]+\\)\"$" string)
-      (match-string 1 string)
-    string))
-
 (provide 'ob-ruby)
 
 
diff --git a/lisp/org/ob-sass.el b/lisp/org/ob-sass.el
index 847c144..a9a2a9f 100644
--- a/lisp/org/ob-sass.el
+++ b/lisp/org/ob-sass.el
@@ -1,4 +1,4 @@
-;;; ob-sass.el --- org-babel functions for the sass css generation language
+;;; ob-sass.el --- Babel Functions for the Sass CSS generation language -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -45,10 +45,9 @@
 (defun org-babel-execute:sass (body params)
   "Execute a block of Sass code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
-         (file (cdr (assoc :file params)))
+  (let* ((file (cdr (assq :file params)))
          (out-file (or file (org-babel-temp-file "sass-out-")))
-         (cmdline (cdr (assoc :cmdline params)))
+         (cmdline (cdr (assq :cmdline params)))
          (in-file (org-babel-temp-file "sass-in-"))
          (cmd (concat "sass " (or cmdline "")
                      " " (org-babel-process-file-name in-file)
@@ -60,7 +59,7 @@ This function is called by `org-babel-execute-src-block'."
        nil ;; signal that output has already been written to file
       (with-temp-buffer (insert-file-contents out-file) (buffer-string)))))
 
-(defun org-babel-prep-session:sass (session params)
+(defun org-babel-prep-session:sass (_session _params)
   "Raise an error because sass does not support sessions."
   (error "Sass does not support sessions"))
 
diff --git a/lisp/org/ob-scala.el b/lisp/org/ob-scala.el
index 9bddeed..7d5f299 100644
--- a/lisp/org/ob-scala.el
+++ b/lisp/org/ob-scala.el
@@ -1,4 +1,4 @@
-;;; ob-scala.el --- org-babel functions for Scala evaluation
+;;; ob-scala.el --- Babel Functions for Scala        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -31,7 +31,6 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (defvar org-babel-tangle-lang-exts) ;; Autoloaded
 (add-to-list 'org-babel-tangle-lang-exts '("scala" . "scala"))
@@ -45,9 +44,8 @@ called by `org-babel-execute-src-block'"
   (message "executing Scala source code block")
   (let* ((processed-params (org-babel-process-params params))
          (session (org-babel-scala-initiate-session (nth 0 processed-params)))
-         (vars (nth 1 processed-params))
          (result-params (nth 2 processed-params))
-         (result-type (cdr (assoc :result-type params)))
+         (result-type (cdr (assq :result-type params)))
          (full-body (org-babel-expand-body:generic
                      body params))
          (result (org-babel-scala-evaluate
@@ -56,17 +54,9 @@ called by `org-babel-execute-src-block'"
     (org-babel-reassemble-table
      result
      (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
      (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
-
-
-(defun org-babel-scala-table-or-string (results)
-  "Convert RESULTS into an appropriate elisp value.
-If RESULTS look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
-  (org-babel-script-escape results))
-
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
 
 (defvar org-babel-scala-wrapper-method
 
@@ -84,19 +74,19 @@ print(str_result)
 
 
 (defun org-babel-scala-evaluate
-  (session body &optional result-type result-params)
+    (session body &optional result-type result-params)
   "Evaluate BODY in external Scala process.
-If RESULT-TYPE equals 'output then return standard output as a string.
-If RESULT-TYPE equals 'value then return the value of the last statement
+If RESULT-TYPE equals `output' then return standard output as a string.
+If RESULT-TYPE equals `value' then return the value of the last statement
 in BODY as elisp."
   (when session (error "Sessions are not (yet) supported for Scala"))
-  (case result-type
-    (output
+  (pcase result-type
+    (`output
      (let ((src-file (org-babel-temp-file "scala-")))
-       (progn (with-temp-file src-file (insert body))
-              (org-babel-eval
-               (concat org-babel-scala-command " " src-file) ""))))
-    (value
+       (with-temp-file src-file (insert body))
+       (org-babel-eval
+       (concat org-babel-scala-command " " src-file) "")))
+    (`value
      (let* ((src-file (org-babel-temp-file "scala-"))
             (wrapper (format org-babel-scala-wrapper-method body)))
        (with-temp-file src-file (insert wrapper))
@@ -104,14 +94,14 @@ in BODY as elisp."
                    (concat org-babel-scala-command " " src-file) "")))
          (org-babel-result-cond result-params
           raw
-           (org-babel-scala-table-or-string raw)))))))
+           (org-babel-script-escape raw)))))))
 
 
-(defun org-babel-prep-session:scala (session params)
+(defun org-babel-prep-session:scala (_session _params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
   (error "Sessions are not (yet) supported for Scala"))
 
-(defun org-babel-scala-initiate-session (&optional session)
+(defun org-babel-scala-initiate-session (&optional _session)
   "If there is not a current inferior-process-buffer in SESSION
 then create.  Return the initialized session.  Sessions are not
 supported in Scala."
diff --git a/lisp/org/ob-scheme.el b/lisp/org/ob-scheme.el
index ae77c7c..cd8c386 100644
--- a/lisp/org/ob-scheme.el
+++ b/lisp/org/ob-scheme.el
@@ -1,4 +1,4 @@
-;;; ob-scheme.el --- org-babel functions for Scheme
+;;; ob-scheme.el --- Babel Functions for Scheme      -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -56,7 +56,7 @@
 
 (defun org-babel-expand-body:scheme (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (if (> (length vars) 0)
         (concat "(let ("
                 (mapconcat
@@ -119,6 +119,22 @@ org-babel-scheme-execute-with-geiser will use a temporary 
session."
               (name))))
     result))
 
+(defmacro org-babel-scheme-capture-current-message (&rest body)
+  "Capture current message in both interactive and noninteractive mode"
+  `(if noninteractive
+       (let ((original-message (symbol-function 'message))
+             (current-message nil))
+         (unwind-protect
+             (progn
+               (defun message (&rest args)
+                 (setq current-message (apply original-message args)))
+               ,@body
+               current-message)
+           (fset 'message original-message)))
+     (progn
+       ,@body
+       (current-message))))
+
 (defun org-babel-scheme-execute-with-geiser (code output impl repl)
   "Execute code in specified REPL. If the REPL doesn't exist, create it
 using the given scheme implementation.
@@ -143,10 +159,11 @@ is true; otherwise returns the last value."
                             (current-buffer)))))
        (setq geiser-repl--repl repl-buffer)
        (setq geiser-impl--implementation nil)
-       (geiser-eval-region (point-min) (point-max))
+       (setq result (org-babel-scheme-capture-current-message
+                     (geiser-eval-region (point-min) (point-max))))
        (setq result
-             (if (equal (substring (current-message) 0 3) "=> ")
-                 (replace-regexp-in-string "^=> " "" (current-message))
+             (if (and (stringp result) (equal (substring result 0 3) "=> "))
+                 (replace-regexp-in-string "^=> " "" result)
                "\"An error occurred.\""))
        (when (not repl)
          (save-current-buffer (set-buffer repl-buffer)
@@ -156,7 +173,7 @@ is true; otherwise returns the last value."
        (setq result (if (or (string= result "#<void>")
                             (string= result "#<unspecified>"))
                         nil
-                      (read result)))))
+                      result))))
     result))
 
 (defun org-babel-execute:scheme (body params)
@@ -168,23 +185,23 @@ This function is called by `org-babel-execute-src-block'"
                              (buffer-name source-buffer))))
     (save-excursion
       (org-babel-reassemble-table
-       (let* ((result-type (cdr (assoc :result-type params)))
-             (impl (or (when (cdr (assoc :scheme params))
-                         (intern (cdr (assoc :scheme params))))
+       (let* ((result-type (cdr (assq :result-type params)))
+             (impl (or (when (cdr (assq :scheme params))
+                         (intern (cdr (assq :scheme params))))
                        geiser-default-implementation
                        (car geiser-active-implementations)))
              (session (org-babel-scheme-make-session-name
-                       source-buffer-name (cdr (assoc :session params)) impl))
+                       source-buffer-name (cdr (assq :session params)) impl))
              (full-body (org-babel-expand-body:scheme body params)))
         (org-babel-scheme-execute-with-geiser
          full-body                      ; code
          (string= result-type "output") ; output?
          impl                           ; implementation
          (and (not (string= session "none")) session))) ; session
-       (org-babel-pick-name (cdr (assoc :colname-names params))
-                           (cdr (assoc :colnames params)))
-       (org-babel-pick-name (cdr (assoc :rowname-names params))
-                           (cdr (assoc :rownames params)))))))
+       (org-babel-pick-name (cdr (assq :colname-names params))
+                           (cdr (assq :colnames params)))
+       (org-babel-pick-name (cdr (assq :rowname-names params))
+                           (cdr (assq :rownames params)))))))
 
 (provide 'ob-scheme)
 
diff --git a/lisp/org/ob-screen.el b/lisp/org/ob-screen.el
index a15f7f7..554f8c4 100644
--- a/lisp/org/ob-screen.el
+++ b/lisp/org/ob-screen.el
@@ -1,4 +1,4 @@
-;;; ob-screen.el --- org-babel support for interactive terminal
+;;; ob-screen.el --- Babel Support for Interactive Terminal -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -48,18 +48,17 @@ In case you want to use a different screen than one 
selected by your $PATH")
 \"default\" session is used when none is specified."
   (message "Sending source code block to interactive terminal session...")
   (save-window-excursion
-    (let* ((session (cdr (assoc :session params)))
+    (let* ((session (cdr (assq :session params)))
            (socket (org-babel-screen-session-socketname session)))
       (unless socket (org-babel-prep-session:screen session params))
       (org-babel-screen-session-execute-string
        session (org-babel-expand-body:generic body params)))))
 
-(defun org-babel-prep-session:screen (session params)
+(defun org-babel-prep-session:screen (_session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
-  (let* ((session (cdr (assoc :session params)))
-         (socket (org-babel-screen-session-socketname session))
-         (cmd (cdr (assoc :cmd params)))
-         (terminal (cdr (assoc :terminal params)))
+  (let* ((session (cdr (assq :session params)))
+         (cmd (cdr (assq :cmd params)))
+         (terminal (cdr (assq :terminal params)))
          (process-name (concat "org-babel: terminal (" session ")")))
     (apply 'start-process process-name "*Messages*"
            terminal `("-T" ,(concat "org-babel: " session) "-e" 
,org-babel-screen-location
@@ -104,7 +103,7 @@ In case you want to use a different screen than one 
selected by your $PATH")
                          sockets)))))
     (when match-socket (car (split-string match-socket)))))
 
-(defun org-babel-screen-session-write-temp-file (session body)
+(defun org-babel-screen-session-write-temp-file (_session body)
   "Save BODY in a temp file that is named after SESSION."
   (let ((tmpfile (org-babel-temp-file "screen-")))
     (with-temp-file tmpfile
@@ -119,11 +118,10 @@ In case you want to use a different screen than one 
selected by your $PATH")
   "Test if the default setup works.
 The terminal should shortly flicker."
   (interactive)
-  (let* ((session "org-babel-testing")
-         (random-string (format "%s" (random 99999)))
+  (let* ((random-string (format "%s" (random 99999)))
          (tmpfile (org-babel-temp-file "ob-screen-test-"))
          (body (concat "echo '" random-string "' > " tmpfile "\nexit\n"))
-         process tmp-string)
+         tmp-string)
     (org-babel-execute:screen body org-babel-default-header-args:screen)
     ;; XXX: need to find a better way to do the following
     (while (not (file-readable-p tmpfile))
diff --git a/lisp/org/ob-sed.el b/lisp/org/ob-sed.el
new file mode 100644
index 0000000..733c7e1
--- /dev/null
+++ b/lisp/org/ob-sed.el
@@ -0,0 +1,107 @@
+;;; ob-sed.el --- Babel Functions for Sed Scripts    -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+;; Author: Bjarte Johansen
+;; Keywords: literate programming, reproducible research
+;; Version: 0.1.0
+
+;; This file is part of GNU Emacs.
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides a way to evaluate sed scripts in Org mode.
+
+;;; Usage:
+
+;; Add to your Emacs config:
+
+;; (org-babel-do-load-languages
+;;  'org-babel-load-languages
+;;  '((sed . t)))
+
+;; In addition to the normal header arguments, ob-sed also provides
+;; :cmd-line and :in-file. :cmd-line allows one to pass other flags to
+;; the sed command like the "--in-place" flag which makes sed edit the
+;; file pass to it instead of outputting to standard out or to a
+;; different file. :in-file is a header arguments that allows one to
+;; tell Org Babel which file the sed script to act on.
+
+;;; Code:
+(require 'ob)
+
+(defvar org-babel-sed-command "sed"
+  "Name of the sed executable command.")
+
+(defvar org-babel-tangle-lang-exts)
+(add-to-list 'org-babel-tangle-lang-exts '("sed" . "sed"))
+
+(defconst org-babel-header-args:sed
+  '((:cmd-line . :any)
+    (:in-file  . :any))
+  "Sed specific header arguments.")
+
+(defvar org-babel-default-header-args:sed '()
+  "Default arguments for evaluating a sed source block.")
+
+(defun org-babel-execute:sed (body params)
+  "Execute a block of sed code with Org Babel.
+BODY is the source inside a sed source block and PARAMS is an
+association list over the source block configurations.  This
+function is called by `org-babel-execute-src-block'."
+  (message "executing sed source code block")
+  (let* ((result-params (cdr (assq :result-params params)))
+         (cmd-line (cdr (assq :cmd-line params)))
+         (in-file (cdr (assq :in-file params)))
+        (code-file (let ((file (org-babel-temp-file "sed-")))
+                      (with-temp-file file
+                       (insert body)) file))
+        (stdin (let ((stdin (cdr (assq :stdin params))))
+                  (when stdin
+                    (let ((tmp (org-babel-temp-file "sed-stdin-"))
+                          (res (org-babel-ref-resolve stdin)))
+                      (with-temp-file tmp
+                        (insert res))
+                      tmp))))
+         (cmd (mapconcat #'identity
+                        (remq nil
+                              (list org-babel-sed-command
+                                    (format "--file=\"%s\"" code-file)
+                                    cmd-line
+                                    in-file))
+                        " ")))
+    (org-babel-reassemble-table
+     (let ((results
+            (cond
+             (stdin (with-temp-buffer
+                      (call-process-shell-command cmd stdin (current-buffer))
+                      (buffer-string)))
+             (t (org-babel-eval cmd "")))))
+       (when results
+         (org-babel-result-cond result-params
+          results
+          (let ((tmp (org-babel-temp-file "sed-results-")))
+            (with-temp-file tmp (insert results))
+            (org-babel-import-elisp-from-file tmp)))))
+     (org-babel-pick-name
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+     (org-babel-pick-name
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
+
+(provide 'ob-sed)
+;;; ob-sed.el ends here
diff --git a/lisp/org/ob-sh.el b/lisp/org/ob-sh.el
deleted file mode 100644
index 47dbab3..0000000
--- a/lisp/org/ob-sh.el
+++ /dev/null
@@ -1,217 +0,0 @@
-;;; ob-sh.el --- org-babel functions for shell evaluation
-
-;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: http://orgmode.org
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org-Babel support for evaluating shell source code.
-
-;;; Code:
-(require 'ob)
-(require 'shell)
-(eval-when-compile (require 'cl))
-
-(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer))
-(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer))
-(declare-function orgtbl-to-generic "org-table"
-                  (table params &optional backend))
-
-(defvar org-babel-default-header-args:sh '())
-
-(defvar org-babel-sh-command "sh"
-  "Command used to invoke a shell.
-This will be passed to  `shell-command-on-region'")
-
-(defcustom org-babel-sh-var-quote-fmt
-  "$(cat <<'BABEL_TABLE'\n%s\nBABEL_TABLE\n)"
-  "Format string used to escape variables when passed to shell scripts."
-  :group 'org-babel
-  :type 'string)
-
-(defun org-babel-execute:sh (body params)
-  "Execute a block of Shell commands with Babel.
-This function is called by `org-babel-execute-src-block'."
-  (let* ((session (org-babel-sh-initiate-session
-                  (cdr (assoc :session params))))
-        (stdin (let ((stdin (cdr (assoc :stdin params))))
-                  (when stdin (org-babel-sh-var-to-string
-                               (org-babel-ref-resolve stdin)))))
-         (full-body (org-babel-expand-body:generic
-                    body params (org-babel-variable-assignments:sh params))))
-    (org-babel-reassemble-table
-     (org-babel-sh-evaluate session full-body params stdin)
-     (org-babel-pick-name
-      (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
-     (org-babel-pick-name
-      (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
-
-(defun org-babel-prep-session:sh (session params)
-  "Prepare SESSION according to the header arguments specified in PARAMS."
-  (let* ((session (org-babel-sh-initiate-session session))
-        (var-lines (org-babel-variable-assignments:sh params)))
-    (org-babel-comint-in-buffer session
-      (mapc (lambda (var)
-              (insert var) (comint-send-input nil t)
-              (org-babel-comint-wait-for-output session)) var-lines))
-    session))
-
-(defun org-babel-load-session:sh (session body params)
-  "Load BODY into SESSION."
-  (save-window-excursion
-    (let ((buffer (org-babel-prep-session:sh session params)))
-      (with-current-buffer buffer
-        (goto-char (process-mark (get-buffer-process (current-buffer))))
-        (insert (org-babel-chomp body)))
-      buffer)))
-
-;; helper functions
-
-(defun org-babel-variable-assignments:sh (params)
-  "Return list of shell statements assigning the block's variables."
-  (let ((sep (cdr (assoc :separator params))))
-    (mapcar
-     (lambda (pair)
-       (format "%s=%s"
-              (car pair)
-              (org-babel-sh-var-to-sh (cdr pair) sep)))
-     (mapcar #'cdr (org-babel-get-header params :var)))))
-
-(defun org-babel-sh-var-to-sh (var &optional sep)
-  "Convert an elisp value to a shell variable.
-Convert an elisp var into a string of shell commands specifying a
-var of the same value."
-  (format org-babel-sh-var-quote-fmt (org-babel-sh-var-to-string var sep)))
-
-(defun org-babel-sh-var-to-string (var &optional sep)
-  "Convert an elisp value to a string."
-  (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
-    (cond
-     ((and (listp var) (or (listp (car var)) (equal (car var) 'hline)))
-      (orgtbl-to-generic var  (list :sep (or sep "\t") :fmt echo-var)))
-     ((listp var)
-      (mapconcat echo-var var "\n"))
-     (t (funcall echo-var var)))))
-
-(defun org-babel-sh-table-or-results (results)
-  "Convert RESULTS to an appropriate elisp value.
-If the results look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
-  (org-babel-script-escape results))
-
-(defun org-babel-sh-initiate-session (&optional session params)
-  "Initiate a session named SESSION according to PARAMS."
-  (when (and session (not (string= session "none")))
-    (save-window-excursion
-      (or (org-babel-comint-buffer-livep session)
-          (progn
-           (shell session)
-           ;; Needed for Emacs 23 since the marker is initially
-           ;; undefined and the filter functions try to use it without
-           ;; checking.
-           (set-marker comint-last-output-start (point))
-           (get-buffer (current-buffer)))))))
-
-(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
-  "String to indicate that evaluation has completed.")
-(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
-  "String to indicate that evaluation has completed.")
-
-(defun org-babel-sh-evaluate (session body &optional params stdin)
-  "Pass BODY to the Shell process in BUFFER.
-If RESULT-TYPE equals 'output then return a list of the outputs
-of the statements in BODY, if RESULT-TYPE equals 'value then
-return the value of the last statement in BODY."
-  (let ((results
-         (cond
-          (stdin                        ; external shell script w/STDIN
-           (let ((script-file (org-babel-temp-file "sh-script-"))
-                 (stdin-file (org-babel-temp-file "sh-stdin-"))
-                 (shebang (cdr (assoc :shebang params)))
-                 (padline (not (string= "no" (cdr (assoc :padline params))))))
-             (with-temp-file script-file
-               (when shebang (insert (concat shebang "\n")))
-               (when padline (insert "\n"))
-               (insert body))
-             (set-file-modes script-file #o755)
-             (with-temp-file stdin-file (insert stdin))
-             (with-temp-buffer
-               (call-process-shell-command
-                (if shebang
-                    script-file
-                  (format "%s %s" org-babel-sh-command script-file))
-                stdin-file
-                (current-buffer))
-               (buffer-string))))
-          (session                      ; session evaluation
-           (mapconcat
-            #'org-babel-sh-strip-weird-long-prompt
-            (mapcar
-             #'org-babel-trim
-             (butlast
-              (org-babel-comint-with-output
-                  (session org-babel-sh-eoe-output t body)
-                (mapc
-                 (lambda (line)
-                   (insert line)
-                   (comint-send-input nil t)
-                   (while (save-excursion
-                            (goto-char comint-last-input-end)
-                            (not (re-search-forward
-                                  comint-prompt-regexp nil t)))
-                     (accept-process-output
-                      (get-buffer-process (current-buffer)))))
-                 (append
-                  (split-string (org-babel-trim body) "\n")
-                  (list org-babel-sh-eoe-indicator))))
-              2)) "\n"))
-          ('otherwise                   ; external shell script
-           (if (and (cdr (assoc :shebang params))
-                    (> (length (cdr (assoc :shebang params))) 0))
-               (let ((script-file (org-babel-temp-file "sh-script-"))
-                     (shebang (cdr (assoc :shebang params)))
-                     (padline (not (equal "no" (cdr (assoc :padline 
params))))))
-                 (with-temp-file script-file
-                   (when shebang (insert (concat shebang "\n")))
-                   (when padline (insert "\n"))
-                   (insert body))
-                 (set-file-modes script-file #o755)
-                 (org-babel-eval script-file ""))
-             (org-babel-eval org-babel-sh-command (org-babel-trim body)))))))
-    (when results
-      (let ((result-params (cdr (assoc :result-params params))))
-        (org-babel-result-cond result-params
-          results
-          (let ((tmp-file (org-babel-temp-file "sh-")))
-            (with-temp-file tmp-file (insert results))
-            (org-babel-import-elisp-from-file tmp-file)))))))
-
-(defun org-babel-sh-strip-weird-long-prompt (string)
-  "Remove prompt cruft from a string of shell output."
-  (while (string-match "^% +[\r\n$]+ *" string)
-    (setq string (substring string (match-end 0))))
-  string)
-
-(provide 'ob-sh)
-
-
-
-;;; ob-sh.el ends here
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
new file mode 100644
index 0000000..3787c26
--- /dev/null
+++ b/lisp/org/ob-shell.el
@@ -0,0 +1,283 @@
+;;; ob-shell.el --- Babel Functions for Shell Evaluation -*- lexical-binding: 
t; -*-
+
+;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating shell source code.
+
+;;; Code:
+(require 'ob)
+(require 'shell)
+(require 'cl-lib)
+
+(declare-function org-babel-comint-in-buffer "ob-comint" (buffer &rest body)
+                 t)
+(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer))
+(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer))
+(declare-function org-babel-comint-with-output "ob-comint" (meta &rest body)
+                 t)
+(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function orgtbl-to-generic "org-table" (table params))
+
+(defvar org-babel-default-header-args:shell '())
+(defvar org-babel-shell-names)
+
+(defun org-babel-shell-initialize ()
+  "Define execution functions associated to shell names.
+This function has to be called whenever `org-babel-shell-names'
+is modified outside the Customize interface."
+  (interactive)
+  (dolist (name org-babel-shell-names)
+    (eval `(defun ,(intern (concat "org-babel-execute:" name))
+              (body params)
+            ,(format "Execute a block of %s commands with Babel." name)
+            (let ((shell-file-name ,name))
+              (org-babel-execute:shell body params))))
+    (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name))
+            'org-babel-variable-assignments:shell
+            ,(format "Return list of %s statements assigning to the block's \
+variables."
+                     name)))))
+
+(defcustom org-babel-shell-names
+  '("sh" "bash" "csh" "ash" "dash" "ksh" "mksh" "posh")
+  "List of names of shell supported by babel shell code blocks.
+Call `org-babel-shell-initialize' when modifying this variable
+outside the Customize interface."
+  :group 'org-babel
+  :type '(repeat (string :tag "Shell name: "))
+  :set (lambda (symbol value)
+        (set-default symbol value)
+        (org-babel-shell-initialize)))
+
+(defun org-babel-execute:shell (body params)
+  "Execute a block of Shell commands with Babel.
+This function is called by `org-babel-execute-src-block'."
+  (let* ((session (org-babel-sh-initiate-session
+                  (cdr (assq :session params))))
+        (stdin (let ((stdin (cdr (assq :stdin params))))
+                  (when stdin (org-babel-sh-var-to-string
+                               (org-babel-ref-resolve stdin)))))
+        (cmdline (cdr (assq :cmdline params)))
+         (full-body (org-babel-expand-body:generic
+                    body params (org-babel-variable-assignments:shell 
params))))
+    (org-babel-reassemble-table
+     (org-babel-sh-evaluate session full-body params stdin cmdline)
+     (org-babel-pick-name
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+     (org-babel-pick-name
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
+
+(defun org-babel-prep-session:shell (session params)
+  "Prepare SESSION according to the header arguments specified in PARAMS."
+  (let* ((session (org-babel-sh-initiate-session session))
+        (var-lines (org-babel-variable-assignments:shell params)))
+    (org-babel-comint-in-buffer session
+      (mapc (lambda (var)
+              (insert var) (comint-send-input nil t)
+              (org-babel-comint-wait-for-output session)) var-lines))
+    session))
+
+(defun org-babel-load-session:shell (session body params)
+  "Load BODY into SESSION."
+  (save-window-excursion
+    (let ((buffer (org-babel-prep-session:shell session params)))
+      (with-current-buffer buffer
+        (goto-char (process-mark (get-buffer-process (current-buffer))))
+        (insert (org-babel-chomp body)))
+      buffer)))
+
+
+;;; Helper functions
+(defun org-babel--variable-assignments:sh-generic
+    (varname values &optional sep hline)
+  "Returns a list of statements declaring the values as a generic variable."
+  (format "%s=%s" varname (org-babel-sh-var-to-sh values sep hline)))
+
+(defun org-babel--variable-assignments:bash_array
+    (varname values &optional sep hline)
+  "Returns a list of statements declaring the values as a bash array."
+  (format "unset %s\ndeclare -a %s=( %s )"
+         varname varname
+         (mapconcat
+          (lambda (value) (org-babel-sh-var-to-sh value sep hline))
+          values
+          " ")))
+
+(defun org-babel--variable-assignments:bash_assoc
+    (varname values &optional sep hline)
+  "Returns a list of statements declaring the values as bash associative 
array."
+  (format "unset %s\ndeclare -A %s\n%s"
+    varname varname
+    (mapconcat
+     (lambda (items)
+       (format "%s[%s]=%s"
+              varname
+              (org-babel-sh-var-to-sh (car items) sep hline)
+              (org-babel-sh-var-to-sh (cdr items) sep hline)))
+     values
+     "\n")))
+
+(defun org-babel--variable-assignments:bash (varname values &optional sep 
hline)
+  "Represents the parameters as useful Bash shell variables."
+  (pcase values
+    (`((,_ ,_ . ,_) . ,_)              ;two-dimensional array
+     (org-babel--variable-assignments:bash_assoc varname values sep hline))
+    (`(,_ . ,_)                                ;simple list
+     (org-babel--variable-assignments:bash_array varname values sep hline))
+    (_                                 ;scalar value
+     (org-babel--variable-assignments:sh-generic varname values sep hline))))
+
+(defun org-babel-variable-assignments:shell (params)
+  "Return list of shell statements assigning the block's variables."
+  (let ((sep (cdr (assq :separator params)))
+       (hline (when (string= "yes" (cdr (assq :hlines params)))
+                (or (cdr (assq :hline-string params))
+                    "hline"))))
+    (mapcar
+     (lambda (pair)
+       (if (string-suffix-p "bash" shell-file-name)
+          (org-babel--variable-assignments:bash
+            (car pair) (cdr pair) sep hline)
+         (org-babel--variable-assignments:sh-generic
+         (car pair) (cdr pair) sep hline)))
+     (org-babel--get-vars params))))
+
+(defun org-babel-sh-var-to-sh (var &optional sep hline)
+  "Convert an elisp value to a shell variable.
+Convert an elisp var into a string of shell commands specifying a
+var of the same value."
+  (concat "'" (replace-regexp-in-string
+              "'" "'\"'\"'"
+              (org-babel-sh-var-to-string var sep hline))
+         "'"))
+
+(defun org-babel-sh-var-to-string (var &optional sep hline)
+  "Convert an elisp value to a string."
+  (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
+    (cond
+     ((and (listp var) (or (listp (car var)) (eq (car var) 'hline)))
+      (orgtbl-to-generic var  (list :sep (or sep "\t") :fmt echo-var
+                                   :hline hline)))
+     ((listp var)
+      (mapconcat echo-var var "\n"))
+     (t (funcall echo-var var)))))
+
+(defun org-babel-sh-initiate-session (&optional session _params)
+  "Initiate a session named SESSION according to PARAMS."
+  (when (and session (not (string= session "none")))
+    (save-window-excursion
+      (or (org-babel-comint-buffer-livep session)
+          (progn
+           (shell session)
+           ;; Needed for Emacs 23 since the marker is initially
+           ;; undefined and the filter functions try to use it without
+           ;; checking.
+           (set-marker comint-last-output-start (point))
+           (get-buffer (current-buffer)))))))
+
+(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
+  "String to indicate that evaluation has completed.")
+(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
+  "String to indicate that evaluation has completed.")
+
+(defun org-babel-sh-evaluate (session body &optional params stdin cmdline)
+  "Pass BODY to the Shell process in BUFFER.
+If RESULT-TYPE equals `output' then return a list of the outputs
+of the statements in BODY, if RESULT-TYPE equals `value' then
+return the value of the last statement in BODY."
+  (let ((results
+         (cond
+          ((or stdin cmdline)         ; external shell script w/STDIN
+           (let ((script-file (org-babel-temp-file "sh-script-"))
+                 (stdin-file (org-babel-temp-file "sh-stdin-"))
+                 (shebang (cdr (assq :shebang params)))
+                 (padline (not (string= "no" (cdr (assq :padline params))))))
+             (with-temp-file script-file
+               (when shebang (insert (concat shebang "\n")))
+               (when padline (insert "\n"))
+               (insert body))
+             (set-file-modes script-file #o755)
+             (with-temp-file stdin-file (insert (or stdin "")))
+             (with-temp-buffer
+               (call-process-shell-command
+                (concat (if shebang script-file
+                         (format "%s %s" shell-file-name script-file))
+                       (and cmdline (concat " " cmdline)))
+                stdin-file
+               (current-buffer))
+               (buffer-string))))
+          (session                      ; session evaluation
+           (mapconcat
+            #'org-babel-sh-strip-weird-long-prompt
+            (mapcar
+             #'org-trim
+             (butlast
+              (org-babel-comint-with-output
+                  (session org-babel-sh-eoe-output t body)
+                (mapc
+                 (lambda (line)
+                   (insert line)
+                   (comint-send-input nil t)
+                   (while (save-excursion
+                            (goto-char comint-last-input-end)
+                            (not (re-search-forward
+                                  comint-prompt-regexp nil t)))
+                     (accept-process-output
+                      (get-buffer-process (current-buffer)))))
+                 (append
+                  (split-string (org-trim body) "\n")
+                  (list org-babel-sh-eoe-indicator))))
+              2)) "\n"))
+          ('otherwise                   ; external shell script
+           (if (and (cdr (assq :shebang params))
+                    (> (length (cdr (assq :shebang params))) 0))
+               (let ((script-file (org-babel-temp-file "sh-script-"))
+                     (shebang (cdr (assq :shebang params)))
+                     (padline (not (equal "no" (cdr (assq :padline params))))))
+                 (with-temp-file script-file
+                   (when shebang (insert (concat shebang "\n")))
+                   (when padline (insert "\n"))
+                   (insert body))
+                 (set-file-modes script-file #o755)
+                 (org-babel-eval script-file ""))
+             (org-babel-eval shell-file-name (org-trim body)))))))
+    (when results
+      (let ((result-params (cdr (assq :result-params params))))
+        (org-babel-result-cond result-params
+          results
+          (let ((tmp-file (org-babel-temp-file "sh-")))
+            (with-temp-file tmp-file (insert results))
+            (org-babel-import-elisp-from-file tmp-file)))))))
+
+(defun org-babel-sh-strip-weird-long-prompt (string)
+  "Remove prompt cruft from a string of shell output."
+  (while (string-match "^% +[\r\n$]+ *" string)
+    (setq string (substring string (match-end 0))))
+  string)
+
+(provide 'ob-shell)
+
+
+
+;;; ob-shell.el ends here
diff --git a/lisp/org/ob-shen.el b/lisp/org/ob-shen.el
index d44a48a..6bf36c6 100644
--- a/lisp/org/ob-shen.el
+++ b/lisp/org/ob-shen.el
@@ -1,4 +1,4 @@
-;;; ob-shen.el --- org-babel functions for Shen
+;;; ob-shen.el --- Babel Functions for Shen          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -43,7 +43,7 @@
 
 (defun org-babel-expand-body:shen (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+  (let ((vars (org-babel--get-vars params)))
     (if (> (length vars) 0)
         (concat "(let "
                 (mapconcat (lambda (var)
@@ -63,14 +63,13 @@
   "Execute a block of Shen code with org-babel.
 This function is called by `org-babel-execute-src-block'"
   (require 'inf-shen)
-  (let* ((result-type (cdr (assoc :result-type params)))
-        (result-params (cdr (assoc :result-params params)))
+  (let* ((result-params (cdr (assq :result-params params)))
          (full-body (org-babel-expand-body:shen body params)))
     (let ((results
            (with-temp-buffer
              (insert full-body)
              (call-interactively #'shen-eval-defun))))
-      (org-babel-result-cond result-params 
+      (org-babel-result-cond result-params
         results
         (condition-case nil (org-babel-script-escape results)
           (error results))))))
diff --git a/lisp/org/ob-sql.el b/lisp/org/ob-sql.el
index 1777582..06477d3 100644
--- a/lisp/org/ob-sql.el
+++ b/lisp/org/ob-sql.el
@@ -1,4 +1,4 @@
-;;; ob-sql.el --- org-babel functions for sql evaluation
+;;; ob-sql.el --- Babel Functions for SQL            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -36,6 +36,7 @@
 ;; - engine
 ;; - cmdline
 ;; - dbhost
+;; - dbport
 ;; - dbuser
 ;; - dbpassword
 ;; - database
@@ -56,11 +57,11 @@
 
 ;;; Code:
 (require 'ob)
-(eval-when-compile (require 'cl))
 
 (declare-function org-table-import "org-table" (file arg))
 (declare-function orgtbl-to-csv "org-table" (table params))
 (declare-function org-table-to-lisp "org-table" (&optional txt))
+(declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file 
&optional absolute-p))
 
 (defvar org-babel-default-header-args:sql '())
 
@@ -68,6 +69,7 @@
   '((engine           . :any)
     (out-file         . :any)
     (dbhost           . :any)
+    (dbport           . :any)
     (dbuser           . :any)
     (dbpassword               . :any)
     (database         . :any))
@@ -76,98 +78,167 @@
 (defun org-babel-expand-body:sql (body params)
   "Expand BODY according to the values of PARAMS."
   (org-babel-sql-expand-vars
-   body (mapcar #'cdr (org-babel-get-header params :var))))
+   body (org-babel--get-vars params)))
 
-(defun dbstring-mysql (host user password database)
+(defun org-babel-sql-dbstring-mysql (host port user password database)
   "Make MySQL cmd line args for database connection.  Pass nil to omit that 
arg."
   (combine-and-quote-strings
-   (remq nil
+   (delq nil
         (list (when host     (concat "-h" host))
+              (when port     (format "-P%d" port))
               (when user     (concat "-u" user))
               (when password (concat "-p" password))
               (when database (concat "-D" database))))))
 
+(defun org-babel-sql-dbstring-postgresql (host port user database)
+  "Make PostgreSQL command line args for database connection.
+Pass nil to omit that arg."
+  (combine-and-quote-strings
+   (delq nil
+        (list (when host (concat "-h" host))
+              (when port (format "-p%d" port))
+              (when user (concat "-U" user))
+              (when database (concat "-d" database))))))
+
+(defun org-babel-sql-dbstring-oracle (host port user password database)
+  "Make Oracle command line args for database connection."
+  (format "%s/address@hidden:%s/%s" user password host port database))
+
+(defun org-babel-sql-dbstring-mssql (host user password database)
+  "Make sqlcmd commmand line args for database connection.
+`sqlcmd' is the preferred command line tool to access Microsoft
+SQL Server on Windows and Linux platform."
+  (mapconcat #'identity
+            (delq nil
+                  (list (when host (format "-S \"%s\"" host))
+                        (when user (format "-U \"%s\"" user))
+                        (when password (format "-P \"%s\"" password))
+                        (when database (format "-d \"%s\"" database))))
+            " "))
+
+(defun org-babel-sql-convert-standard-filename (file)
+  "Convert FILE to OS standard file name.
+If in Cygwin environment, uses Cygwin specific function to
+convert the file name.  In a Windows-NT environment, do nothing.
+Otherwise, use Emacs' standard conversion function."
+  (cond ((fboundp 'cygwin-convert-file-name-to-windows)
+        (format "%S" (cygwin-convert-file-name-to-windows file)))
+       ((string= "windows-nt" system-type) file)
+       (t (format "%S" (convert-standard-filename file)))))
+
 (defun org-babel-execute:sql (body params)
   "Execute a block of Sql code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (cdr (assoc :result-params params)))
-         (cmdline (cdr (assoc :cmdline params)))
-         (dbhost (cdr (assoc :dbhost params)))
-         (dbuser (cdr (assoc :dbuser params)))
-         (dbpassword (cdr (assoc :dbpassword params)))
-         (database (cdr (assoc :database params)))
-         (engine (cdr (assoc :engine params)))
-         (colnames-p (not (equal "no" (cdr (assoc :colnames params)))))
+  (let* ((result-params (cdr (assq :result-params params)))
+         (cmdline (cdr (assq :cmdline params)))
+         (dbhost (cdr (assq :dbhost params)))
+         (dbport (cdr (assq :dbport params)))
+         (dbuser (cdr (assq :dbuser params)))
+         (dbpassword (cdr (assq :dbpassword params)))
+         (database (cdr (assq :database params)))
+         (engine (cdr (assq :engine params)))
+         (colnames-p (not (equal "no" (cdr (assq :colnames params)))))
          (in-file (org-babel-temp-file "sql-in-"))
-         (out-file (or (cdr (assoc :out-file params))
+         (out-file (or (cdr (assq :out-file params))
                        (org-babel-temp-file "sql-out-")))
         (header-delim "")
-         (command (case (intern engine)
-                    ('dbi (format "dbish --batch %s < %s | sed '%s' > %s"
+         (command (pcase (intern engine)
+                    (`dbi (format "dbish --batch %s < %s | sed '%s' > %s"
                                  (or cmdline "")
                                  (org-babel-process-file-name in-file)
                                  "/^+/d;s/^|//;s/(NULL)/ /g;$d"
                                  (org-babel-process-file-name out-file)))
-                    ('monetdb (format "mclient -f tab %s < %s > %s"
-                                      (or cmdline "")
-                                      (org-babel-process-file-name in-file)
-                                      (org-babel-process-file-name out-file)))
-                    ('msosql (format "osql %s -s \"\t\" -i %s -o %s"
-                                     (or cmdline "")
-                                     (org-babel-process-file-name in-file)
-                                     (org-babel-process-file-name out-file)))
-                    ('mysql (format "mysql %s %s %s < %s > %s"
-                                   (dbstring-mysql dbhost dbuser dbpassword 
database)
+                    (`monetdb (format "mclient -f tab %s < %s > %s"
+                                     (or cmdline "")
+                                     (org-babel-process-file-name in-file)
+                                     (org-babel-process-file-name out-file)))
+                   (`mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s"
+                                   (or cmdline "")
+                                   (org-babel-sql-dbstring-mssql
+                                    dbhost dbuser dbpassword database)
+                                   (org-babel-sql-convert-standard-filename
+                                    (org-babel-process-file-name in-file))
+                                   (org-babel-sql-convert-standard-filename
+                                    (org-babel-process-file-name out-file))))
+                    (`mysql (format "mysql %s %s %s < %s > %s"
+                                   (org-babel-sql-dbstring-mysql
+                                    dbhost dbport dbuser dbpassword database)
                                    (if colnames-p "" "-N")
-                                    (or cmdline "")
+                                   (or cmdline "")
                                    (org-babel-process-file-name in-file)
                                    (org-babel-process-file-name out-file)))
-                   ('postgresql (format
-                                 "psql -A -P footer=off -F \"\t\"  -f %s -o %s 
%s"
+                   (`postgresql (format
+                                 "%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \
+footer=off -F \"\t\"  %s -f %s -o %s %s"
+                                 (if dbpassword
+                                     (format "PGPASSWORD=%s " dbpassword)
+                                   "")
+                                 (if colnames-p "" "-t")
+                                 (org-babel-sql-dbstring-postgresql
+                                  dbhost dbport dbuser database)
                                  (org-babel-process-file-name in-file)
                                  (org-babel-process-file-name out-file)
                                  (or cmdline "")))
-                    (t (error "No support for the %s SQL engine" engine)))))
+                    (`oracle (format
+                             "sqlplus -s %s < %s > %s"
+                             (org-babel-sql-dbstring-oracle
+                              dbhost dbport dbuser dbpassword database)
+                             (org-babel-process-file-name in-file)
+                             (org-babel-process-file-name out-file)))
+                    (_ (error "No support for the %s SQL engine" engine)))))
     (with-temp-file in-file
       (insert
-       (case (intern engine)
-        ('dbi "/format partbox\n")
-        (t ""))
+       (pcase (intern engine)
+        (`dbi "/format partbox\n")
+         (`oracle "SET PAGESIZE 50000
+SET NEWPAGE 0
+SET TAB OFF
+SET SPACE 0
+SET LINESIZE 9999
+SET ECHO OFF
+SET FEEDBACK OFF
+SET VERIFY OFF
+SET HEADING ON
+SET MARKUP HTML OFF SPOOL OFF
+SET COLSEP '|'
+
+")
+        (`mssql "SET NOCOUNT ON
+
+")
+        (_ ""))
        (org-babel-expand-body:sql body params)))
-    (message command)
     (org-babel-eval command "")
     (org-babel-result-cond result-params
       (with-temp-buffer
-         (progn (insert-file-contents-literally out-file) (buffer-string)))
+       (progn (insert-file-contents-literally out-file) (buffer-string)))
       (with-temp-buffer
        (cond
-         ((or (eq (intern engine) 'mysql)
-              (eq (intern engine) 'dbi)
-              (eq (intern engine) 'postgresql))
-          ;; Add header row delimiter after column-names header in first line
-          (cond
-           (colnames-p
-            (with-temp-buffer
-              (insert-file-contents out-file)
-              (goto-char (point-min))
-              (forward-line 1)
-              (insert "-\n")
-              (setq header-delim "-")
-              (write-file out-file)))))
-         (t
-          ;; Need to figure out the delimiter for the header row
-          (with-temp-buffer
-            (insert-file-contents out-file)
-            (goto-char (point-min))
-            (when (re-search-forward "^\\(-+\\)[^-]" nil t)
-              (setq header-delim (match-string-no-properties 1)))
-            (goto-char (point-max))
-            (forward-char -1)
-            (while (looking-at "\n")
-              (delete-char 1)
-              (goto-char (point-max))
-              (forward-char -1))
-            (write-file out-file))))
+        ((memq (intern engine) '(dbi mysql postgresql))
+         ;; Add header row delimiter after column-names header in first line
+         (cond
+          (colnames-p
+           (with-temp-buffer
+             (insert-file-contents out-file)
+             (goto-char (point-min))
+             (forward-line 1)
+             (insert "-\n")
+             (setq header-delim "-")
+             (write-file out-file)))))
+        (t
+         ;; Need to figure out the delimiter for the header row
+         (with-temp-buffer
+           (insert-file-contents out-file)
+           (goto-char (point-min))
+           (when (re-search-forward "^\\(-+\\)[^-]" nil t)
+             (setq header-delim (match-string-no-properties 1)))
+           (goto-char (point-max))
+           (forward-char -1)
+           (while (looking-at "\n")
+             (delete-char 1)
+             (goto-char (point-max))
+             (forward-char -1))
+           (write-file out-file))))
        (org-table-import out-file '(16))
        (org-babel-reassemble-table
         (mapcar (lambda (x)
@@ -175,10 +246,10 @@ This function is called by `org-babel-execute-src-block'."
                       'hline
                     x))
                 (org-table-to-lisp))
-        (org-babel-pick-name (cdr (assoc :colname-names params))
-                             (cdr (assoc :colnames params)))
-        (org-babel-pick-name (cdr (assoc :rowname-names params))
-                             (cdr (assoc :rownames params))))))))
+        (org-babel-pick-name (cdr (assq :colname-names params))
+                             (cdr (assq :colnames params)))
+        (org-babel-pick-name (cdr (assq :rowname-names params))
+                             (cdr (assq :rownames params))))))))
 
 (defun org-babel-sql-expand-vars (body vars)
   "Expand the variables held in VARS in BODY."
@@ -201,7 +272,7 @@ This function is called by `org-babel-execute-src-block'."
    vars)
   body)
 
-(defun org-babel-prep-session:sql (session params)
+(defun org-babel-prep-session:sql (_session _params)
   "Raise an error because Sql sessions aren't implemented."
   (error "SQL sessions not yet implemented"))
 
diff --git a/lisp/org/ob-sqlite.el b/lisp/org/ob-sqlite.el
index 4b165dc..8094019 100644
--- a/lisp/org/ob-sqlite.el
+++ b/lisp/org/ob-sqlite.el
@@ -1,4 +1,4 @@
-;;; ob-sqlite.el --- org-babel functions for sqlite database interaction
+;;; ob-sqlite.el --- Babel Functions for SQLite Databases -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -53,23 +53,22 @@
 (defun org-babel-expand-body:sqlite (body params)
   "Expand BODY according to the values of PARAMS."
   (org-babel-sqlite-expand-vars
-   body (mapcar #'cdr (org-babel-get-header params :var))))
+   body (org-babel--get-vars params)))
 
 (defvar org-babel-sqlite3-command "sqlite3")
 
 (defun org-babel-execute:sqlite (body params)
   "Execute a block of Sqlite code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let ((result-params (split-string (or (cdr (assoc :results params)) "")))
-       (db (cdr (assoc :db params)))
-       (separator (cdr (assoc :separator params)))
-       (nullvalue (cdr (assoc :nullvalue params)))
-       (headers-p (equal "yes" (cdr (assoc :colnames params))))
+  (let ((result-params (split-string (or (cdr (assq :results params)) "")))
+       (db (cdr (assq :db params)))
+       (separator (cdr (assq :separator params)))
+       (nullvalue (cdr (assq :nullvalue params)))
+       (headers-p (equal "yes" (cdr (assq :colnames params))))
        (others (delq nil (mapcar
-                          (lambda (arg) (car (assoc arg params)))
+                          (lambda (arg) (car (assq arg params)))
                           (list :header :echo :bail :column
-                                :csv :html :line :list))))
-       exit-code)
+                                :csv :html :line :list)))))
     (unless db (error "ob-sqlite: can't evaluate without a database"))
     (with-temp-buffer
       (insert
@@ -140,7 +139,7 @@ This function is called by `org-babel-execute-src-block'."
           (equal 1 (length (car result))))
       (org-babel-read (caar result))
     (mapcar (lambda (row)
-             (if (equal 'hline row)
+             (if (eq 'hline row)
                  'hline
                (mapcar #'org-babel-string-read row))) result)))
 
@@ -150,7 +149,7 @@ This function is called by `org-babel-execute-src-block'."
       (cons (car table) (cons 'hline (cdr table)))
     table))
 
-(defun org-babel-prep-session:sqlite (session params)
+(defun org-babel-prep-session:sqlite (_session _params)
   "Raise an error because support for SQLite sessions isn't implemented.
 Prepare SESSION according to the header arguments specified in PARAMS."
   (error "SQLite sessions not yet implemented"))
diff --git a/lisp/org/ob-stan.el b/lisp/org/ob-stan.el
new file mode 100644
index 0000000..40dd0ef
--- /dev/null
+++ b/lisp/org/ob-stan.el
@@ -0,0 +1,84 @@
+;;; ob-stan.el --- Babel Functions for Stan          -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+;; Author: Kyle Meyer
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating Stan [1] source code.
+;;
+;; Evaluating a Stan block can produce two different results.
+;;
+;; 1) Dump the source code contents to a file.
+;;
+;;    This file can then be used as a variable in other blocks, which
+;;    allows interfaces like RStan to use the model.
+;;
+;; 2) Compile the contents to a model file.
+;;
+;;    This provides access to the CmdStan interface.  To use this, set
+;;    `org-babel-stan-cmdstan-directory' and provide a :file argument
+;;    that does not end in ".stan".
+;;
+;; For more information and usage examples, visit
+;; http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html
+;;
+;; [1] http://mc-stan.org/
+
+;;; Code:
+(require 'ob)
+(require 'org-compat)
+
+(defcustom org-babel-stan-cmdstan-directory nil
+  "CmdStan source directory.
+'make' will be called from this directory to compile the Stan
+block.  When nil, executing Stan blocks dumps the content to a
+plain text file."
+  :group 'org-babel
+  :type 'string)
+
+(defvar org-babel-default-header-args:stan
+  '((:results . "file")))
+
+(defun org-babel-execute:stan (body params)
+  "Generate Stan file from BODY according to PARAMS.
+A :file header argument must be given.  If
+`org-babel-stan-cmdstan-directory' is non-nil and the file name
+does not have a \".stan\" extension, save an intermediate
+\".stan\" file and compile the block to the named file.
+Otherwise, write the Stan code directly to the named file."
+  (let ((file (expand-file-name
+              (or (cdr (assq :file params))
+                  (user-error "Set :file argument to execute Stan blocks")))))
+    (if (or (not org-babel-stan-cmdstan-directory)
+           (string-match-p "\\.stan\\'" file))
+       (with-temp-file file (insert body))
+      (with-temp-file (concat file ".stan") (insert body))
+      (let ((default-directory org-babel-stan-cmdstan-directory))
+       (call-process-shell-command (concat "make " file))))
+    nil))              ; Signal that output has been written to file.
+
+(defun org-babel-prep-session:stan (_session _params)
+  "Return an error because Stan does not support sessions."
+  (user-error "Stan does not support sessions"))
+
+(provide 'ob-stan)
+;;; ob-stan.el ends here
diff --git a/lisp/org/ob-table.el b/lisp/org/ob-table.el
index 1fa9105..4de8936 100644
--- a/lisp/org/ob-table.el
+++ b/lisp/org/ob-table.el
@@ -1,4 +1,4 @@
-;;; ob-table.el --- support for calling org-babel functions from tables
+;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -23,8 +23,8 @@
 
 ;;; Commentary:
 
-;; Should allow calling functions from org-mode tables using the
-;; function `org-sbe' as so...
+;; Should allow calling functions from Org tables using the function
+;; `org-sbe' as so...
 
 ;; #+begin_src emacs-lisp :results silent
 ;;   (defun fibbd (n) (if (< n 2) 1 (+ (fibbd (- n 1)) (fibbd (- n 2)))))
@@ -47,38 +47,50 @@
 ;; |        7 |        |
 ;; |        8 |        |
 ;; |        9 |        |
-;; #+TBLFM: $2='(org-sbe 'fibbd (n $1))
+;; #+TBLFM: $2='(org-sbe "fibbd" (n $1))
+
+;; NOTE: The quotation marks around the function name, 'fibbd' here,
+;; are optional.
 
 ;;; Code:
 (require 'ob-core)
 
+(declare-function org-trim "org" (s &optional keep-lead))
+
 (defun org-babel-table-truncate-at-newline (string)
   "Replace newline character with ellipses.
 If STRING ends in a newline character, then remove the newline
 character and replace it with ellipses."
   (if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string))
       (concat (substring string 0 (match-beginning 0))
-             (if (match-string 1 string) "...")) string))
+             (when (match-string 1 string) "...")) string))
 
 (defmacro org-sbe (source-block &rest variables)
   "Return the results of calling SOURCE-BLOCK with VARIABLES.
-Each element of VARIABLES should be a two
-element list, whose first element is the name of the variable and
-second element is a string of its value.  The following call to
-`org-sbe' would be equivalent to the following source code block.
 
- (org-sbe \\='source-block (n $2) (m 3))
+Each element of VARIABLES should be a list of two elements: the
+first element is the name of the variable and second element is a
+string of its value.
+
+So this `org-sbe' construct
+
+ (org-sbe \"source-block\" (n $2) (m 3))
+
+is the equivalent of the following source code block:
+
+ #+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) 
:results silent
+ results
+ #+end_src
 
-#+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) :results 
silent
-results
-#+end_src
+NOTE: The quotation marks around the function name,
+'source-block', are optional.
 
-NOTE: by default string variable names are interpreted as
+NOTE: By default, string variable names are interpreted as
 references to source-code blocks, to force interpretation of a
 cell's value as a string, prefix the identifier a \"$\" (e.g.,
 \"$$2\" instead of \"$2\" or \"address@hidden" instead of \"@2$2\").
 
-NOTE: it is also possible to pass header arguments to the code
+NOTE: It is also possible to pass header arguments to the code
 block.  In this case a table cell should hold the string value of
 the header argument which can then be passed before all variables
 as shown in the example below.
@@ -132,7 +144,7 @@ as shown in the example below.
                     nil (list "emacs-lisp" "results" params)
                     '((:results . "silent"))))
                "")))
-        (org-babel-trim (if (stringp result) result (format "%S" result)))))))
+        (org-trim (if (stringp result) result (format "%S" result)))))))
 
 (provide 'ob-table)
 
diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el
index 437e0a2..3b05332 100644
--- a/lisp/org/ob-tangle.el
+++ b/lisp/org/ob-tangle.el
@@ -1,4 +1,4 @@
-;;; ob-tangle.el --- extract source code from org-mode files
+;;; ob-tangle.el --- Extract Source Code From Org Files -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -26,22 +26,35 @@
 ;; Extract the code from source blocks out into raw source-code files.
 
 ;;; Code:
+
+(require 'cl-lib)
 (require 'org-src)
-(eval-when-compile
-  (require 'cl))
 
+(declare-function make-directory "files" (dir &optional parents))
+(declare-function org-at-heading-p "org" (&optional ignored))
+(declare-function org-babel-update-block-body "ob-core" (new-body))
+(declare-function org-back-to-heading "org" (&optional invisible-ok))
+(declare-function org-before-first-heading-p "org" ())
 (declare-function org-edit-special "org" (&optional arg))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-type "org-element" (element))
+(declare-function org-fill-template "org" (template alist))
+(declare-function org-heading-components "org" ())
+(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
 (declare-function org-link-escape "org" (text &optional table merge))
-(declare-function org-store-link "org" (arg))
 (declare-function org-open-link-from-string "org" (s &optional arg 
reference-buffer))
-(declare-function org-heading-components "org" ())
-(declare-function org-back-to-heading "org" (&optional invisible-ok))
-(declare-function org-fill-template "org" (template alist))
-(declare-function org-babel-update-block-body "ob-core" (new-body))
-(declare-function make-directory "files" (dir &optional parents))
+(declare-function org-remove-indentation "org" (code &optional n))
+(declare-function org-store-link "org" (arg))
+(declare-function org-string-nw-p "org-macs" (s))
+(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function outline-previous-heading "outline" ())
+(declare-function org-id-find "org-id" (id &optional markerp))
+
+(defvar org-link-types-re)
 
 (defcustom org-babel-tangle-lang-exts
-  '(("emacs-lisp" . "el"))
+  '(("emacs-lisp" . "el")
+    ("elisp" . "el"))
   "Alist mapping languages to their file extensions.
 The key is the language name, the value is the string that should
 be inserted as the extension commonly used to identify files
@@ -54,6 +67,11 @@ then the name of the language is used."
           (string "Language name")
           (string "File Extension"))))
 
+(defcustom org-babel-tangle-use-relative-file-links t
+  "Use relative path names in links from tangled source back the Org file."
+  :group 'org-babel-tangle
+  :type 'boolean)
+
 (defcustom org-babel-post-tangle-hook nil
   "Hook run in code files tangled by `org-babel-tangle'."
   :group 'org-babel
@@ -78,9 +96,14 @@ The following format strings can be used to insert special
 information into the output using `org-fill-template'.
 %start-line --- the line number at the start of the code block
 %file --------- the file from which the code block was tangled
-%link --------- Org-mode style link to the code block
+%link --------- Org style link to the code block
 %source-name -- name of the code block
 
+Upon insertion the formatted comment will be commented out, and
+followed by a newline.  To inhibit this post-insertion processing
+set the `org-babel-tangle-uncomment-comments' variable to a
+non-nil value.
+
 Whether or not comments are inserted during tangling is
 controlled by the :comments header argument."
   :group 'org-babel
@@ -93,20 +116,33 @@ The following format strings can be used to insert special
 information into the output using `org-fill-template'.
 %start-line --- the line number at the start of the code block
 %file --------- the file from which the code block was tangled
-%link --------- Org-mode style link to the code block
+%link --------- Org style link to the code block
 %source-name -- name of the code block
 
+Upon insertion the formatted comment will be commented out, and
+followed by a newline.  To inhibit this post-insertion processing
+set the `org-babel-tangle-uncomment-comments' variable to a
+non-nil value.
+
 Whether or not comments are inserted during tangling is
 controlled by the :comments header argument."
   :group 'org-babel
   :version "24.1"
   :type 'string)
 
-(defcustom org-babel-process-comment-text #'org-babel-trim
-  "Function called to process raw Org-mode text collected to be
+(defcustom org-babel-tangle-uncomment-comments nil
+  "Inhibits automatic commenting and addition of trailing newline
+of tangle comments.  Use `org-babel-tangle-comment-format-beg'
+and `org-babel-tangle-comment-format-end' to customize the format
+of tangled comments."
+  :group 'org-babel
+  :type 'boolean)
+
+(defcustom org-babel-process-comment-text 'org-remove-indentation
+  "Function called to process raw Org text collected to be
 inserted as comments in tangled source-code files.  The function
 should take a single string argument and return a string
-result.  The default value is `org-babel-trim'."
+result.  The default value is `org-remove-indentation'."
   :group 'org-babel
   :version "24.1"
   :type 'function)
@@ -153,12 +189,14 @@ Return a list whose CAR is the tangled file name."
        (save-window-excursion
          (find-file file)
          (setq to-be-removed (current-buffer))
-         (org-babel-tangle nil target-file lang))
+         (mapcar #'expand-file-name (org-babel-tangle nil target-file lang)))
       (unless visited-p
        (kill-buffer to-be-removed)))))
 
 (defun org-babel-tangle-publish (_ filename pub-dir)
   "Tangle FILENAME and place the results in PUB-DIR."
+  (unless (file-exists-p pub-dir)
+    (make-directory pub-dir t))
   (mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file 
filename)))
 
 ;;;###autoload
@@ -176,12 +214,12 @@ used to limit the exported source code blocks by 
language."
   (run-hooks 'org-babel-pre-tangle-hook)
   ;; Possibly Restrict the buffer to the current code block
   (save-restriction
-    (when (equal arg '(4))
-      (let ((head (org-babel-where-is-src-block-head)))
+    (save-excursion
+      (when (equal arg '(4))
+       (let ((head (org-babel-where-is-src-block-head)))
          (if head
              (goto-char head)
            (user-error "Point is not in a source code block"))))
-    (save-excursion
       (let ((block-counter 0)
            (org-babel-default-header-args
             (if target-file
@@ -190,7 +228,7 @@ used to limit the exported source code blocks by language."
               org-babel-default-header-args))
            (tangle-file
             (when (equal arg '(16))
-              (or (cdr (assoc :tangle (nth 2 (org-babel-get-src-block-info 
'light))))
+              (or (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 
'light))))
                   (user-error "Point is not in a source code block"))))
            path-collector)
        (mapc ;; map over all languages
@@ -216,7 +254,7 @@ used to limit the exported source code blocks by language."
                         (base-name (cond
                                     ((string= "yes" tangle)
                                      (file-name-sans-extension
-                                      (buffer-file-name)))
+                                      (nth 1 spec)))
                                     ((string= "no" tangle) nil)
                                     ((> (length tangle) 0) tangle)))
                         (file-name (when base-name
@@ -243,9 +281,13 @@ used to limit the exported source code blocks by language."
                        ;; We avoid append-to-file as it does not work with 
tramp.
                        (let ((content (buffer-string)))
                          (with-temp-buffer
-                           (if (file-exists-p file-name)
-                               (insert-file-contents file-name))
+                           (when (file-exists-p file-name)
+                             (insert-file-contents file-name))
                            (goto-char (point-max))
+                           ;; Handle :padlines unless first line in file
+                           (unless (or (string= "no" (cdr (assq :padline (nth 
4 spec))))
+                                       (= (point) (point-min)))
+                             (insert "\n"))
                            (insert content)
                            (write-region nil nil file-name))))
                      ;; if files contain she-bangs, then make the executable
@@ -253,10 +295,8 @@ used to limit the exported source code blocks by language."
                        (unless tangle-mode (setq tangle-mode #o755)))
                      ;; update counter
                      (setq block-counter (+ 1 block-counter))
-                     (add-to-list 'path-collector
-                                  (cons file-name tangle-mode)
-                                  nil
-                                  (lambda (a b) (equal (car a) (car b))))))))
+                     (unless (assoc file-name path-collector)
+                       (push (cons file-name tangle-mode) path-collector))))))
              specs)))
         (if (equal arg '(4))
             (org-babel-tangle-single-block 1 t)
@@ -284,7 +324,7 @@ used to limit the exported source code blocks by language."
 Call this function inside of a source-code file generated by
 `org-babel-tangle' to remove all comments inserted automatically
 by `org-babel-tangle'.  Warning, this comment removes any lines
-containing constructs which resemble org-mode file links or noweb
+containing constructs which resemble Org file links or noweb
 references."
   (interactive)
   (goto-char (point-min))
@@ -303,153 +343,134 @@ code file.  This function uses `comment-region' which 
assumes
 that the appropriate major-mode is set.  SPEC has the form:
 
   (start-line file link source-name params body comment)"
-  (let* ((start-line (nth 0 spec))
-        (file (nth 1 spec))
-        (link (nth 2 spec))
-        (source-name (nth 3 spec))
-        (body (nth 5 spec))
-        (comment (nth 6 spec))
-        (comments (cdr (assoc :comments (nth 4 spec))))
-        (padline (not (string= "no" (cdr (assoc :padline (nth 4 spec))))))
-        (link-p (or (string= comments "both") (string= comments "link")
-                    (string= comments "yes") (string= comments "noweb")))
-        (link-data (mapcar (lambda (el)
-                             (cons (symbol-name el)
-                                   (let ((le (eval el)))
-                                      (if (stringp le) le (format "%S" le)))))
-                           '(start-line file link source-name)))
-        (insert-comment (lambda (text)
-                          (when (and comments (not (string= comments "no"))
-                                     (> (length text) 0))
-                            (when padline (insert "\n"))
-                            (comment-region (point) (progn (insert text) 
(point)))
-                            (end-of-line nil) (insert "\n")))))
+  (pcase-let*
+      ((`(,start ,file ,link ,source ,info ,body ,comment) spec)
+       (comments (cdr (assq :comments info)))
+       (link? (or (string= comments "both") (string= comments "link")
+                 (string= comments "yes") (string= comments "noweb")))
+       (link-data `(("start-line" . ,(number-to-string start))
+                   ("file" . ,file)
+                   ("link" . ,link)
+                   ("source-name" . ,source)))
+       (insert-comment (lambda (text)
+                        (when (and comments
+                                   (not (string= comments "no"))
+                                   (org-string-nw-p text))
+                          (if org-babel-tangle-uncomment-comments
+                              ;; Plain comments: no processing.
+                              (insert text)
+                            ;; Ensure comments are made to be
+                            ;; comments, and add a trailing newline.
+                            ;; Also ignore invisible characters when
+                            ;; commenting.
+                            (comment-region
+                             (point)
+                             (progn (insert (org-no-properties text))
+                                    (point)))
+                            (end-of-line)
+                            (insert "\n"))))))
     (when comment (funcall insert-comment comment))
-    (when link-p
-      (funcall
-       insert-comment
-       (org-fill-template org-babel-tangle-comment-format-beg link-data)))
-    (when padline (insert "\n"))
-    (insert
-     (format
-      "%s\n"
-      (org-unescape-code-in-string
-       (org-babel-trim body (if org-src-preserve-indentation "[\f\n\r\v]")))))
-    (when link-p
-      (funcall
-       insert-comment
-       (org-fill-template org-babel-tangle-comment-format-end link-data)))))
-
-(defvar org-comment-string) ;; Defined in org.el
+    (when link?
+      (funcall insert-comment
+              (org-fill-template
+               org-babel-tangle-comment-format-beg link-data)))
+    (insert body "\n")
+    (when link?
+      (funcall insert-comment
+              (org-fill-template
+               org-babel-tangle-comment-format-end link-data)))))
+
 (defun org-babel-tangle-collect-blocks (&optional language tangle-file)
-  "Collect source blocks in the current Org-mode file.
+  "Collect source blocks in the current Org file.
 Return an association list of source-code block specifications of
 the form used by `org-babel-spec-to-string' grouped by language.
 Optional argument LANGUAGE can be used to limit the collected
 source code blocks by language.  Optional argument TANGLE-FILE
 can be used to limit the collected code blocks by target file."
-  (let ((block-counter 1) (current-heading "") blocks by-lang)
+  (let ((counter 0) last-heading-pos blocks)
     (org-babel-map-src-blocks (buffer-file-name)
-      (lambda (new-heading)
-       (if (not (string= new-heading current-heading))
-           (progn
-             (setq block-counter 1)
-             (setq current-heading new-heading))
-         (setq block-counter (+ 1 block-counter))))
-      (replace-regexp-in-string "[ \t]" "-"
-                               (condition-case nil
-                                   (or (nth 4 (org-heading-components))
-                                       "(dummy for heading without text)")
-                                 (error (buffer-file-name))))
-      (let* ((info (org-babel-get-src-block-info 'light))
-            (src-lang (nth 0 info))
-            (src-tfile (cdr (assoc :tangle (nth 2 info)))))
-        (unless (or (string-match (concat "^" org-comment-string) 
current-heading)
-                   (string= (cdr (assoc :tangle (nth 2 info))) "no")
-                   (and tangle-file (not (equal tangle-file src-tfile))))
-          (unless (and language (not (string= language src-lang)))
-           ;; Add the spec for this block to blocks under it's language
-           (setq by-lang (cdr (assoc src-lang blocks)))
-           (setq blocks (delq (assoc src-lang blocks) blocks))
-           (setq blocks (cons
-                         (cons src-lang
-                               (cons
-                                (org-babel-tangle-single-block
-                                 block-counter)
-                                by-lang)) blocks))))))
-    ;; Ensure blocks are in the correct order
-    (setq blocks
-          (mapcar
-          (lambda (by-lang) (cons (car by-lang) (reverse (cdr by-lang))))
-          blocks))
-    blocks))
-
-(defun org-babel-tangle-single-block
-  (block-counter &optional only-this-block)
+      (let ((current-heading-pos
+            (org-with-wide-buffer
+             (org-with-limited-levels (outline-previous-heading)))))
+       (if (eq last-heading-pos current-heading-pos) (cl-incf counter)
+         (setq counter 1)
+         (setq last-heading-pos current-heading-pos)))
+      (unless (org-in-commented-heading-p)
+       (let* ((info (org-babel-get-src-block-info 'light))
+              (src-lang (nth 0 info))
+              (src-tfile (cdr (assq :tangle (nth 2 info)))))
+         (unless (or (string= src-tfile "no")
+                     (and tangle-file (not (equal tangle-file src-tfile)))
+                     (and language (not (string= language src-lang))))
+           ;; Add the spec for this block to blocks under its
+           ;; language.
+           (let ((by-lang (assoc src-lang blocks))
+                 (block (org-babel-tangle-single-block counter)))
+             (if by-lang (setcdr by-lang (cons block (cdr by-lang)))
+               (push (cons src-lang (list block)) blocks)))))))
+    ;; Ensure blocks are in the correct order.
+    (mapcar (lambda (b) (cons (car b) (nreverse (cdr b)))) blocks)))
+
+(defun org-babel-tangle-single-block (block-counter &optional only-this-block)
   "Collect the tangled source for current block.
 Return the list of block attributes needed by
-`org-babel-tangle-collect-blocks'.
-When ONLY-THIS-BLOCK is non-nil, return the full association
-list to be used by `org-babel-tangle' directly."
+`org-babel-tangle-collect-blocks'.  When ONLY-THIS-BLOCK is
+non-nil, return the full association list to be used by
+`org-babel-tangle' directly."
   (let* ((info (org-babel-get-src-block-info))
         (start-line
          (save-restriction (widen)
                            (+ 1 (line-number-at-pos (point)))))
-        (file (buffer-file-name))
+        (file (buffer-file-name (buffer-base-buffer)))
         (src-lang (nth 0 info))
         (params (nth 2 info))
         (extra (nth 3 info))
         (cref-fmt (or (and (string-match "-l \"\\(.+\\)\"" extra)
                            (match-string 1 extra))
                       org-coderef-label-format))
-        (link (let ((link (org-no-properties
-                            (org-store-link nil))))
-                 (and (string-match org-bracket-link-regexp link)
-                      (match-string 1 link))))
+        (link (let ((l (org-no-properties (org-store-link nil))))
+                 (and (string-match org-bracket-link-regexp l)
+                      (match-string 1 l))))
         (source-name
-         (intern (or (nth 4 info)
-                     (format "%s:%d"
-                             (or (ignore-errors (nth 4 
(org-heading-components)))
-                                 "No heading")
-                             block-counter))))
-        (expand-cmd
-         (intern (concat "org-babel-expand-body:" src-lang)))
+         (or (nth 4 info)
+             (format "%s:%d"
+                     (or (ignore-errors (nth 4 (org-heading-components)))
+                         "No heading")
+                     block-counter)))
+        (expand-cmd (intern (concat "org-babel-expand-body:" src-lang)))
         (assignments-cmd
          (intern (concat "org-babel-variable-assignments:" src-lang)))
         (body
          ;; Run the tangle-body-hook.
-          (let* ((body ;; Expand the body in language specific manner.
-                  (if (org-babel-noweb-p params :tangle)
-                      (org-babel-expand-noweb-references info)
-                    (nth 1 info)))
-                 (body
-                  (if (assoc :no-expand params)
-                      body
-                    (if (fboundp expand-cmd)
-                        (funcall expand-cmd body params)
-                      (org-babel-expand-body:generic
-                       body params
-                       (and (fboundp assignments-cmd)
-                            (funcall assignments-cmd params)))))))
-            (with-temp-buffer
-              (insert body)
-              (when (string-match "-r" extra)
-                (goto-char (point-min))
-                (while (re-search-forward
-                        (replace-regexp-in-string "%s" ".+" cref-fmt) nil t)
-                  (replace-match "")))
-              (run-hooks 'org-babel-tangle-body-hook)
-              (buffer-string))))
+          (let ((body (if (org-babel-noweb-p params :tangle)
+                         (org-babel-expand-noweb-references info)
+                       (nth 1 info))))
+           (with-temp-buffer
+             (insert
+              ;; Expand body in language specific manner.
+              (cond ((assq :no-expand params) body)
+                    ((fboundp expand-cmd) (funcall expand-cmd body params))
+                    (t
+                     (org-babel-expand-body:generic
+                      body params (and (fboundp assignments-cmd)
+                                       (funcall assignments-cmd params))))))
+             (when (string-match "-r" extra)
+               (goto-char (point-min))
+               (while (re-search-forward
+                       (replace-regexp-in-string "%s" ".+" cref-fmt) nil t)
+                 (replace-match "")))
+             (run-hooks 'org-babel-tangle-body-hook)
+             (buffer-string))))
         (comment
-         (when (or (string= "both" (cdr (assoc :comments params)))
-                   (string= "org" (cdr (assoc :comments params))))
+         (when (or (string= "both" (cdr (assq :comments params)))
+                   (string= "org" (cdr (assq :comments params))))
            ;; From the previous heading or code-block end
            (funcall
             org-babel-process-comment-text
             (buffer-substring
              (max (condition-case nil
                       (save-excursion
-                        (org-back-to-heading t)  ; Sets match data
+                        (org-back-to-heading t) ; Sets match data
                         (match-end 0))
                     (error (point-min)))
                   (save-excursion
@@ -459,31 +480,48 @@ list to be used by `org-babel-tangle' directly."
                       (point-min))))
              (point)))))
         (result
-         (list start-line file link source-name params body comment)))
+         (list start-line
+               (if org-babel-tangle-use-relative-file-links
+                   (file-relative-name file)
+                 file)
+               (if (and org-babel-tangle-use-relative-file-links
+                        (string-match org-link-types-re link)
+                        (string= (match-string 0 link) "file"))
+                   (concat "file:"
+                           (file-relative-name (match-string 1 link)
+                                               (file-name-directory
+                                                (cdr (assq :tangle params)))))
+                 link)
+               source-name
+               params
+               (org-unescape-code-in-string
+                (if org-src-preserve-indentation
+                    (org-trim body t)
+                  (org-trim (org-remove-indentation body))))
+               comment)))
     (if only-this-block
        (list (cons src-lang (list result)))
       result)))
 
-(defun org-babel-tangle-comment-links ( &optional info)
+(defun org-babel-tangle-comment-links (&optional info)
   "Return a list of begin and end link comments for the code block at point."
-  (let* ((start-line (org-babel-where-is-src-block-head))
-        (file (buffer-file-name))
-        (link (org-link-escape (progn (call-interactively 'org-store-link)
-                                      (org-no-properties
-                                       (car (pop org-stored-links))))))
-        (source-name (nth 4 (or info (org-babel-get-src-block-info 'light))))
-        (link-data (mapcar (lambda (el)
-                             (cons (symbol-name el)
-                                   (let ((le (eval el)))
-                                      (if (stringp le) le (format "%S" le)))))
-                           '(start-line file link source-name))))
+  (let ((link-data
+        `(("start-line" . ,(number-to-string
+                            (org-babel-where-is-src-block-head)))
+          ("file" . ,(buffer-file-name))
+          ("link" . ,(org-link-escape
+                      (progn
+                        (call-interactively #'org-store-link)
+                        (org-no-properties (car (pop org-stored-links))))))
+          ("source-name" .
+           ,(nth 4 (or info (org-babel-get-src-block-info 'light)))))))
     (list (org-fill-template org-babel-tangle-comment-format-beg link-data)
          (org-fill-template org-babel-tangle-comment-format-end link-data))))
 
 ;; de-tangling functions
 (defvar org-bracket-link-analytic-regexp)
 (defun org-babel-detangle (&optional source-code-file)
-  "Propagate changes in source file back original to Org-mode file.
+  "Propagate changes in source file back original to Org file.
 This requires that code blocks were tangled with link comments
 which enable the original code blocks to be found."
   (interactive)
@@ -504,18 +542,17 @@ which enable the original code blocks to be found."
       (prog1 counter (message "Detangled %d code blocks" counter)))))
 
 (defun org-babel-tangle-jump-to-org ()
-  "Jump from a tangled code file to the related Org-mode file."
+  "Jump from a tangled code file to the related Org mode file."
   (interactive)
   (let ((mid (point))
-       start body-start end done
+       start body-start end
         target-buffer target-char link path block-name body)
     (save-window-excursion
       (save-excursion
        (while (and (re-search-backward org-bracket-link-analytic-regexp nil t)
                    (not ; ever wider searches until matching block comments
-                    (and (setq start (point-at-eol))
-                         (setq body-start (save-excursion
-                                            (forward-line 2) (point-at-bol)))
+                    (and (setq start (line-beginning-position))
+                         (setq body-start (line-beginning-position 2))
                          (setq link (match-string 0))
                          (setq path (match-string 3))
                          (setq block-name (match-string 5))
@@ -524,32 +561,37 @@ which enable the original code blocks to be found."
                              (re-search-forward
                               (concat " " (regexp-quote block-name)
                                       " ends here") nil t)
-                             (setq end (point-at-bol))))))))
+                             (setq end (line-beginning-position))))))))
        (unless (and start (< start mid) (< mid end))
          (error "Not in tangled code"))
-        (setq body (org-babel-trim (buffer-substring start end))))
+        (setq body (buffer-substring body-start end)))
       (when (string-match "::" path)
         (setq path (substring path 0 (match-beginning 0))))
-      (find-file path) (setq target-buffer (current-buffer))
-      (goto-char start) (org-open-link-from-string link)
+      (find-file (or (car (org-id-find path)) path))
+      (setq target-buffer (current-buffer))
+      ;; Go to the beginning of the relative block in Org file.
+      (org-open-link-from-string link)
       (if (string-match "[^ \t\n\r]:\\([[:digit:]]+\\)" block-name)
-          (org-babel-next-src-block
-           (string-to-number (match-string 1 block-name)))
+          (let ((n (string-to-number (match-string 1 block-name))))
+           (if (org-before-first-heading-p) (goto-char (point-min))
+             (org-back-to-heading t))
+           ;; Do not skip the first block if it begins at point min.
+           (cond ((or (org-at-heading-p)
+                      (not (eq (org-element-type (org-element-at-point))
+                               'src-block)))
+                  (org-babel-next-src-block n))
+                 ((= n 1))
+                 (t (org-babel-next-src-block (1- n)))))
         (org-babel-goto-named-src-block block-name))
-      ;; position at the beginning of the code block body
       (goto-char (org-babel-where-is-src-block-head))
+      ;; Preserve location of point within the source code in tangled
+      ;; code file.
       (forward-line 1)
-      ;; Use org-edit-special to isolate the code.
-      (org-edit-special)
-      ;; Then move forward the correct number of characters in the
-      ;; code buffer.
       (forward-char (- mid body-start))
-      ;; And return to the Org-mode buffer with the point in the right
-      ;; place.
-      (org-edit-src-exit)
       (setq target-char (point)))
     (org-src-switch-to-buffer target-buffer t)
-    (prog1 body (goto-char target-char))))
+    (goto-char target-char)
+    body))
 
 (provide 'ob-tangle)
 
diff --git a/lisp/org/ob.el b/lisp/org/ob.el
index b0c3d52..736f588 100644
--- a/lisp/org/ob.el
+++ b/lisp/org/ob.el
@@ -1,4 +1,4 @@
-;;; ob.el --- working with code blocks in org-mode
+;;; ob.el --- Working with Code Blocks in Org        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index 153e377..f90dd53 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -24,7 +24,7 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the code for creating and using the Agenda for Org-mode.
+;; This file contains the code for creating and using the Agenda for Org.
 ;;
 ;; The functions `org-batch-agenda', `org-batch-agenda-csv', and
 ;; `org-batch-store-agenda-views' are implemented as macros to provide
@@ -45,10 +45,9 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'org)
 (require 'org-macs)
-(eval-when-compile
-  (require 'cl))
 
 (declare-function diary-add-to-list "diary-lib"
                   (date string specifier &optional marker globcolor literal))
@@ -69,6 +68,7 @@
 (declare-function calendar-persian-date-string  "cal-persia" (&optional date))
 (declare-function calendar-check-holidays       "holidays" (date))
 
+(declare-function org-columns-remove-overlays "org-colview" ())
 (declare-function org-datetree-find-date-create "org-datetree"
                  (date &optional keep-restriction))
 (declare-function org-columns-quit              "org-colview" ())
@@ -79,16 +79,15 @@
 (declare-function org-is-habit-p "org-habit" (&optional pom))
 (declare-function org-habit-parse-todo "org-habit" (&optional pom))
 (declare-function org-habit-get-priority "org-habit" (habit &optional moment))
-(declare-function org-pop-to-buffer-same-window "org-compat"
-                 (&optional buffer-or-name norecord label))
 (declare-function org-agenda-columns "org-colview" ())
 (declare-function org-add-archive-files "org-archive" (files))
 (declare-function org-capture "org-capture" (&optional goto keys))
 
-(defvar calendar-mode-map)                    ; defined in calendar.el
-(defvar org-clock-current-task nil)           ; defined in org-clock.el
-(defvar org-mobile-force-id-on-agenda-items)  ; defined in org-mobile.el
-(defvar org-habit-show-habits)                ; defined in org-habit.el
+(defvar calendar-mode-map)
+(defvar org-clock-current-task)
+(defvar org-current-tag-alist)
+(defvar org-mobile-force-id-on-agenda-items)
+(defvar org-habit-show-habits)
 (defvar org-habit-show-habits-only-for-today)
 (defvar org-habit-show-all-today)
 
@@ -96,8 +95,8 @@
 (defvar org-agenda-buffer-name "*Org Agenda*")
 (defvar org-agenda-overriding-header nil)
 (defvar org-agenda-title-append nil)
-(org-no-warnings (defvar entry)) ;; unprefixed, from calendar.el
-(org-no-warnings (defvar date))  ;; unprefixed, from calendar.el
+(with-no-warnings (defvar entry)) ;; unprefixed, from calendar.el
+(with-no-warnings (defvar date))  ;; unprefixed, from calendar.el
 (defvar original-date) ; dynamically scoped, calendar.el does scope this
 
 (defvar org-agenda-undo-list nil
@@ -135,7 +134,7 @@ addresses the separator between the current and the 
previous block."
          (string)))
 
 (defgroup org-agenda-export nil
-  "Options concerning exporting agenda views in Org-mode."
+  "Options concerning exporting agenda views in Org mode."
   :tag "Org Agenda Export"
   :group 'org-agenda)
 
@@ -152,7 +151,7 @@ before assigned to the variables.  So make sure to quote 
values you do
 *not* want evaluated, for example
 
    (setq org-agenda-exporter-settings
-         '((ps-print-color-p 'black-white)))"
+         \\='((ps-print-color-p \\='black-white)))"
   :group 'org-agenda-export
   :type '(repeat
          (list
@@ -237,7 +236,7 @@ you can \"misuse\" it to also add other text to the header."
   :type 'boolean)
 
 (defgroup org-agenda-custom-commands nil
-  "Options concerning agenda views in Org-mode."
+  "Options concerning agenda views in Org mode."
   :tag "Org Agenda Custom Commands"
   :group 'org-agenda)
 
@@ -261,8 +260,8 @@ you can \"misuse\" it to also add other text to the header."
 
 ;; Keep custom values for `org-agenda-filter-preset' compatible with
 ;; the new variable `org-agenda-tag-filter-preset'.
-(org-defvaralias 'org-agenda-filter-preset 'org-agenda-tag-filter-preset)
-(org-defvaralias 'org-agenda-filter 'org-agenda-tag-filter)
+(defvaralias 'org-agenda-filter-preset 'org-agenda-tag-filter-preset)
+(defvaralias 'org-agenda-filter 'org-agenda-tag-filter)
 
 (defvar org-agenda-entry-types '(:deadline :scheduled :timestamp :sexp)
   "List of types searched for when creating the daily/weekly agenda.
@@ -360,6 +359,12 @@ the daily/weekly agenda, see `org-agenda-skip-function'.")
                          (const :format "" quote)
                          (repeat
                           (string :tag "+tag or -tag"))))
+                  (list :tag "Effort filter preset"
+                        (const org-agenda-effort-filter-preset)
+                        (list
+                         (const :format "" quote)
+                         (repeat
+                          (string :tag "+=10 or -=10 or +<10 or ->10"))))
                   (list :tag "Regexp filter preset"
                         (const org-agenda-regexp-filter-preset)
                         (list
@@ -435,8 +440,9 @@ This will be spliced into the custom type of
 (defcustom org-agenda-custom-commands
   '(("n" "Agenda and all TODOs" ((agenda "") (alltodo ""))))
   "Custom commands for the agenda.
+\\<org-mode-map>
 These commands will be offered on the splash screen displayed by the
-agenda dispatcher \\[org-agenda].  Each entry is a list like this:
+agenda dispatcher `\\[org-agenda]'.  Each entry is a list like this:
 
    (key desc type match settings files)
 
@@ -463,8 +469,8 @@ match    What to search for:
 settings  A list of option settings, similar to that in a let form, so like
           this: ((opt1 val1) (opt2 val2) ...).   The values will be
           evaluated at the moment of execution, so quote them when needed.
-files     A list of files file to write the produced agenda buffer to
-          with the command `org-store-agenda-views'.
+files     A list of files to write the produced agenda buffer to with
+          the command `org-store-agenda-views'.
           If a file name ends in \".html\", an HTML version of the buffer
           is written out.  If it ends in \".ps\", a postscript version is
           produced.  Otherwise, only the plain text is written to the file.
@@ -601,23 +607,17 @@ subtree to see if any of the subtasks have project status.
 See also the variable `org-tags-match-list-sublevels' which applies
 to projects matched by this search as well.
 
-After defining this variable, you may use \\[org-agenda-list-stuck-projects]
-or `C-c a #' to produce the list."
+After defining this variable, you may use `\\[org-agenda-list-stuck-projects]'
+\(bound to `C-c a #') to produce the list."
   :group 'org-agenda-custom-commands
   :type '(list
          (string :tag "Tags/TODO match to identify a project")
-         (repeat :tag "Projects are *not* stuck if they have an entry with 
TODO keyword any of" (string))
-         (repeat :tag "Projects are *not* stuck if they have an entry with TAG 
being any of" (string))
-         (regexp :tag "Projects are *not* stuck if this regexp matches inside 
the subtree")))
-
-(defcustom org-agenda-filter-effort-default-operator "<"
-  "The default operator for effort estimate filtering.
-If you select an effort estimate limit without first pressing an operator,
-this one will be used."
-  :group 'org-agenda-custom-commands
-  :type '(choice (const :tag "less or equal" "<")
-                (const :tag "greater or equal"">")
-                (const :tag "equal" "=")))
+         (repeat :tag "Projects are *not* stuck if they have an entry with \
+TODO keyword any of" (string))
+         (repeat :tag "Projects are *not* stuck if they have an entry with \
+TAG being any of" (string))
+         (regexp :tag "Projects are *not* stuck if this regexp matches inside \
+the subtree")))
 
 (defgroup org-agenda-skip nil
   "Options concerning skipping parts of agenda files."
@@ -769,10 +769,12 @@ to make his option also apply to the tags-todo list."
 
 (defcustom org-agenda-todo-ignore-deadlines nil
   "Non-nil means ignore some deadline TODO items when making TODO list.
+
 There are different motivations for using different values, please think
 carefully when configuring this variable.
 
-This applies when creating the global todo list.
+This applies when creating the global TODO list.
+
 Valid values are:
 
 near    Don't show near deadline entries.  A deadline is near when it is
@@ -780,8 +782,8 @@ near    Don't show near deadline entries.  A deadline is 
near when it is
         is that such items will appear in the agenda anyway.
 
 far     Don't show TODO entries where a deadline has been defined, but
-        the deadline is not near.  This is useful if you don't want to
-        use the todo list to figure out what to do now.
+        is not going to happen anytime soon.  This is useful if you want to use
+        the TODO list to figure out what to do now.
 
 past    Don't show entries with a deadline timestamp for today or in the past.
 
@@ -842,10 +844,9 @@ restricted to unfinished TODO entries only."
 
 (defcustom org-agenda-skip-scheduled-if-done nil
   "Non-nil means don't show scheduled items in agenda when they are done.
-This is relevant for the daily/weekly agenda, not for the TODO list.  And
-it applies only to the actual date of the scheduling.  Warnings about
-an item with a past scheduling dates are always turned off when the item
-is DONE."
+This is relevant for the daily/weekly agenda, not for the TODO list.  It
+applies only to the actual date of the scheduling.  Warnings about an item
+with a past scheduling dates are always turned off when the item is DONE."
   :group 'org-agenda-skip
   :group 'org-agenda-daily/weekly
   :type 'boolean)
@@ -894,8 +895,8 @@ several times."
 (defcustom org-agenda-skip-deadline-if-done nil
   "Non-nil means don't show deadlines when the corresponding item is done.
 When nil, the deadline is still shown and should give you a happy feeling.
-This is relevant for the daily/weekly agenda.  And it applied only to the
-actually date of the deadline.  Warnings about approaching and past-due
+This is relevant for the daily/weekly agenda.  It applies only to the
+actual date of the deadline.  Warnings about approaching and past-due
 deadlines are always turned off when the item is DONE."
   :group 'org-agenda-skip
   :group 'org-agenda-daily/weekly
@@ -1001,8 +1002,6 @@ you want to use two-columns display (see 
`org-agenda-menu-two-columns')."
   :version "24.1"
   :type 'boolean)
 
-(define-obsolete-variable-alias 'org-agenda-menu-two-column 
'org-agenda-menu-two-columns "24.3")
-
 (defcustom org-agenda-menu-two-columns nil
   "Non-nil means, use two columns to show custom commands in the dispatcher.
 If you use this, you probably want to set `org-agenda-menu-show-matcher'
@@ -1011,7 +1010,6 @@ to nil."
   :version "24.1"
   :type 'boolean)
 
-(define-obsolete-variable-alias 'org-finalize-agenda-hook 
'org-agenda-finalize-hook "24.3")
 (defcustom org-agenda-finalize-hook nil
   "Hook run just before displaying an agenda buffer.
 The buffer is still writable when the hook is called.
@@ -1024,8 +1022,8 @@ headlines as the agenda display heavily relies on them."
 
 (defcustom org-agenda-mouse-1-follows-link nil
   "Non-nil means mouse-1 on a link will follow the link in the agenda.
-A longer mouse click will still set point.  Does not work on XEmacs.
-Needs to be set before org.el is loaded."
+A longer mouse click will still set point.  Needs to be set
+before org.el is loaded."
   :group 'org-agenda-startup
   :type 'boolean)
 
@@ -1054,9 +1052,9 @@ current item's tree, in an indirect buffer."
 (defcustom org-agenda-entry-text-maxlines 5
   "Number of text lines to be added when `E' is pressed in the agenda.
 
-Note that this variable only used during agenda display.  Add add entry text
+Note that this variable only used during agenda display.  To add entry text
 when exporting the agenda, configure the variable
-`org-agenda-add-entry-ext-maxlines'."
+`org-agenda-add-entry-text-maxlines'."
   :group 'org-agenda
   :type 'integer)
 
@@ -1097,6 +1095,7 @@ Possible values for this option are:
 
 current-window    Show agenda in the current window, keeping all other windows.
 other-window      Use `switch-to-buffer-other-window' to display agenda.
+only-window       Show agenda, deleting all other windows.
 reorganize-frame  Show only two windows on the current frame, the current
                   window and the agenda.
 other-frame       Use `switch-to-buffer-other-frame' to display agenda.
@@ -1107,6 +1106,7 @@ See also the variable 
`org-agenda-restore-windows-after-quit'."
          (const current-window)
          (const other-frame)
          (const other-window)
+         (const only-window)
          (const reorganize-frame)))
 
 (defcustom org-agenda-window-frame-fractions '(0.5 . 0.75)
@@ -1126,16 +1126,6 @@ option will be ignored."
   :group 'org-agenda-windows
   :type 'boolean)
 
-(defcustom org-agenda-ndays nil
-  "Number of days to include in overview display.
-Should be 1 or 7.
-Obsolete, see `org-agenda-span'."
-  :group 'org-agenda-daily/weekly
-  :type '(choice (const nil)
-                (integer)))
-
-(make-obsolete-variable 'org-agenda-ndays 'org-agenda-span "24.1")
-
 (defcustom org-agenda-span 'week
   "Number of days to include in overview display.
 Can be day, week, month, year, or any number of days.
@@ -1211,7 +1201,7 @@ For example, 9:30am would become 09:30 rather than  9:30."
   :type 'boolean)
 
 (defun org-agenda-time-of-day-to-ampm (time)
-  "Convert TIME of a string like `13:45' to an AM/PM style time string."
+  "Convert TIME of a string like \"13:45\" to an AM/PM style time string."
   (let* ((hour-number (string-to-number (substring time 0 -3)))
          (minute (substring time -2))
          (ampm "am"))
@@ -1284,20 +1274,22 @@ shown, either today or the nearest into the future."
 
 (defcustom org-scheduled-past-days 10000
   "Number of days to continue listing scheduled items not marked DONE.
-When an item is scheduled on a date, it shows up in the agenda on this
-day and will be listed until it is marked done for the number of days
-given here."
+When an item is scheduled on a date, it shows up in the agenda on
+this day and will be listed until it is marked done or for the
+number of days given here."
   :group 'org-agenda-daily/weekly
   :type 'integer)
 
 (defcustom org-agenda-log-mode-items '(closed clock)
   "List of items that should be shown in agenda log mode.
+\\<org-agenda-mode-map>\
 This list may contain the following symbols:
 
   closed    Show entries that have been closed on that day.
   clock     Show entries that have received clocked time on that day.
   state     Show all logged state changes.
-Note that instead of changing this variable, you can also press `C-u l' in
+Note that instead of changing this variable, you can also press \
+`\\[universal-argument] \\[org-agenda-log-mode]' in
 the agenda to display all available LOG items temporarily."
   :group 'org-agenda-daily/weekly
   :type '(set :greedy t (const closed) (const clock) (const state)))
@@ -1413,7 +1405,7 @@ boolean search."
   :version "24.1"
   :type 'boolean)
 
-(org-defvaralias 'org-agenda-search-view-search-words-only
+(defvaralias 'org-agenda-search-view-search-words-only
   'org-agenda-search-view-always-boolean)
 
 (defcustom org-agenda-search-view-force-full-words nil
@@ -1434,7 +1426,7 @@ value, don't limit agenda view by outline level."
   :type 'integer)
 
 (defgroup org-agenda-time-grid nil
-  "Options concerning the time grid in the Org-mode Agenda."
+  "Options concerning the time grid in the Org Agenda."
   :tag "Org Agenda Time Grid"
   :group 'org-agenda)
 
@@ -1506,7 +1498,7 @@ a grid line."
   :type 'string)
 
 (defgroup org-agenda-sorting nil
-  "Options concerning sorting in the Org-mode Agenda."
+  "Options concerning sorting in the Org Agenda."
   :tag "Org Agenda Sorting"
   :group 'org-agenda)
 
@@ -1612,7 +1604,7 @@ When nil, such items are sorted as 0 minutes effort."
   :type 'boolean)
 
 (defgroup org-agenda-line-format nil
-  "Options concerning the entry prefix in the Org-mode agenda display."
+  "Options concerning the entry prefix in the Org agenda display."
   :tag "Org Agenda Line Format"
   :group 'org-agenda)
 
@@ -1792,17 +1784,18 @@ When non-nil, this must be the number of minutes, e.g. 
60 for one hour."
 (defcustom org-agenda-show-inherited-tags t
   "Non-nil means show inherited tags in each agenda line.
 
-When this option is set to 'always, it take precedences over
+When this option is set to `always', it takes precedence over
 `org-agenda-use-tag-inheritance' and inherited tags are shown
 in every agenda.
 
 When this option is set to t (the default), inherited tags are
 shown when they are available, i.e. when the value of
-`org-agenda-use-tag-inheritance' has been taken into account.
+`org-agenda-use-tag-inheritance' enables tag inheritance for the
+given agenda type.
 
 This can be set to a list of agenda types in which the agenda
-must display the inherited tags.  Available types are 'todo,
-'agenda, 'search and 'timeline.
+must display the inherited tags.  Available types are `todo',
+`agenda', `search' and `timeline'.
 
 When set to nil, never show inherited tags in agenda lines."
   :group 'org-agenda-line-format
@@ -1823,10 +1816,10 @@ controlled by `org-use-tag-inheritance'.  In other 
agenda types,
 agenda entries.  Still, you may want the agenda to be aware of
 the inherited tags anyway, e.g. for later tag filtering.
 
-Allowed value are 'todo, 'search, 'timeline and 'agenda.
+Allowed value are `todo', `search', `timeline' and `agenda'.
 
 This variable has no effect if `org-agenda-show-inherited-tags'
-is set to 'always.  In that case, the agenda is aware of those
+is set to `always'.  In that case, the agenda is aware of those
 tags.
 
 The default value sets tags in every agenda type.  Setting this
@@ -1858,10 +1851,10 @@ When this is the symbol `prefix', only remove tags when
          (const :tag "Never" nil)
          (const :tag "When prefix format contains %T" prefix)))
 
-(org-defvaralias 'org-agenda-remove-tags-when-in-prefix
+(defvaralias 'org-agenda-remove-tags-when-in-prefix
   'org-agenda-remove-tags)
 
-(defcustom org-agenda-tags-column (if (featurep 'xemacs) -79 -80)
+(defcustom org-agenda-tags-column -80
   "Shift tags in agenda items to this column.
 If this number is positive, it specifies the column.  If it is negative,
 it means that the tags should be flushright to that column.  For example,
@@ -1869,7 +1862,7 @@ it means that the tags should be flushright to that 
column.  For example,
   :group 'org-agenda-line-format
   :type 'integer)
 
-(org-defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column)
+(defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column)
 
 (defcustom org-agenda-fontify-priorities 'cookies
   "Non-nil means highlight low and high priorities in agenda.
@@ -1948,6 +1941,14 @@ category, you can use:
   :tag "Org Agenda Column View"
   :group 'org-agenda)
 
+(defcustom org-agenda-view-columns-initially nil
+  "When non-nil, switch to columns view right after creating the agenda."
+  :group 'org-agenda-column-view
+  :type 'boolean
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :safe #'booleanp)
+
 (defcustom org-agenda-columns-show-summaries t
   "Non-nil means show summaries for columns displayed in the agenda view."
   :group 'org-agenda-column-view
@@ -1975,7 +1976,8 @@ estimate."
   :type 'boolean)
 
 (defcustom org-agenda-auto-exclude-function nil
-  "A function called with a tag to decide if it is filtered on `/ RET'.
+  "A function called with a tag to decide if it is filtered on \
+\\<org-agenda-mode-map>`\\[org-agenda-filter-by-tag] RET'.
 The sole argument to the function, which is called once for each
 possible tag, is a string giving the name of the tag.  The
 function should return either nil if the tag should be included
@@ -1990,13 +1992,13 @@ the lower-case version of all tags."
   "Alist of characters and custom functions for bulk actions.
 For example, this value makes those two functions available:
 
-  ((?R set-category)
-   (?C bulk-cut))
+  \\='((?R set-category)
+    (?C bulk-cut))
 
 With selected entries in an agenda buffer, `B R' will call
 the custom function `set-category' on the selected entries.
 Note that functions in this alist don't need to be quoted."
-  :type 'alist
+  :type '(alist :key-type character :value-type (group function))
   :version "24.1"
   :group 'org-agenda)
 
@@ -2006,7 +2008,7 @@ If STRING is non-nil, the text property will be fetched 
from position 0
 in that string.  If STRING is nil, it will be fetched from the beginning
 of the current line."
   (org-with-gensyms (marker)
-    `(let ((,marker (get-text-property (if string 0 (point-at-bol))
+    `(let ((,marker (get-text-property (if ,string 0 (point-at-bol))
                                       'org-hd-marker ,string)))
        (with-current-buffer (marker-buffer ,marker)
         (save-excursion
@@ -2027,7 +2029,7 @@ works you probably want to add it to 
`org-agenda-custom-commands' for good."
 
 (defvar org-agenda-mode-map (make-sparse-keymap)
   "Keymap for `org-agenda-mode'.")
-(org-defvaralias 'org-agenda-keymap 'org-agenda-mode-map)
+(defvaralias 'org-agenda-keymap 'org-agenda-mode-map)
 
 (defvar org-agenda-menu) ; defined later in this file.
 (defvar org-agenda-restrict nil) ; defined later in this file.
@@ -2044,6 +2046,8 @@ The buffer is still writable when this hook is called.")
 (defvar org-agenda-force-single-file nil)
 (defvar org-agenda-bulk-marked-entries nil
   "List of markers that refer to marked entries in the agenda.")
+(defvar org-agenda-current-date nil
+  "Active date when building the agenda.")
 
 ;;; Multiple agenda buffers support
 
@@ -2064,13 +2068,13 @@ When nil, `q' will kill the single agenda buffer."
                       (> (prefix-numeric-value arg) 0)
                     (not org-agenda-sticky))))
     (if (equal new-value org-agenda-sticky)
-       (and (org-called-interactively-p 'interactive)
+       (and (called-interactively-p 'interactive)
             (message "Sticky agenda was already %s"
                      (if org-agenda-sticky "enabled" "disabled")))
       (setq org-agenda-sticky new-value)
       (org-agenda-kill-all-agenda-buffers)
-      (and (org-called-interactively-p 'interactive)
-          (message "Sticky agenda was %s"
+      (and (called-interactively-p 'interactive)
+          (message "Sticky agenda %s"
                    (if org-agenda-sticky "enabled" "disabled"))))))
 
 (defvar org-agenda-buffer nil
@@ -2080,6 +2084,8 @@ When nil, `q' will kill the single agenda buffer."
 (defvar org-agenda-this-buffer-name nil)
 (defvar org-agenda-doing-sticky-redo nil)
 (defvar org-agenda-this-buffer-is-sticky nil)
+(defvar org-agenda-last-indirect-buffer nil
+  "Last buffer loaded by `org-agenda-tree-to-indirect-buffer'.")
 
 (defconst org-agenda-local-vars
   '(org-agenda-this-buffer-name
@@ -2101,8 +2107,10 @@ When nil, `q' will kill the single agenda buffer."
     org-agenda-category-filter
     org-agenda-top-headline-filter
     org-agenda-regexp-filter
+    org-agenda-effort-filter
     org-agenda-markers
     org-agenda-last-search-view-search-was-boolean
+    org-agenda-last-indirect-buffer
     org-agenda-filtered-by-category
     org-agenda-filter-form
     org-agenda-cycle-counter
@@ -2110,7 +2118,7 @@ When nil, `q' will kill the single agenda buffer."
   "Variables that must be local in agenda buffers to allow multiple buffers.")
 
 (defun org-agenda-mode ()
-  "Mode for time-sorted view on action items in Org-mode files.
+  "Mode for time-sorted view on action items in Org files.
 
 The following commands are available:
 
@@ -2123,42 +2131,41 @@ The following commands are available:
         ;; while letting `kill-all-local-variables' kill the rest
         (let ((save (buffer-local-variables)))
           (kill-all-local-variables)
-          (mapc 'make-local-variable org-agenda-local-vars)
+          (mapc #'make-local-variable org-agenda-local-vars)
           (dolist (elem save)
-            (let ((var (car elem))
-                  (val (cdr elem)))
-              (when (and val
-                         (member var org-agenda-local-vars))
-                (set var val)))))
-        (set (make-local-variable 'org-agenda-this-buffer-is-sticky) t))
+            (pcase elem
+              (`(,var . ,val)          ;ignore unbound variables
+               (when (and val (memq var org-agenda-local-vars))
+                 (set var val))))))
+        (setq-local org-agenda-this-buffer-is-sticky t))
        (org-agenda-sticky
         ;; Creating a sticky Agenda buffer for the first time
         (kill-all-local-variables)
         (mapc 'make-local-variable org-agenda-local-vars)
-        (set (make-local-variable 'org-agenda-this-buffer-is-sticky) t))
+        (setq-local org-agenda-this-buffer-is-sticky t))
        (t
         ;; Creating a non-sticky agenda buffer
         (kill-all-local-variables)
-        (set (make-local-variable 'org-agenda-this-buffer-is-sticky) nil)))
+        (setq-local org-agenda-this-buffer-is-sticky nil)))
   (setq org-agenda-undo-list nil
        org-agenda-pending-undo-list nil
        org-agenda-bulk-marked-entries nil)
   (setq major-mode 'org-agenda-mode)
   ;; Keep global-font-lock-mode from turning on font-lock-mode
-  (org-set-local 'font-lock-global-modes (list 'not major-mode))
+  (setq-local font-lock-global-modes (list 'not major-mode))
   (setq mode-name "Org-Agenda")
   (setq indent-tabs-mode nil)
   (use-local-map org-agenda-mode-map)
   (easy-menu-add org-agenda-menu)
   (if org-startup-truncated (setq truncate-lines t))
-  (org-set-local 'line-move-visual nil)
-  (org-add-hook 'post-command-hook 'org-agenda-update-agenda-type nil 'local)
-  (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
+  (setq-local line-move-visual nil)
+  (add-hook 'post-command-hook 'org-agenda-update-agenda-type nil 'local)
+  (add-hook 'pre-command-hook 'org-unhighlight nil 'local)
   ;; Make sure properties are removed when copying text
-  (org-add-hook 'filter-buffer-substring-functions
-               (lambda (fun start end delete)
-                 (substring-no-properties (funcall fun start end delete)))
-               nil t)
+  (add-hook 'filter-buffer-substring-functions
+           (lambda (fun start end delete)
+             (substring-no-properties (funcall fun start end delete)))
+           nil t)
   (unless org-agenda-keep-modes
     (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
          org-agenda-entry-text-mode org-agenda-start-with-entry-text-mode))
@@ -2309,9 +2316,9 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "{" 'org-agenda-manipulate-query-add-re)
 (org-defkey org-agenda-mode-map "}" 'org-agenda-manipulate-query-subtract-re)
 (org-defkey org-agenda-mode-map "/" 'org-agenda-filter-by-tag)
+(org-defkey org-agenda-mode-map "_" 'org-agenda-filter-by-effort)
 (org-defkey org-agenda-mode-map "=" 'org-agenda-filter-by-regexp)
 (org-defkey org-agenda-mode-map "|" 'org-agenda-filter-remove-all)
-(org-defkey org-agenda-mode-map "\\" 'org-agenda-filter-by-tag-refine)
 (org-defkey org-agenda-mode-map "~" 'org-agenda-limit-interactively)
 (org-defkey org-agenda-mode-map "<" 'org-agenda-filter-by-category)
 (org-defkey org-agenda-mode-map "^" 'org-agenda-filter-by-top-headline)
@@ -2322,6 +2329,10 @@ The following commands are available:
 
 (org-defkey org-agenda-mode-map [mouse-2] 'org-agenda-goto-mouse)
 (org-defkey org-agenda-mode-map [mouse-3] 'org-agenda-show-mouse)
+
+(define-key org-agenda-mode-map [remap forward-paragraph] 
'org-agenda-forward-block)
+(define-key org-agenda-mode-map [remap backward-paragraph] 
'org-agenda-backward-block)
+
 (when org-agenda-mouse-1-follows-link
   (org-defkey org-agenda-mode-map [follow-link] 'mouse-face))
 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
@@ -2346,7 +2357,7 @@ The following commands are available:
      ["Fortnight View" org-agenda-fortnight-view
       :active (org-agenda-check-type nil 'agenda)
       :style radio :selected (eq org-agenda-current-span 'fortnight)
-      :keys "v f"]
+      :keys "v t"]
      ["Month View" org-agenda-month-view
       :active (org-agenda-check-type nil 'agenda)
       :style radio :selected (eq org-agenda-current-span 'month)
@@ -2387,7 +2398,7 @@ The following commands are available:
      ["Remove Restriction" org-agenda-remove-restriction-lock 
org-agenda-restrict])
     ["Write view to file" org-agenda-write t]
     ["Rebuild buffer" org-agenda-redo t]
-    ["Save all Org-mode Buffers" org-save-all-org-buffers t]
+    ["Save all Org buffers" org-save-all-org-buffers t]
     "--"
     ["Show original entry" org-agenda-show t]
     ["Go To (other window)" org-agenda-goto t]
@@ -2538,7 +2549,7 @@ For example, if you have a custom agenda command \"p\" 
and you
 want this command to be accessible only from plain text files,
 use this:
 
-   \\='((\"p\" ((in-file . \"\\.txt\"))))
+   \\='((\"p\" ((in-file . \"\\\\.txt\\\\'\"))))
 
 Here are the available contexts definitions:
 
@@ -2556,7 +2567,7 @@ accessible if there is at least one valid check.
 You can also bind a key to another agenda custom command
 depending on contextual rules.
 
-    \\='((\"p\" \"q\" ((in-file . \"\\.txt\"))))
+    \\='((\"p\" \"q\" ((in-file . \"\\\\.txt\\\\'\"))))
 
 Here it means: in .txt files, use \"p\" as the key for the
 agenda command otherwise associated with \"q\".  (The command
@@ -2656,6 +2667,7 @@ to limit entries to in this type."
                                (const timeline))
                        (integer :tag "Max number of minutes")))))
 
+(defvar org-agenda-keep-restricted-file-list nil)
 (defvar org-keys nil)
 (defvar org-match nil)
 ;;;###autoload
@@ -2688,9 +2700,9 @@ More commands can be added by configuring the variable
 `org-agenda-custom-commands'.  In particular, specific tags and TODO keyword
 searches can be pre-defined in this way.
 
-If the current buffer is in Org-mode and visiting a file, you can also
+If the current buffer is in Org mode and visiting a file, you can also
 first press `<' once to indicate that the agenda should be temporarily
-\(until the next use of \\[org-agenda]) restricted to the current file.
+\(until the next use of `\\[org-agenda]') restricted to the current file.
 Pressing `<' twice means to restrict to the current subtree or region
 \(if active)."
   (interactive "P")
@@ -2722,7 +2734,7 @@ Pressing `<' twice means to restrict to the current 
subtree or region
           entry key type org-match lprops ans)
       ;; Turn off restriction unless there is an overriding one,
       (unless org-agenda-overriding-restriction
-       (unless (org-bound-and-true-p org-agenda-keep-restricted-file-list)
+       (unless org-agenda-keep-restricted-file-list
          ;; There is a request to keep the file list in place
          (put 'org-agenda-files 'org-restrict nil))
        (setq org-agenda-restrict nil)
@@ -2819,7 +2831,7 @@ Pressing `<' twice means to restrict to the current 
subtree or region
        ((equal org-keys "M") (org-call-with-arg 'org-tags-view (or arg '(4))))
        ((equal org-keys "e") (call-interactively 'org-store-agenda-views))
        ((equal org-keys "?") (org-tags-view nil "+FLAGGED")
-       (org-add-hook
+       (add-hook
         'post-command-hook
         (lambda ()
           (unless (current-message)
@@ -2836,7 +2848,7 @@ Pressing `<' twice means to restrict to the current 
subtree or region
         t t))
        ((equal org-keys "L")
        (unless (derived-mode-p 'org-mode)
-         (user-error "This is not an Org-mode file"))
+         (user-error "This is not an Org file"))
        (unless restriction
          (put 'org-agenda-files 'org-restrict (list bfn))
          (org-call-with-arg 'org-timeline arg)))
@@ -2928,7 +2940,7 @@ L   Timeline for current buffer         #   List stuck 
projects (!=configure)
                  type (nth 2 entry)
                  match (nth 3 entry))
            (if (> (length key) 1)
-               (pushnew (string-to-char key) prefixes :test #'equal)
+               (cl-pushnew (string-to-char key) prefixes :test #'equal)
              (setq line
                    (format
                     "%-4s%-14s"
@@ -3034,7 +3046,7 @@ L   Timeline for current buffer         #   List stuck 
projects (!=configure)
            (call-interactively 'org-toggle-sticky-agenda)
            (sit-for 2))
           ((and (not restrict-ok) (memq c '(?1 ?0 ?<)))
-           (message "Restriction is only possible in Org-mode buffers")
+           (message "Restriction is only possible in Org buffers")
            (ding) (sit-for 1))
           ((eq c ?1)
            (org-agenda-remove-restriction-lock 'noupdate)
@@ -3067,10 +3079,13 @@ L   Timeline for current buffer         #   List stuck 
projects (!=configure)
   "Fit the window to the buffer size."
   (and (memq org-agenda-window-setup '(reorganize-frame))
        (fboundp 'fit-window-to-buffer)
-       (org-fit-window-to-buffer
-       nil
-       (floor (* (frame-height) (cdr org-agenda-window-frame-fractions)))
-       (floor (* (frame-height) (car org-agenda-window-frame-fractions))))))
+       (if (and (= (cdr org-agenda-window-frame-fractions) 1.0)
+               (= (car org-agenda-window-frame-fractions) 1.0))
+          (delete-other-windows)
+        (org-fit-window-to-buffer
+         nil
+         (floor (* (frame-height) (cdr org-agenda-window-frame-fractions)))
+         (floor (* (frame-height) (car org-agenda-window-frame-fractions)))))))
 
 (defvar org-cmd nil)
 (defvar org-agenda-overriding-cmd nil)
@@ -3089,9 +3104,9 @@ L   Timeline for current buffer         #   List stuck 
projects (!=configure)
         match ;; The byte compiler incorrectly complains about this.  Keep it!
         org-cmd type lprops)
     (while (setq org-cmd (pop cmds))
-      (setq type (car org-cmd)
-           match (eval (nth 1 org-cmd))
-           lprops (nth 2 org-cmd))
+      (setq type (car org-cmd))
+      (setq match (eval (nth 1 org-cmd)))
+      (setq lprops (nth 2 org-cmd))
       (let ((org-agenda-overriding-arguments
             (if (eq org-agenda-overriding-cmd org-cmd)
                 (or org-agenda-overriding-arguments
@@ -3144,7 +3159,7 @@ Parameters are alternating variable names and values that 
will be bound
 before running the agenda command."
   (org-eval-in-environment (org-make-parameter-alist parameters)
     (let (org-agenda-sticky)
-      (if (> (length cmd-key) 2)
+      (if (> (length cmd-key) 1)
          (org-tags-view nil cmd-key)
        (org-agenda nil cmd-key))))
   (set-buffer org-agenda-buffer-name)
@@ -3232,7 +3247,7 @@ This ensures the export commands can easily use it."
        (setq tmp (replace-match "" t t tmp)))
       (when (and (setq re (plist-get props 'org-todo-regexp))
                 (setq re (concat "\\`\\.*" re " ?"))
-                (string-match re tmp))
+                (let ((case-fold-search nil)) (string-match re tmp)))
        (plist-put props 'todo (match-string 1 tmp))
        (setq tmp (replace-match "" t t tmp)))
       (plist-put props 'txt tmp)))
@@ -3245,9 +3260,7 @@ This ensures the export commands can easily use it."
           ((not res) "")
           ((stringp res) res)
           (t (prin1-to-string res))))
-    (while (string-match "," res)
-      (setq res (replace-match ";" t t res)))
-    (org-trim res)))
+    (org-trim (replace-regexp-in-string "," ";" res nil t))))
 
 ;;;###autoload
 (defun org-store-agenda-views (&rest parameters)
@@ -3306,39 +3319,42 @@ This ensures the export commands can easily use it."
 (defvar org-agenda-write-buffer-name "Agenda View")
 (defun org-agenda-write (file &optional open nosettings agenda-bufname)
   "Write the current buffer (an agenda view) as a file.
+
 Depending on the extension of the file name, plain text (.txt),
 HTML (.html or .htm), PDF (.pdf) or Postscript (.ps) is produced.
-If the extension is .ics, run icalendar export over all files used
-to construct the agenda and limit the export to entries listed in the
-agenda now.
-If the extension is .org, collect all subtrees corresponding to the
-agenda entries and add them in an .org file.
-With prefix argument OPEN, open the new file immediately.
-If NOSETTINGS is given, do not scope the settings of
-`org-agenda-exporter-settings' into the export commands.  This is used when
-the settings have already been scoped and we do not wish to overrule other,
-higher priority settings.
-If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write."
+If the extension is .ics, translate visible agenda into iCalendar
+format.  If the extension is .org, collect all subtrees
+corresponding to the agenda entries and add them in an .org file.
+
+With prefix argument OPEN, open the new file immediately.  If
+NOSETTINGS is given, do not scope the settings of
+`org-agenda-exporter-settings' into the export commands.  This is
+used when the settings have already been scoped and we do not
+wish to overrule other, higher priority settings.  If
+AGENDA-BUFFER-NAME is provided, use this as the buffer name for
+the agenda to write."
   (interactive "FWrite agenda to file: \nP")
   (if (or (not (file-writable-p file))
          (and (file-exists-p file)
-              (if (org-called-interactively-p 'any)
+              (if (called-interactively-p 'any)
                   (not (y-or-n-p (format "Overwrite existing file %s? " 
file))))))
       (user-error "Cannot write agenda to file %s" file))
   (org-let (if nosettings nil org-agenda-exporter-settings)
     '(save-excursion
        (save-window-excursion
-        (let ((bs (copy-sequence (buffer-string))) beg content)
+        (let ((bs (copy-sequence (buffer-string)))
+              (extension (file-name-extension file))
+              beg content)
           (with-temp-buffer
             (rename-buffer org-agenda-write-buffer-name t)
             (set-buffer-modified-p nil)
             (insert bs)
-            (org-agenda-remove-marked-text 'org-filtered)
+            (org-agenda-remove-marked-text 'invisible 'org-filtered)
             (run-hooks 'org-agenda-before-write-hook)
             (cond
-             ((org-bound-and-true-p org-mobile-creating-agendas)
+             ((bound-and-true-p org-mobile-creating-agendas)
               (org-mobile-write-agenda-for-mobile file))
-             ((string-match "\\.org\\'" file)
+             ((string= "org" extension)
               (let (content p m message-log-max)
                 (goto-char (point-min))
                 (while (setq p (next-single-property-change (point) 
'org-hd-marker nil))
@@ -3357,7 +3373,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for 
the agenda to write."
                 (write-file file)
                 (kill-buffer (current-buffer))
                 (message "Org file written to %s" file)))
-             ((string-match "\\.html?\\'" file)
+             ((member extension '("html" "htm"))
               (require 'htmlize)
               (set-buffer (htmlize-buffer (current-buffer)))
               (when org-agenda-export-html-style
@@ -3369,11 +3385,11 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for 
the agenda to write."
               (write-file file)
               (kill-buffer (current-buffer))
               (message "HTML written to %s" file))
-             ((string-match "\\.ps\\'" file)
+             ((string= "ps" extension)
               (require 'ps-print)
               (ps-print-buffer-with-faces file)
               (message "Postscript written to %s" file))
-             ((string-match "\\.pdf\\'" file)
+             ((string= "pdf" extension)
               (require 'ps-print)
               (ps-print-buffer-with-faces
                (concat (file-name-sans-extension file) ".ps"))
@@ -3383,7 +3399,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for 
the agenda to write."
                             (expand-file-name file))
               (delete-file (concat (file-name-sans-extension file) ".ps"))
               (message "PDF written to %s" file))
-             ((string-match "\\.ics\\'" file)
+             ((string= "ics" extension)
               (require 'ox-icalendar)
               (org-icalendar-export-current-agenda (expand-file-name file)))
              (t
@@ -3395,7 +3411,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for 
the agenda to write."
                 (kill-buffer (current-buffer))
                 (message "Plain text written to %s" file))))))))
     (set-buffer (or agenda-bufname
-                   (and (org-called-interactively-p 'any) (buffer-name))
+                   (and (called-interactively-p 'any) (buffer-name))
                    org-agenda-buffer-name)))
   (when open (org-open-file file)))
 
@@ -3416,7 +3432,7 @@ This will add a maximum of 
`org-agenda-add-entry-text-maxlines' lines of the
 entry text following headings shown in the agenda.
 Drawers will be excluded, also the line with scheduling/deadline info."
   (when (and (> org-agenda-add-entry-text-maxlines 0)
-            (not (org-bound-and-true-p org-mobile-creating-agendas)))
+            (not (bound-and-true-p org-mobile-creating-agendas)))
     (let (m txt)
       (goto-char (point-min))
       (while (not (eobp))
@@ -3441,85 +3457,83 @@ removed from the entry content.  Currently only 
`planning' is allowed here."
       (with-current-buffer (marker-buffer marker)
        (if (not (derived-mode-p 'org-mode))
            (setq txt "")
-         (save-excursion
-           (save-restriction
-             (widen)
-             (goto-char marker)
-             (end-of-line 1)
-             (setq txt (buffer-substring
-                        (min (1+ (point)) (point-max))
-                        (progn (outline-next-heading) (point)))
-                   drawer-re org-drawer-regexp
-                   kwd-time-re (concat "^[ \t]*" org-keyword-time-regexp
-                                       ".*\n?"))
-             (with-temp-buffer
-               (insert txt)
-               (when org-agenda-add-entry-text-descriptive-links
-                 (goto-char (point-min))
-                 (while (org-activate-bracket-links (point-max))
-                   (add-text-properties (match-beginning 0) (match-end 0)
-                                        '(face org-link))))
-               (goto-char (point-min))
-               (while (re-search-forward org-bracket-link-regexp (point-max) t)
-                 (set-text-properties (match-beginning 0) (match-end 0)
-                                      nil))
-               (goto-char (point-min))
-               (while (re-search-forward drawer-re nil t)
-                 (delete-region
-                  (match-beginning 0)
-                  (progn (re-search-forward
-                          "^[ \t]*:END:.*\n?" nil 'move)
-                         (point))))
-               (unless (member 'planning keep)
-                 (goto-char (point-min))
-                 (while (re-search-forward kwd-time-re nil t)
-                   (replace-match "")))
-               (goto-char (point-min))
-               (when org-agenda-entry-text-exclude-regexps
-                 (let ((re-list org-agenda-entry-text-exclude-regexps) re)
-                   (while (setq re (pop re-list))
-                     (goto-char (point-min))
-                     (while (re-search-forward re nil t)
-                       (replace-match "")))))
-               (goto-char (point-max))
-               (skip-chars-backward " \t\n")
-               (if (looking-at "[ \t\n]+\\'") (replace-match ""))
-
-               ;; find and remove min common indentation
-               (goto-char (point-min))
-               (untabify (point-min) (point-max))
-               (setq ind (org-get-indentation))
-               (while (not (eobp))
-                 (unless (looking-at "[ \t]*$")
-                   (setq ind (min ind (org-get-indentation))))
-                 (beginning-of-line 2))
-               (goto-char (point-min))
-               (while (not (eobp))
-                 (unless (looking-at "[ \t]*$")
-                   (move-to-column ind)
-                   (delete-region (point-at-bol) (point)))
-                 (beginning-of-line 2))
-
-               (run-hooks 'org-agenda-entry-text-cleanup-hook)
-
-               (goto-char (point-min))
-               (when indent
-                 (while (and (not (eobp)) (re-search-forward "^" nil t))
-                   (replace-match indent t t)))
-               (goto-char (point-min))
-               (while (looking-at "[ \t]*\n") (replace-match ""))
-               (goto-char (point-max))
-               (when (> (org-current-line)
-                        n-lines)
-                 (org-goto-line (1+ n-lines))
-                 (backward-char 1))
-               (setq txt (buffer-substring (point-min) (point)))))))))
+         (org-with-wide-buffer
+          (goto-char marker)
+          (end-of-line 1)
+          (setq txt (buffer-substring
+                     (min (1+ (point)) (point-max))
+                     (progn (outline-next-heading) (point)))
+                drawer-re org-drawer-regexp
+                kwd-time-re (concat "^[ \t]*" org-keyword-time-regexp
+                                    ".*\n?"))
+          (with-temp-buffer
+            (insert txt)
+            (when org-agenda-add-entry-text-descriptive-links
+              (goto-char (point-min))
+              (while (org-activate-links (point-max))
+                (add-text-properties (match-beginning 0) (match-end 0)
+                                     '(face org-link))))
+            (goto-char (point-min))
+            (while (re-search-forward org-bracket-link-regexp (point-max) t)
+              (set-text-properties (match-beginning 0) (match-end 0)
+                                   nil))
+            (goto-char (point-min))
+            (while (re-search-forward drawer-re nil t)
+              (delete-region
+               (match-beginning 0)
+               (progn (re-search-forward
+                       "^[ \t]*:END:.*\n?" nil 'move)
+                      (point))))
+            (unless (member 'planning keep)
+              (goto-char (point-min))
+              (while (re-search-forward kwd-time-re nil t)
+                (replace-match "")))
+            (goto-char (point-min))
+            (when org-agenda-entry-text-exclude-regexps
+              (let ((re-list org-agenda-entry-text-exclude-regexps)    re)
+                (while (setq re (pop re-list))
+                  (goto-char (point-min))
+                  (while (re-search-forward re nil t)
+                    (replace-match "")))))
+            (goto-char (point-max))
+            (skip-chars-backward " \t\n")
+            (if (looking-at "[ \t\n]+\\'") (replace-match ""))
+
+            ;; find and remove min common indentation
+            (goto-char (point-min))
+            (untabify (point-min) (point-max))
+            (setq ind (org-get-indentation))
+            (while (not (eobp))
+              (unless (looking-at "[ \t]*$")
+                (setq ind (min ind (org-get-indentation))))
+              (beginning-of-line 2))
+            (goto-char (point-min))
+            (while (not (eobp))
+              (unless (looking-at "[ \t]*$")
+                (move-to-column ind)
+                (delete-region (point-at-bol) (point)))
+              (beginning-of-line 2))
+
+            (run-hooks 'org-agenda-entry-text-cleanup-hook)
+
+            (goto-char (point-min))
+            (when indent
+              (while (and (not (eobp)) (re-search-forward "^" nil t))
+                (replace-match indent t t)))
+            (goto-char (point-min))
+            (while (looking-at "[ \t]*\n") (replace-match ""))
+            (goto-char (point-max))
+            (when (> (org-current-line)
+                     n-lines)
+              (org-goto-line (1+ n-lines))
+              (backward-char 1))
+            (setq txt (buffer-substring (point-min) (point))))))))
     txt))
 
 (defun org-check-for-org-mode ()
   "Make sure current buffer is in org-mode.  Error if not."
   (or (derived-mode-p 'org-mode)
-      (error "Cannot execute org-mode agenda command on buffer in %s"
+      (error "Cannot execute Org agenda command on buffer in %s"
             major-mode)))
 
 ;;; Agenda prepare and finalize
@@ -3531,6 +3545,7 @@ removed from the entry content.  Currently only 
`planning' is allowed here."
 (defvar org-agenda-tag-filter nil)
 (defvar org-agenda-category-filter nil)
 (defvar org-agenda-regexp-filter nil)
+(defvar org-agenda-effort-filter nil)
 (defvar org-agenda-top-headline-filter nil)
 (defvar org-agenda-tag-filter-preset nil
   "A preset of the tags filter used for secondary agenda filtering.
@@ -3562,6 +3577,16 @@ the entire agenda view.  In a block agenda, it will not 
work reliably to
 define a filter for one of the individual blocks.  You need to set it in
 the global options and expect it to be applied to the entire view.")
 
+(defvar org-agenda-effort-filter-preset nil
+  "A preset of the effort condition used for secondary agenda filtering.
+This must be a list of strings, each string must be a single regexp
+preceded by \"+\" or \"-\".
+This variable should not be set directly, but agenda custom commands can
+bind it in the options section.  The preset filter is a global property of
+the entire agenda view.  In a block agenda, it will not work reliably to
+define a filter for one of the individual blocks.  You need to set it in
+the global options and expect it to be applied to the entire view.")
+
 (defun org-agenda-use-sticky-p ()
   "Return non-nil if an agenda buffer named
 `org-agenda-buffer-name' exists and should be shown instead of
@@ -3593,30 +3618,37 @@ FILTER-ALIST is an alist of filters we need to apply 
when
      ((equal (current-buffer) abuf) nil)
      (awin (select-window awin))
      ((not (setq wconf (current-window-configuration))))
-     ((equal org-agenda-window-setup 'current-window)
-      (org-pop-to-buffer-same-window abuf))
-     ((equal org-agenda-window-setup 'other-window)
+     ((eq org-agenda-window-setup 'current-window)
+      (pop-to-buffer-same-window abuf))
+     ((eq org-agenda-window-setup 'other-window)
       (org-switch-to-buffer-other-window abuf))
-     ((equal org-agenda-window-setup 'other-frame)
+     ((eq org-agenda-window-setup 'other-frame)
       (switch-to-buffer-other-frame abuf))
-     ((equal org-agenda-window-setup 'reorganize-frame)
+     ((eq org-agenda-window-setup 'only-window)
+      (delete-other-windows)
+      (pop-to-buffer-same-window abuf))
+     ((eq org-agenda-window-setup 'reorganize-frame)
       (delete-other-windows)
       (org-switch-to-buffer-other-window abuf)))
-    (setq org-agenda-tag-filter (cdr (assoc 'tag filter-alist)))
-    (setq org-agenda-category-filter (cdr (assoc 'cat filter-alist)))
-    (setq org-agenda-regexp-filter (cdr (assoc 're filter-alist)))
+    (setq org-agenda-tag-filter (cdr (assq 'tag filter-alist)))
+    (setq org-agenda-category-filter (cdr (assq 'cat filter-alist)))
+    (setq org-agenda-effort-filter (cdr (assq 'effort filter-alist)))
+    (setq org-agenda-regexp-filter (cdr (assq 're filter-alist)))
     ;; Additional test in case agenda is invoked from within agenda
     ;; buffer via elisp link.
     (unless (equal (current-buffer) abuf)
-      (org-pop-to-buffer-same-window abuf))
+      (pop-to-buffer-same-window abuf))
     (setq org-agenda-pre-window-conf
-         (or org-agenda-pre-window-conf wconf))))
+         (or wconf org-agenda-pre-window-conf))))
 
 (defun org-agenda-prepare (&optional name)
   (let ((filter-alist (if org-agenda-persistent-filter
-                         (list `(tag . ,org-agenda-tag-filter)
-                               `(re . ,org-agenda-regexp-filter)
-                               `(car . ,org-agenda-category-filter)))))
+                         (with-current-buffer
+                             (get-buffer-create org-agenda-buffer-name)
+                           (list `(tag . ,org-agenda-tag-filter)
+                                 `(re . ,org-agenda-regexp-filter)
+                                 `(effort . ,org-agenda-effort-filter)
+                                 `(cat . ,org-agenda-category-filter))))))
     (if (org-agenda-use-sticky-p)
        (progn
          (put 'org-agenda-tag-filter :preset-filter nil)
@@ -3629,13 +3661,14 @@ FILTER-ALIST is an alist of filters we need to apply 
when
          (or org-agenda-multi (org-agenda-fit-window-to-buffer))
          (throw 'exit "Sticky Agenda buffer, use `r' to refresh"))
       (setq org-todo-keywords-for-agenda nil)
-      (setq org-drawers-for-agenda nil)
       (put 'org-agenda-tag-filter :preset-filter
           org-agenda-tag-filter-preset)
       (put 'org-agenda-category-filter :preset-filter
           org-agenda-category-filter-preset)
       (put 'org-agenda-regexp-filter :preset-filter
           org-agenda-regexp-filter-preset)
+      (put 'org-agenda-effort-filter :preset-filter
+          org-agenda-effort-filter-preset)
       (if org-agenda-multi
          (progn
            (setq buffer-read-only nil)
@@ -3649,7 +3682,6 @@ FILTER-ALIST is an alist of filters we need to apply when
                      "\n"))
            (narrow-to-region (point) (point-max)))
        (setq org-done-keywords-for-agenda nil)
-
        ;; Setting any org variables that are in org-agenda-local-vars
        ;; list need to be done after the prepare call
        (org-agenda-prepare-window
@@ -3666,11 +3698,10 @@ FILTER-ALIST is an alist of filters we need to apply 
when
              (org-uniquify org-todo-keywords-for-agenda))
        (setq org-done-keywords-for-agenda
              (org-uniquify org-done-keywords-for-agenda))
-       (setq org-drawers-for-agenda (org-uniquify org-drawers-for-agenda))
        (setq org-agenda-last-prefix-arg current-prefix-arg)
        (setq org-agenda-this-buffer-name org-agenda-buffer-name)
        (and name (not org-agenda-name)
-            (org-set-local 'org-agenda-name name)))
+            (setq-local org-agenda-name name)))
       (setq buffer-read-only nil))))
 
 (defvar org-agenda-overriding-columns-format)  ; From org-colview.el
@@ -3681,11 +3712,7 @@ FILTER-ALIST is an alist of filters we need to apply when
       (let ((inhibit-read-only t))
        (goto-char (point-min))
        (save-excursion
-         (while (org-activate-bracket-links (point-max))
-           (add-text-properties (match-beginning 0) (match-end 0)
-                                '(face org-link))))
-       (save-excursion
-         (while (org-activate-plain-links (point-max))
+         (while (org-activate-links (point-max))
            (add-text-properties (match-beginning 0) (match-end 0)
                                 '(face org-link))))
        (unless (eq org-agenda-remove-tags t)
@@ -3694,8 +3721,8 @@ FILTER-ALIST is an alist of filters we need to apply when
          (remove-text-properties (point-min) (point-max) '(face nil)))
        (if (and (boundp 'org-agenda-overriding-columns-format)
                 org-agenda-overriding-columns-format)
-           (org-set-local 'org-agenda-overriding-columns-format
-                          org-agenda-overriding-columns-format))
+           (setq-local org-agenda-overriding-columns-format
+                       org-agenda-overriding-columns-format))
        (if (and (boundp 'org-agenda-view-columns-initially)
                 org-agenda-view-columns-initially)
            (org-agenda-columns))
@@ -3733,10 +3760,10 @@ FILTER-ALIST is an alist of filters we need to apply 
when
          (org-agenda-filter-top-headline-apply
           org-agenda-top-headline-filter))
        (when org-agenda-tag-filter
-         (org-agenda-filter-apply org-agenda-tag-filter 'tag))
+         (org-agenda-filter-apply org-agenda-tag-filter 'tag t))
        (when (get 'org-agenda-tag-filter :preset-filter)
          (org-agenda-filter-apply
-          (get 'org-agenda-tag-filter :preset-filter) 'tag))
+          (get 'org-agenda-tag-filter :preset-filter) 'tag t))
        (when org-agenda-category-filter
          (org-agenda-filter-apply org-agenda-category-filter 'category))
        (when (get 'org-agenda-category-filter :preset-filter)
@@ -3747,13 +3774,18 @@ FILTER-ALIST is an alist of filters we need to apply 
when
        (when (get 'org-agenda-regexp-filter :preset-filter)
          (org-agenda-filter-apply
           (get 'org-agenda-regexp-filter :preset-filter) 'regexp))
-       (org-add-hook 'kill-buffer-hook 'org-agenda-reset-markers 'append 
'local)))))
+       (when org-agenda-effort-filter
+         (org-agenda-filter-apply org-agenda-effort-filter 'effort))
+       (when (get 'org-agenda-effort-filter :preset-filter)
+         (org-agenda-filter-apply
+          (get 'org-agenda-effort-filter :preset-filter) 'effort))
+       (add-hook 'kill-buffer-hook 'org-agenda-reset-markers 'append 
'local)))))
 
 (defun org-agenda-mark-clocking-task ()
   "Mark the current clock entry in the agenda if it is present."
   ;; We need to widen when `org-agenda-finalize' is called from
   ;; `org-agenda-change-all-lines' (e.g. in `org-agenda-clock-in')
-  (when org-clock-current-task
+  (when (bound-and-true-p org-clock-current-task)
     (save-restriction
       (widen)
       (org-agenda-unmark-clocking-task)
@@ -3782,7 +3814,7 @@ FILTER-ALIST is an alist of filters we need to apply when
   "Make highest priority lines bold, and lowest italic."
   (interactive)
   (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-priority)
-                       (delete-overlay o)))
+                  (delete-overlay o)))
        (overlays-in (point-min) (point-max)))
   (save-excursion
     (let (b e p ov h l)
@@ -3800,16 +3832,17 @@ FILTER-ALIST is an alist of filters we need to apply 
when
              ov (make-overlay b e))
        (overlay-put
         ov 'face
-        (cons (cond ((org-face-from-face-or-color
-                      'priority nil
-                      (cdr (assoc p org-priority-faces))))
-                    ((and (listp org-agenda-fontify-priorities)
-                          (org-face-from-face-or-color
-                           'priority nil
-                           (cdr (assoc p org-agenda-fontify-priorities)))))
-                    ((equal p l) 'italic)
-                    ((equal p h) 'bold))
-              'org-priority))
+        (let ((special-face
+               (cond ((org-face-from-face-or-color
+                       'priority 'org-priority
+                       (cdr (assoc p org-priority-faces))))
+                     ((and (listp org-agenda-fontify-priorities)
+                           (org-face-from-face-or-color
+                            'priority 'org-priority
+                            (cdr (assoc p org-agenda-fontify-priorities)))))
+                     ((equal p l) 'italic)
+                     ((equal p h) 'bold))))
+          (if special-face (list special-face 'org-priority) 'org-priority)))
        (overlay-put ov 'org-type 'org-priority)))))
 
 (defvar org-depend-tag-blocked)
@@ -3819,39 +3852,39 @@ FILTER-ALIST is an alist of filters we need to apply 
when
 When INVISIBLE is non-nil, hide currently blocked TODO instead of
 dimming them."
   (interactive "P")
-  (when (org-called-interactively-p 'interactive)
+  (when (called-interactively-p 'interactive)
     (message "Dim or hide blocked tasks..."))
-  (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-blocked-todo)
-                       (delete-overlay o)))
-       (overlays-in (point-min) (point-max)))
+  (dolist (o (overlays-in (point-min) (point-max)))
+    (when (eq (overlay-get o 'org-type) 'org-blocked-todo)
+      (delete-overlay o)))
   (save-excursion
     (let ((inhibit-read-only t)
          (org-depend-tag-blocked nil)
-         (invis (or (not (null invisible))
-                    (eq org-agenda-dim-blocked-tasks 'invisible)))
-         org-blocked-by-checkboxes
-         invis1 b e p ov h l)
+         org-blocked-by-checkboxes)
       (goto-char (point-min))
-      (while (let ((pos (next-single-property-change (point) 'todo-state)))
-              (and pos (goto-char (1+ pos))))
-       (setq org-blocked-by-checkboxes nil invis1 invis)
+      (while (let ((pos (text-property-not-all
+                        (point) (point-max) 'todo-state nil)))
+              (when pos (goto-char pos)))
+       (setq org-blocked-by-checkboxes nil)
        (let ((marker (org-get-at-bol 'org-hd-marker)))
-         (when (and marker
+         (when (and (markerp marker)
                     (with-current-buffer (marker-buffer marker)
                       (save-excursion (goto-char marker)
                                       (org-entry-blocked-p))))
-           (if org-blocked-by-checkboxes (setq invis1 nil))
-           (setq b (if invis1
-                       (max (point-min) (1- (point-at-bol)))
-                     (point-at-bol))
-                 e (point-at-eol)
-                 ov (make-overlay b e))
-           (if invis1
-               (progn (overlay-put ov 'invisible t)
-                      (overlay-put ov 'intangible t))
-             (overlay-put ov 'face 'org-agenda-dimmed-todo-face))
-           (overlay-put ov 'org-type 'org-blocked-todo))))))
-  (when (org-called-interactively-p 'interactive)
+           ;; Entries blocked by checkboxes cannot be made invisible.
+           ;; See `org-agenda-dim-blocked-tasks' for details.
+           (let* ((really-invisible
+                   (and (not org-blocked-by-checkboxes)
+                        (or invisible (eq org-agenda-dim-blocked-tasks
+                                          'invisible))))
+                  (ov (make-overlay (if really-invisible (line-end-position 0)
+                                      (line-beginning-position))
+                                    (line-end-position))))
+             (if really-invisible (overlay-put ov 'invisible t)
+               (overlay-put ov 'face 'org-agenda-dimmed-todo-face))
+             (overlay-put ov 'org-type 'org-blocked-todo))))
+       (forward-line))))
+  (when (called-interactively-p 'interactive)
     (message "Dim or hide blocked tasks...done")))
 
 (defvar org-agenda-skip-function nil
@@ -3908,9 +3941,9 @@ functions do."
 
 (defun org-agenda-new-marker (&optional pos)
   "Return a new agenda marker.
-Org-mode keeps a list of these markers and resets them when they are
-no longer in use."
-  (let ((m (copy-marker (or pos (point)))))
+Maker is at point, or at POS if non-nil.  Org mode keeps a list of
+these markers and resets them when they are no longer in use."
+  (let ((m (copy-marker (or pos (point)) t)))
     (setq org-agenda-last-marker-time (float-time))
     (if org-agenda-buffer
        (with-current-buffer org-agenda-buffer
@@ -3972,13 +4005,12 @@ This check for agenda markers in all agenda buffers 
currently active."
 
 (defun org-agenda-get-day-face (date)
   "Return the face DATE should be displayed with."
-  (or (and (functionp org-agenda-day-face-function)
-          (funcall org-agenda-day-face-function date))
-      (cond ((org-agenda-todayp date)
-            'org-agenda-date-today)
-           ((member (calendar-day-of-week date) org-agenda-weekend-days)
-            'org-agenda-date-weekend)
-           (t 'org-agenda-date))))
+  (cond ((and (functionp org-agenda-day-face-function)
+             (funcall org-agenda-day-face-function date)))
+       ((org-agenda-today-p date) 'org-agenda-date-today)
+       ((memq (calendar-day-of-week date) org-agenda-weekend-days)
+        'org-agenda-date-weekend)
+       (t 'org-agenda-date)))
 
 ;;; Agenda timeline
 
@@ -3986,12 +4018,16 @@ This check for agenda markers in all agenda buffers 
currently active."
 (defvar org-agenda-show-log-scoped) ;; dynamically scope in `org-timeline' or 
`org-agenda-list'
 
 (defun org-timeline (&optional dotodo)
-  "Show a time-sorted view of the entries in the current org file.
-Only entries with a time stamp of today or later will be listed.  With
-\\[universal-argument] prefix, all unfinished TODO items will also be shown,
+  "Show a time-sorted view of the entries in the current Org file.
+
+Only entries with a time stamp of today or later will be listed.
+
+With `\\[universal-argument]' prefix, all unfinished TODO items will also be \
+shown,
 under the current date.
-If the buffer contains an active region, only check the region for
-dates."
+
+If the buffer contains an active region, only check the region
+for dates."
   (interactive "P")
   (let* ((dopast t)
         (org-agenda-show-log-scoped org-agenda-show-log)
@@ -4160,13 +4196,14 @@ items if they have an hour specification like [h]h:mm."
   (catch 'exit
     (setq org-agenda-buffer-name
          (or org-agenda-buffer-tmp-name
+             (and org-agenda-doing-sticky-redo org-agenda-buffer-name)
              (if org-agenda-sticky
                  (cond ((and org-keys (stringp org-match))
                         (format "*Org Agenda(%s:%s)*" org-keys org-match))
                        (org-keys
                         (format "*Org Agenda(%s)*" org-keys))
                        (t "*Org Agenda(a)*")))
-             org-agenda-buffer-name))
+             "*Org Agenda*"))
     (org-agenda-prepare "Day/Week")
     (setq start-day (or start-day org-agenda-start-day))
     (if (stringp start-day)
@@ -4174,8 +4211,7 @@ items if they have an hour specification like [h]h:mm."
        (setq start-day (time-to-days (org-read-date nil t start-day))))
     (org-compile-prefix-format 'agenda)
     (org-set-sorting-strategy 'agenda)
-    (let* ((span (org-agenda-ndays-to-span
-                 (or span org-agenda-ndays org-agenda-span)))
+    (let* ((span (org-agenda-ndays-to-span (or span org-agenda-span)))
           (today (org-today))
           (sd (or start-day today))
           (ndays (org-agenda-span-to-ndays span sd))
@@ -4205,9 +4241,9 @@ items if they have an hour specification like [h]h:mm."
       (setq day-numbers (nreverse day-numbers))
       (setq clocktable-start (car day-numbers)
            clocktable-end (1+ (or (org-last day-numbers) 0)))
-      (org-set-local 'org-starting-day (car day-numbers))
-      (org-set-local 'org-arg-loc arg)
-      (org-set-local 'org-agenda-current-span (org-agenda-ndays-to-span span))
+      (setq-local org-starting-day (car day-numbers))
+      (setq-local org-arg-loc arg)
+      (setq-local org-agenda-current-span (org-agenda-ndays-to-span span))
       (unless org-agenda-compact-blocks
        (let* ((d1 (car day-numbers))
               (d2 (org-last day-numbers))
@@ -4353,10 +4389,10 @@ START-DAY is an absolute time value."
        ((eq span 'fortnight) 14)
        ((eq span 'month)
         (let ((date (calendar-gregorian-from-absolute start-day)))
-          (calendar-last-day-of-month (car date) (caddr date))))
+          (calendar-last-day-of-month (car date) (cl-caddr date))))
        ((eq span 'year)
         (let ((date (calendar-gregorian-from-absolute start-day)))
-          (if (calendar-leap-year-p (caddr date)) 366 365)))))
+          (if (calendar-leap-year-p (cl-caddr date)) 366 365)))))
 
 (defun org-agenda-span-name (span)
   "Return a SPAN name."
@@ -4371,7 +4407,7 @@ START-DAY is an absolute time value."
 (defvar org-agenda-search-history nil)
 
 (defvar org-search-syntax-table nil
-  "Special syntax table for org-mode search.
+  "Special syntax table for Org search.
 In this table, we have single quotes not as word constituents, to
 that when \"+Ameli\" is searched as a work, it will also match \"Ameli's\"")
 
@@ -4444,7 +4480,7 @@ in `org-agenda-text-search-extra-files'."
         (full-words org-agenda-search-view-force-full-words)
         (org-agenda-text-search-extra-files org-agenda-text-search-extra-files)
         regexp rtn rtnall files file pos inherited-tags
-        marker category category-pos level tags c neg re boolean
+        marker category level tags c neg re boolean
         ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str)
     (unless (and (not edit-at)
                 (stringp string)
@@ -4576,7 +4612,7 @@ in `org-agenda-text-search-extra-files'."
                                  (> (org-reduced-level (org-outline-level))
                                     org-agenda-search-view-max-outline-level)
                                  (forward-line -1)
-                                 (outline-back-to-heading t)))
+                                 (org-back-to-heading t)))
                      (skip-chars-forward "* ")
                      (setq beg (point-at-bol)
                            beg1 (point)
@@ -4611,7 +4647,6 @@ in `org-agenda-text-search-extra-files'."
                        (setq marker (org-agenda-new-marker (point))
                              category (org-get-category)
                              level (make-string (org-reduced-level 
(org-outline-level)) ? )
-                             category-pos (get-text-property (point) 
'org-category-position)
                              inherited-tags
                              (or (eq org-agenda-show-inherited-tags 'always)
                                  (and (listp org-agenda-show-inherited-tags)
@@ -4630,8 +4665,7 @@ in `org-agenda-text-search-extra-files'."
                          'org-todo-regexp org-todo-regexp
                          'level level
                          'org-complex-heading-regexp org-complex-heading-regexp
-                         'priority 1000 'org-category category
-                         'org-category-position category-pos
+                         'priority 1000
                          'type "search")
                        (push txt ee)
                        (goto-char (1- end))))))))))
@@ -4648,8 +4682,12 @@ in `org-agenda-text-search-extra-files'."
        (add-text-properties pos (1- (point)) (list 'face 'org-warning))
        (setq pos (point))
        (unless org-agenda-multi
-         (insert (substitute-command-keys
-                  "Press `[', `]' to add/sub word, `{', `}' to add/sub regexp, 
`C-u r' to edit\n"))
+         (insert (substitute-command-keys "\
+Press `\\[org-agenda-manipulate-query-add]', \
+`\\[org-agenda-manipulate-query-subtract]' to add/sub word, \
+`\\[org-agenda-manipulate-query-add-re]', \
+`\\[org-agenda-manipulate-query-subtract-re]' to add/sub regexp, \
+`\\[universal-argument] \\[org-agenda-redo]' to edit\n"))
          (add-text-properties pos (1- (point))
                               (list 'face 'org-agenda-structure))))
       (org-agenda-mark-header-line (point-min))
@@ -4686,7 +4724,7 @@ in `org-agenda-text-search-extra-files'."
 (defun org-todo-list (&optional arg)
   "Show all (not done) TODO entries from all agenda file in a single list.
 The prefix arg can be used to select a specific TODO keyword and limit
-the list to these.  When using \\[universal-argument], you will be prompted
+the list to these.  When using `\\[universal-argument]', you will be prompted
 for a keyword.  A numeric prefix directly selects the Nth keyword in
 `org-todo-keywords-1'."
   (interactive "P")
@@ -4704,8 +4742,8 @@ for a keyword.  A numeric prefix directly selects the Nth 
keyword in
         rtn rtnall files file pos)
     (when (equal arg '(4))
       (setq org-select-this-todo-keyword
-           (org-icompleting-read "Keyword (or KWD1|K2D2|...): "
-                                 (mapcar 'list kwds) nil nil)))
+           (completing-read "Keyword (or KWD1|K2D2|...): "
+                            (mapcar #'list kwds) nil nil)))
     (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
     (catch 'exit
       (if org-agenda-sticky
@@ -4743,7 +4781,8 @@ for a keyword.  A numeric prefix directly selects the Nth 
keyword in
                 org-select-this-todo-keyword))
        (setq pos (point))
        (unless org-agenda-multi
-         (insert (substitute-command-keys "Available with `N r': (0)[ALL]"))
+         (insert (substitute-command-keys "Available with \
+`N \\[org-agenda-redo]': (0)[ALL]"))
          (let ((n 0) s)
            (mapc (lambda (x)
                    (setq s (format "(%d)%s" (setq n (1+ n)) x))
@@ -4779,6 +4818,7 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
   (let* ((org-tags-match-list-sublevels
          org-tags-match-list-sublevels)
         (completion-ignore-case t)
+        (org--matcher-tags-todo-only todo-only)
         rtn rtnall files file pos matcher
         buffer)
     (when (and (stringp match) (not (string-match "\\S-" match)))
@@ -4794,13 +4834,15 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
       ;; expanding tags within `org-make-tags-matcher'
       (org-agenda-prepare (concat "TAGS " match))
       (setq matcher (org-make-tags-matcher match)
-           match (car matcher) matcher (cdr matcher))
+           match (car matcher)
+           matcher (cdr matcher))
       (org-compile-prefix-format 'tags)
       (org-set-sorting-strategy 'tags)
       (setq org-agenda-query-string match)
       (setq org-agenda-redo-command
-           (list 'org-tags-view `(quote ,todo-only)
-                 (list 'if 'current-prefix-arg nil `(quote 
,org-agenda-query-string))))
+           (list 'org-tags-view
+                 `(quote ,org--matcher-tags-todo-only)
+                 `(if current-prefix-arg nil ,org-agenda-query-string)))
       (setq files (org-agenda-files nil 'ifmode)
            rtnall nil)
       (while (setq file (pop files))
@@ -4823,7 +4865,9 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
                      (narrow-to-region org-agenda-restrict-begin
                                        org-agenda-restrict-end)
                    (widen))
-                 (setq rtn (org-scan-tags 'agenda matcher todo-only))
+                 (setq rtn (org-scan-tags 'agenda
+                                          matcher
+                                          org--matcher-tags-todo-only))
                  (setq rtnall (append rtnall rtn))))))))
       (if org-agenda-overriding-header
          (insert (org-add-props (copy-sequence org-agenda-overriding-header)
@@ -4839,18 +4883,21 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
        (setq pos (point))
        (unless org-agenda-multi
          (insert (substitute-command-keys
-                  "Press `C-u r' to search again with new search string\n")))
-       (add-text-properties pos (1- (point)) (list 'face 
'org-agenda-structure)))
+                  "Press `\\[universal-argument] \\[org-agenda-redo]' \
+to search again with new search string\n")))
+       (add-text-properties pos (1- (point))
+                            (list 'face 'org-agenda-structure)))
       (org-agenda-mark-header-line (point-min))
       (when rtnall
        (insert (org-agenda-finalize-entries rtnall 'tags) "\n"))
       (goto-char (point-min))
       (or org-agenda-multi (org-agenda-fit-window-to-buffer))
-      (add-text-properties (point-min) (point-max)
-                          `(org-agenda-type tags
-                                            org-last-args (,todo-only ,match)
-                                            org-redo-cmd 
,org-agenda-redo-command
-                                            org-series-cmd ,org-cmd))
+      (add-text-properties
+       (point-min) (point-max)
+       `(org-agenda-type tags
+                        org-last-args (,org--matcher-tags-todo-only ,match)
+                        org-redo-cmd ,org-agenda-redo-command
+                        org-series-cmd ,org-cmd))
       (org-agenda-finalize)
       (setq buffer-read-only t))))
 
@@ -5038,50 +5085,53 @@ Stuck projects are project that have no next actions.  
For the definitions
 of what a project is and how to check if it stuck, customize the variable
 `org-stuck-projects'."
   (interactive)
-  (let* ((org-agenda-skip-function
-         'org-agenda-skip-entry-when-regexp-matches-in-subtree)
-        ;; We could have used org-agenda-skip-if here.
-        (org-agenda-overriding-header
+  (let* ((org-agenda-overriding-header
          (or org-agenda-overriding-header "List of stuck projects: "))
         (matcher (nth 0 org-stuck-projects))
         (todo (nth 1 org-stuck-projects))
-        (todo-wds (if (member "*" todo)
-                      (progn
-                        (org-agenda-prepare-buffers (org-agenda-files
-                                                     nil 'ifmode))
-                        (org-delete-all
-                         org-done-keywords-for-agenda
-                         (copy-sequence org-todo-keywords-for-agenda)))
-                    todo))
-        (todo-re (concat "^\\*+[ \t]+\\("
-                         (mapconcat 'identity todo-wds "\\|")
-                         "\\)\\>"))
         (tags (nth 2 org-stuck-projects))
-        (tags-re (if (member "*" tags)
-                     (concat org-outline-regexp-bol
-                             (org-re ".*:[[:alnum:address@hidden:[ \t]*$"))
-                   (if tags
-                       (concat org-outline-regexp-bol
-                               ".*:\\("
-                               (mapconcat 'identity tags "\\|")
-                               (org-re "\\):[[:alnum:address@hidden:]*[ 
\t]*$")))))
-        (gen-re (nth 3 org-stuck-projects))
-        (re-list
-         (delq nil
-               (list
-                (if todo todo-re)
-                (if tags tags-re)
-                (and gen-re (stringp gen-re) (string-match "\\S-" gen-re)
-                     gen-re)))))
-    (setq org-agenda-skip-regexp
-         (if re-list
-             (mapconcat 'identity re-list "\\|")
-           (error "No information how to identify unstuck projects")))
+        (gen-re (org-string-nw-p (nth 3 org-stuck-projects)))
+        (todo-wds
+         (if (not (member "*" todo)) todo
+           (org-agenda-prepare-buffers (org-agenda-files nil 'ifmode))
+           (org-delete-all org-done-keywords-for-agenda
+                           (copy-sequence org-todo-keywords-for-agenda))))
+        (todo-re (and todo
+                      (format "^\\*+[ \t]+\\(%s\\)\\>"
+                              (mapconcat #'identity todo-wds "\\|"))))
+        (tags-re (cond ((null tags) nil)
+                       ((member "*" tags)
+                        (eval-when-compile
+                          (concat org-outline-regexp-bol
+                                  ".*:[[:alnum:address@hidden:[ \t]*$")))
+                       (tags (concat org-outline-regexp-bol
+                                     ".*:\\("
+                                     (mapconcat #'identity tags "\\|")
+                                     "\\):[[:alnum:address@hidden:]*[ \t]*$"))
+                       (t nil)))
+        (re-list (delq nil (list todo-re tags-re gen-re)))
+        (skip-re
+         (if (null re-list)
+             (error "Missing information to identify unstuck projects")
+           (mapconcat #'identity re-list "\\|")))
+        (org-agenda-skip-function
+         ;; Skip entry if `org-agenda-skip-regexp' matches anywhere
+         ;; in the subtree.
+         `(lambda ()
+            (and (save-excursion
+                   (let ((case-fold-search nil))
+                     (re-search-forward
+                      ,skip-re (save-excursion (org-end-of-subtree t)) t)))
+                 (progn (outline-next-heading) (point))))))
     (org-tags-view nil matcher)
     (setq org-agenda-buffer-name (buffer-name))
     (with-current-buffer org-agenda-buffer-name
       (setq org-agenda-redo-command
-           `(org-agenda-list-stuck-projects ,current-prefix-arg)))))
+           `(org-agenda-list-stuck-projects ,current-prefix-arg))
+      (let ((inhibit-read-only t))
+        (add-text-properties
+         (point-min) (point-max)
+         `(org-redo-cmd ,org-agenda-redo-command))))))
 
 ;;; Diary integration
 
@@ -5159,7 +5209,7 @@ date.  It also removes lines that contain only 
whitespace."
   (while (re-search-forward "^ +\n" nil t)
     (replace-match ""))
   (goto-char (point-min))
-  (if (re-search-forward "^Org-mode dummy\n?" nil t)
+  (if (re-search-forward "^Org mode dummy\n?" nil t)
       (replace-match ""))
   (run-hooks 'org-agenda-cleanup-fancy-diary-hook))
 
@@ -5177,7 +5227,7 @@ date.  It also removes lines that contain only 
whitespace."
           (setq string (org-modify-diary-entry-string string))))))
 
 (defun org-modify-diary-entry-string (string)
-  "Add text properties to string, allowing org-mode to act on it."
+  "Add text properties to string, allowing Org to act on it."
   (org-add-props string nil
     'mouse-face 'highlight
     'help-echo (if buffer-file-name
@@ -5193,9 +5243,9 @@ Needed to avoid empty dates which mess up holiday 
display."
   ;; Catch the error if dealing with the new add-to-diary-alist
   (when org-disable-agenda-to-diary
     (condition-case nil
-       (org-add-to-diary-list original-date "Org-mode dummy" "")
+       (org-add-to-diary-list original-date "Org mode dummy" "")
       (error
-       (org-add-to-diary-list original-date  "Org-mode dummy" "" nil)))))
+       (org-add-to-diary-list original-date  "Org mode dummy" "" nil)))))
 
 (defun org-add-to-diary-list (&rest args)
   (if (fboundp 'diary-add-to-list)
@@ -5265,67 +5315,77 @@ function from a program - use 
`org-agenda-get-day-entries' instead."
 
 ;;; Agenda entry finders
 
+(defun org-agenda--timestamp-to-absolute (&rest args)
+  "Call `org-time-string-to-absolute' with ARGS.
+However, throw `:skip' whenever an error is raised."
+  (condition-case e
+      (apply #'org-time-string-to-absolute args)
+    (org-diary-sexp-no-match (throw :skip nil))
+    (error
+     (message "%s; Skipping entry" (error-message-string e))
+     (throw :skip nil))))
+
 (defun org-agenda-get-day-entries (file date &rest args)
   "Does the work for `org-diary' and `org-agenda'.
 FILE is the path to a file to be checked for entries.  DATE is date like
 the one returned by `calendar-current-date'.  ARGS are symbols indicating
 which kind of entries should be extracted.  For details about these, see
 the documentation of `org-diary'."
-  (setq args (or args org-agenda-entry-types))
   (let* ((org-startup-folded nil)
         (org-startup-align-all-tables nil)
-        (buffer (if (file-exists-p file)
-                    (org-get-agenda-file-buffer file)
-                  (error "No such file %s" file)))
-        arg results rtn deadline-results)
+        (buffer (if (file-exists-p file) (org-get-agenda-file-buffer file)
+                  (error "No such file %s" file))))
     (if (not buffer)
-       ;; If file does not exist, make sure an error message ends up in diary
+       ;; If file does not exist, signal it in diary nonetheless.
        (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
       (with-current-buffer buffer
        (unless (derived-mode-p 'org-mode)
          (error "Agenda file %s is not in `org-mode'" file))
        (setq org-agenda-buffer (or org-agenda-buffer buffer))
-       (let ((case-fold-search nil))
-         (save-excursion
-           (save-restriction
-             (if (eq buffer org-agenda-restrict)
-                 (narrow-to-region org-agenda-restrict-begin
-                                   org-agenda-restrict-end)
-               (widen))
-             ;; The way we repeatedly append to `results' makes it O(n^2) :-(
-             (while (setq arg (pop args))
-               (cond
-                ((and (eq arg :todo)
-                      (equal date (calendar-gregorian-from-absolute
-                                   (org-today))))
-                 (setq rtn (org-agenda-get-todos))
-                 (setq results (append results rtn)))
-                ((eq arg :timestamp)
-                 (setq rtn (org-agenda-get-blocks))
-                 (setq results (append results rtn))
-                 (setq rtn (org-agenda-get-timestamps deadline-results))
-                 (setq results (append results rtn)))
-                ((eq arg :sexp)
-                 (setq rtn (org-agenda-get-sexps))
-                 (setq results (append results rtn)))
-                ((eq arg :scheduled)
-                 (setq rtn (org-agenda-get-scheduled deadline-results))
-                 (setq results (append results rtn)))
-                ((eq arg :scheduled*)
-                 (setq rtn (org-agenda-get-scheduled deadline-results t))
-                 (setq results (append results rtn)))
-                ((eq arg :closed)
-                 (setq rtn (org-agenda-get-progress))
-                 (setq results (append results rtn)))
-                ((eq arg :deadline)
-                 (setq rtn (org-agenda-get-deadlines))
-                 (setq deadline-results (copy-sequence rtn))
-                 (setq results (append results rtn)))
-                ((eq arg :deadline*)
-                 (setq rtn (org-agenda-get-deadlines t))
-                 (setq deadline-results (copy-sequence rtn))
-                 (setq results (append results rtn))))))))
-       results))))
+       (setf org-agenda-current-date date)
+       (save-excursion
+         (save-restriction
+           (if (eq buffer org-agenda-restrict)
+               (narrow-to-region org-agenda-restrict-begin
+                                 org-agenda-restrict-end)
+             (widen))
+           ;; Rationalize ARGS.  Also make sure `:deadline' comes
+           ;; first in order to populate DEADLINES before passing it.
+           ;;
+           ;; We use `delq' since `org-uniquify' duplicates ARGS,
+           ;; guarding us from modifying `org-agenda-entry-types'.
+           (setf args (org-uniquify (or args org-agenda-entry-types)))
+           (when (and (memq :scheduled args) (memq :scheduled* args))
+             (setf args (delq :scheduled* args)))
+           (cond
+            ((memq :deadline args)
+             (setf args (cons :deadline
+                              (delq :deadline (delq :deadline* args)))))
+            ((memq :deadline* args)
+             (setf args (cons :deadline* (delq :deadline* args)))))
+           ;; Collect list of headlines.  Return them flattened.
+           (let ((case-fold-search nil) results deadlines)
+             (dolist (arg args (apply #'nconc (nreverse results)))
+               (pcase arg
+                 ((and :todo (guard (org-agenda-today-p date)))
+                  (push (org-agenda-get-todos) results))
+                 (:timestamp
+                  (push (org-agenda-get-blocks) results)
+                  (push (org-agenda-get-timestamps deadlines) results))
+                 (:sexp
+                  (push (org-agenda-get-sexps) results))
+                 (:scheduled
+                  (push (org-agenda-get-scheduled deadlines) results))
+                 (:scheduled*
+                  (push (org-agenda-get-scheduled deadlines t) results))
+                 (:closed
+                  (push (org-agenda-get-progress) results))
+                 (:deadline
+                  (setf deadlines (org-agenda-get-deadlines))
+                  (push deadlines results))
+                 (:deadline*
+                  (setf deadlines (org-agenda-get-deadlines t))
+                  (push deadlines results)))))))))))
 
 (defsubst org-em (x y list)
   "Is X or Y a member of LIST?"
@@ -5334,6 +5394,40 @@ the documentation of `org-diary'."
 (defvar org-heading-keyword-regexp-format) ; defined in org.el
 (defvar org-agenda-sorting-strategy-selected nil)
 
+(defun org-agenda-entry-get-agenda-timestamp (pom)
+  "Retrieve timestamp information for sorting agenda views.
+Given a point or marker POM, returns a cons cell of the timestamp
+and the timestamp type relevant for the sorting strategy in
+`org-agenda-sorting-strategy-selected'."
+  (let (ts ts-date-type)
+    (save-match-data
+      (cond ((org-em 'scheduled-up 'scheduled-down
+                    org-agenda-sorting-strategy-selected)
+            (setq ts (org-entry-get pom "SCHEDULED")
+                  ts-date-type " scheduled"))
+           ((org-em 'deadline-up 'deadline-down
+                    org-agenda-sorting-strategy-selected)
+            (setq ts (org-entry-get pom "DEADLINE")
+                  ts-date-type " deadline"))
+           ((org-em 'ts-up 'ts-down
+                    org-agenda-sorting-strategy-selected)
+            (setq ts (org-entry-get pom "TIMESTAMP")
+                  ts-date-type " timestamp"))
+           ((org-em 'tsia-up 'tsia-down
+                    org-agenda-sorting-strategy-selected)
+            (setq ts (org-entry-get pom "TIMESTAMP_IA")
+                  ts-date-type " timestamp_ia"))
+           ((org-em 'timestamp-up 'timestamp-down
+                    org-agenda-sorting-strategy-selected)
+            (setq ts (or (org-entry-get pom "SCHEDULED")
+                         (org-entry-get pom "DEADLINE")
+                         (org-entry-get pom "TIMESTAMP")
+                         (org-entry-get pom "TIMESTAMP_IA"))
+                  ts-date-type ""))
+           (t (setq ts-date-type "")))
+      (cons (when ts (ignore-errors (org-time-string-to-absolute ts)))
+           ts-date-type))))
+
 (defun org-agenda-get-todos ()
   "Return the TODO information for agenda display."
   (let* ((props (list 'face nil
@@ -5345,6 +5439,7 @@ the documentation of `org-diary'."
                      'help-echo
                      (format "mouse-2 or RET jump to org file %s"
                              (abbreviate-file-name buffer-file-name))))
+        (case-fold-search nil)
         (regexp (format org-heading-keyword-regexp-format
                         (cond
                          ((and org-select-this-todo-keyword
@@ -5358,7 +5453,8 @@ the documentation of `org-diary'."
                                               "|")
                                              "\\|") "\\)"))
                          (t org-not-done-regexp))))
-        marker priority category category-pos level tags todo-state ts-date 
ts-date-type
+        marker priority category level tags todo-state
+        ts-date ts-date-type ts-date-pair
         ee txt beg end inherited-tags todo-state-end-pos)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
@@ -5378,36 +5474,10 @@ the documentation of `org-diary'."
        (goto-char (match-beginning 2))
        (setq marker (org-agenda-new-marker (match-beginning 0))
              category (org-get-category)
-             ts-date (let (ts)
-                       (save-match-data
-                         (cond ((org-em 'scheduled-up 'scheduled-down
-                                        org-agenda-sorting-strategy-selected)
-                                (setq ts (org-entry-get (point) "SCHEDULED")
-                                      ts-date-type " scheduled"))
-                               ((org-em 'deadline-up 'deadline-down
-                                        org-agenda-sorting-strategy-selected)
-                                (setq ts (org-entry-get (point) "DEADLINE")
-                                      ts-date-type " deadline"))
-                               ((org-em 'ts-up 'ts-down
-                                        org-agenda-sorting-strategy-selected)
-                                (setq ts (org-entry-get (point) "TIMESTAMP")
-                                      ts-date-type " timestamp"))
-                               ((org-em 'tsia-up 'tsia-down
-                                        org-agenda-sorting-strategy-selected)
-                                (setq ts (org-entry-get (point) "TIMESTAMP_IA")
-                                      ts-date-type " timestamp_ia"))
-                               ((org-em 'timestamp-up 'timestamp-down
-                                        org-agenda-sorting-strategy-selected)
-                                (setq ts (or (org-entry-get (point) 
"SCHEDULED")
-                                             (org-entry-get (point) "DEADLINE")
-                                             (org-entry-get (point) 
"TIMESTAMP")
-                                             (org-entry-get (point) 
"TIMESTAMP_IA"))
-                                      ts-date-type ""))
-                               (t (setq ts-date-type "")))
-                         (when ts (ignore-errors (org-time-string-to-absolute 
ts)))))
-             category-pos (get-text-property (point) 'org-category-position)
-             txt (org-trim
-                  (buffer-substring (match-beginning 2) (match-end 0)))
+             ts-date-pair (org-agenda-entry-get-agenda-timestamp (point))
+             ts-date (car ts-date-pair)
+             ts-date-type (cdr ts-date-pair)
+             txt (org-trim (buffer-substring (match-beginning 2) (match-end 
0)))
              inherited-tags
              (or (eq org-agenda-show-inherited-tags 'always)
                  (and (listp org-agenda-show-inherited-tags)
@@ -5421,10 +5491,9 @@ the documentation of `org-diary'."
              priority (1+ (org-get-priority txt)))
        (org-add-props txt props
          'org-marker marker 'org-hd-marker marker
-         'priority priority 'org-category category
+         'priority priority
          'level level
          'ts-date ts-date
-         'org-category-position category-pos
          'type (concat "todo" ts-date-type) 'todo-state todo-state)
        (push txt ee)
        (if org-agenda-todo-list-sublevels
@@ -5473,7 +5542,7 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
               (cond
                ((memq org-agenda-todo-ignore-deadlines '(t all)) t)
                ((eq org-agenda-todo-ignore-deadlines 'far)
-                (not (org-deadline-close (match-string 1))))
+                (not (org-deadline-close-p (match-string 1))))
                ((eq org-agenda-todo-ignore-deadlines 'future)
                 (> (org-time-stamp-to-now
                     (match-string 1) 
org-agenda-todo-ignore-time-comparison-use-seconds) 0))
@@ -5483,7 +5552,7 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
                ((numberp org-agenda-todo-ignore-deadlines)
                 (org-agenda-todo-custom-ignore-p
                  (match-string 1) org-agenda-todo-ignore-deadlines))
-               (t (org-deadline-close (match-string 1)))))
+               (t (org-deadline-close-p (match-string 1)))))
          (and org-agenda-todo-ignore-timestamp
               (let ((buffer (current-buffer))
                     (regexp
@@ -5512,24 +5581,27 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
                        (match-string 1) org-agenda-todo-ignore-timestamp))
                      (t))))))))))
 
-(defun org-agenda-get-timestamps (&optional deadline-results)
-  "Return the date stamp information for agenda display."
+(defun org-agenda-get-timestamps (&optional deadlines)
+  "Return the date stamp information for agenda display.
+Optional argument DEADLINES is a list of deadline items to be
+displayed in agenda view."
   (let* ((props (list 'face 'org-agenda-calendar-event
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
                      'org-complex-heading-regexp org-complex-heading-regexp
                      'mouse-face 'highlight
                      'help-echo
-                     (format "mouse-2 or RET jump to org file %s"
+                     (format "mouse-2 or RET jump to Org file %s"
                              (abbreviate-file-name buffer-file-name))))
-        (d1 (calendar-absolute-from-gregorian date))
-        mm
+        (current (calendar-absolute-from-gregorian date))
+        (today (org-today))
         (deadline-position-alist
-         (mapcar (lambda (a) (and (setq mm (get-text-property
-                                            0 'org-hd-marker a))
-                                  (cons (marker-position mm) a)))
-                 deadline-results))
-        (remove-re org-ts-regexp)
+         (mapcar (lambda (d)
+                   (let ((m (get-text-property 0 'org-hd-marker d)))
+                     (and m (marker-position m))))
+                 deadlines))
+        ;; Match time-stamps set to current date, time-stamps with
+        ;; a repeater, and S-exp time-stamps.
         (regexp
          (concat
           (if org-agenda-include-inactive-timestamps "[[<]" "<")
@@ -5537,97 +5609,106 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
            (substring
             (format-time-string
              (car org-time-stamp-formats)
-             (apply 'encode-time  ; DATE bound by calendar
+             (apply #'encode-time      ; DATE bound by calendar
                     (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
             1 11))
           "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[hdwmy]>\\)"
           "\\|\\(<%%\\(([^>\n]+)\\)>\\)"))
-        marker hdmarker deadlinep scheduledp clockp closedp inactivep
-        donep tmp priority category category-pos level ee txt timestr tags
-        b0 b3 e3 head todo-state end-of-match show-all warntime habitp
-        inherited-tags ts-date)
+        timestamp-items)
     (goto-char (point-min))
-    (while (setq end-of-match (re-search-forward regexp nil t))
-      (setq b0 (match-beginning 0)
-           b3 (match-beginning 3) e3 (match-end 3)
-           todo-state (save-match-data (ignore-errors (org-get-todo-state)))
-           habitp (and (functionp 'org-is-habit-p) (save-match-data 
(org-is-habit-p)))
-           show-all (or (eq org-agenda-repeating-timestamp-show-all t)
-                        (member todo-state
-                                org-agenda-repeating-timestamp-show-all)))
+    (while (re-search-forward regexp nil t)
+      ;; Skip date ranges, scheduled and deadlines, which are handled
+      ;; specially.  Also skip time-stamps before first headline as
+      ;; there would be no entry to add to the agenda.  Eventually,
+      ;; ignore clock entries.
       (catch :skip
-       (and (org-at-date-range-p) (throw :skip nil))
-       (org-agenda-skip)
-       (if (and (match-end 1)
-                (not (= d1 (org-time-string-to-absolute
-                            (match-string 1) d1 nil show-all
-                            (current-buffer) b0))))
-           (throw :skip nil))
-       (if (and e3
-                (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date)))
+       (save-match-data
+         (when (or (org-at-date-range-p)
+                   (org-at-planning-p)
+                   (org-before-first-heading-p)
+                   (and org-agenda-include-inactive-timestamps
+                        (org-at-clock-log-p)))
            (throw :skip nil))
-       (setq tmp (buffer-substring (max (point-min)
-                                        (- b0 org-ds-keyword-length))
-                                   b0)
-             timestr (if b3 "" (buffer-substring b0 (point-at-eol)))
-             inactivep (= (char-after b0) ?\[)
-             deadlinep (string-match org-deadline-regexp tmp)
-             scheduledp (string-match org-scheduled-regexp tmp)
-             closedp (and org-agenda-include-inactive-timestamps
-                          (string-match org-closed-string tmp))
-             clockp (and org-agenda-include-inactive-timestamps
-                         (or (string-match org-clock-string tmp)
-                             (string-match "]-+\\'" tmp)))
-             warntime (get-text-property (point) 'org-appt-warntime)
-             donep (member todo-state org-done-keywords))
-       (if (or scheduledp deadlinep closedp clockp
-               (and donep org-agenda-skip-timestamp-if-done))
+         (org-agenda-skip))
+       (let* ((pos (match-beginning 0))
+              (repeat (match-string 1))
+              (sexp-entry (match-string 3))
+              (time-stamp (if (or repeat sexp-entry) (match-string 0)
+                            (save-excursion
+                              (goto-char pos)
+                              (looking-at org-ts-regexp-both)
+                              (match-string 0))))
+              (todo-state (org-get-todo-state))
+              (show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                            (member todo-state
+                                    org-agenda-repeating-timestamp-show-all)))
+              (warntime (get-text-property (point) 'org-appt-warntime))
+              (done? (member todo-state org-done-keywords)))
+         ;; Possibly skip done tasks.
+         (when (and done? org-agenda-skip-timestamp-if-done)
            (throw :skip t))
-       (if (string-match ">" timestr)
-           ;; substring should only run to end of time stamp
-           (setq timestr (substring timestr 0 (match-end 0))))
-       (setq marker (org-agenda-new-marker b0)
-             category (org-get-category b0)
-             category-pos (get-text-property b0 'org-category-position))
-       (save-excursion
-         (if (not (re-search-backward org-outline-regexp-bol nil t))
-             (throw :skip nil)
-           (goto-char (match-beginning 0))
-           (if (and (eq t org-agenda-skip-timestamp-if-deadline-is-shown)
-                    (assoc (point) deadline-position-alist))
-               (throw :skip nil))
-           (setq hdmarker (org-agenda-new-marker)
-                 inherited-tags
-                 (or (eq org-agenda-show-inherited-tags 'always)
-                     (and (listp org-agenda-show-inherited-tags)
-                          (memq 'agenda org-agenda-show-inherited-tags))
-                     (and (eq org-agenda-show-inherited-tags t)
-                          (or (eq org-agenda-use-tag-inheritance t)
-                              (memq 'agenda org-agenda-use-tag-inheritance))))
-                 tags (org-get-tags-at nil (not inherited-tags))
-                 level (make-string (org-reduced-level (org-outline-level)) ? 
))
-           (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
-           (setq head (or (match-string 1) ""))
-           (setq txt (org-agenda-format-item
-                      (if inactivep org-agenda-inactive-leader nil)
-                      head level category tags timestr
-                      remove-re habitp)))
-         (setq priority (org-get-priority txt))
-         (org-add-props txt props 'priority priority
-                        'org-marker marker 'org-hd-marker hdmarker
-                        'org-category category 'date date
-                        'level level
-                        'ts-date
-                        (ignore-errors (org-time-string-to-absolute timestr))
-                        'org-category-position category-pos
-                        'todo-state todo-state
-                        'warntime warntime
-                        'type "timestamp")
-         (push txt ee))
-       (if org-agenda-skip-additional-timestamps-same-entry
-           (outline-next-heading)
-         (goto-char end-of-match))))
-    (nreverse ee)))
+         ;; S-exp entry doesn't match current day: skip it.
+         (when (and sexp-entry (not (org-diary-sexp-entry sexp-entry "" date)))
+           (throw :skip nil))
+         ;; When time-stamp doesn't match CURRENT but has a repeater,
+         ;; make sure it repeats on CURRENT.  Furthermore, if
+         ;; SHOW-ALL is nil, ensure that repeats are only the first
+         ;; before and the first after today.
+         (when (and repeat
+                    (if show-all
+                        (/= current
+                            (org-agenda--timestamp-to-absolute
+                             repeat current 'future (current-buffer) pos))
+                      (and (/= current
+                               (org-agenda--timestamp-to-absolute
+                                repeat today 'past (current-buffer) pos))
+                           (/= current
+                               (org-agenda--timestamp-to-absolute
+                                repeat today 'future (current-buffer) pos)))))
+           (throw :skip nil))
+         (save-excursion
+           (re-search-backward org-outline-regexp-bol nil t)
+           ;; Possibly skip time-stamp when a deadline is set.
+           (when (and org-agenda-skip-timestamp-if-deadline-is-shown
+                      (assq (point) deadline-position-alist))
+             (throw :skip nil))
+           (let* ((category (org-get-category pos))
+                  (inherited-tags
+                   (or (eq org-agenda-show-inherited-tags 'always)
+                       (and (consp org-agenda-show-inherited-tags)
+                            (memq 'agenda org-agenda-show-inherited-tags))
+                       (and (eq org-agenda-show-inherited-tags t)
+                            (or (eq org-agenda-use-tag-inheritance t)
+                                (memq 'agenda
+                                      org-agenda-use-tag-inheritance)))))
+                  (tags (org-get-tags-at nil (not inherited-tags)))
+                  (level (make-string (org-reduced-level (org-outline-level))
+                                      ?\s))
+                  (head (and (looking-at "\\*+[ \t]+\\(.*\\)")
+                             (match-string 1)))
+                  (inactive? (= (char-after pos) ?\[))
+                  (habit? (and (fboundp 'org-is-habit-p) (org-is-habit-p)))
+                  (item
+                   (org-agenda-format-item
+                    (and inactive? org-agenda-inactive-leader)
+                    head level category tags time-stamp org-ts-regexp habit?)))
+             (org-add-props item props
+               'priority (if habit?
+                             (org-habit-get-priority (org-habit-parse-todo))
+                           (org-get-priority item))
+               'org-marker (org-agenda-new-marker pos)
+               'org-hd-marker (org-agenda-new-marker)
+               'date date
+               'level level
+               'ts-date (if repeat (org-agenda--timestamp-to-absolute repeat)
+                          current)
+               'todo-state todo-state
+               'warntime warntime
+               'type "timestamp")
+             (push item timestamp-items))))
+       (when org-agenda-skip-additional-timestamps-same-entry
+         (outline-next-heading))))
+    (nreverse timestamp-items)))
 
 (defun org-agenda-get-sexps ()
   "Return the sexp information for agenda display."
@@ -5638,7 +5719,7 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
                      (format "mouse-2 or RET jump to org file %s"
                              (abbreviate-file-name buffer-file-name))))
         (regexp "^&?%%(")
-        marker category extra category-pos level ee txt tags entry
+        marker category extra level ee txt tags entry
         result beg b sexp sexp-entry todo-state warntime inherited-tags)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
@@ -5657,7 +5738,6 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
          (setq marker (org-agenda-new-marker beg)
                level (make-string (org-reduced-level (org-outline-level)) ? )
                category (org-get-category beg)
-               category-pos (get-text-property beg 'org-category-position)
                inherited-tags
                (or (eq org-agenda-show-inherited-tags 'always)
                    (and (listp org-agenda-show-inherited-tags)
@@ -5682,38 +5762,33 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
              (setq txt "SEXP entry returned empty string"))
            (setq txt (org-agenda-format-item extra txt level category tags 
'time))
            (org-add-props txt props 'org-marker marker
-                          'org-category category 'date date 'todo-state 
todo-state
-                          'org-category-position category-pos
-                          'level level
-                          'type "sexp" 'warntime warntime)
+                          'date date 'todo-state todo-state
+                          'level level 'type "sexp" 'warntime warntime)
            (push txt ee)))))
     (nreverse ee)))
 
 ;; Calendar sanity: define some functions that are independent of
 ;; `calendar-date-style'.
-;; Normally I would like to use ISO format when calling the diary functions,
-;; but to make sure we still have Emacs 22 compatibility we bind
-;; also `european-calendar-style' and use european format
 (defun org-anniversary (year month day &optional mark)
   "Like `diary-anniversary', but with fixed (ISO) order of arguments."
-  (org-no-warnings
-   (let ((calendar-date-style 'european) (european-calendar-style t))
-     (diary-anniversary day month year mark))))
+  (with-no-warnings
+    (let ((calendar-date-style 'iso))
+      (diary-anniversary year month day mark))))
 (defun org-cyclic (N year month day &optional mark)
   "Like `diary-cyclic', but with fixed (ISO) order of arguments."
-  (org-no-warnings
-   (let ((calendar-date-style 'european)       (european-calendar-style t))
-     (diary-cyclic N day month year mark))))
+  (with-no-warnings
+    (let ((calendar-date-style 'iso))
+      (diary-cyclic N year month day mark))))
 (defun org-block (Y1 M1 D1 Y2 M2 D2 &optional mark)
   "Like `diary-block', but with fixed (ISO) order of arguments."
-  (org-no-warnings
-   (let ((calendar-date-style 'european)       (european-calendar-style t))
-     (diary-block D1 M1 Y1 D2 M2 Y2 mark))))
+  (with-no-warnings
+    (let ((calendar-date-style 'iso))
+      (diary-block Y1 M1 D1 Y2 M2 D2 mark))))
 (defun org-date (year month day &optional mark)
   "Like `diary-date', but with fixed (ISO) order of arguments."
-  (org-no-warnings
-   (let ((calendar-date-style 'european)       (european-calendar-style t))
-     (diary-date day month year mark))))
+  (with-no-warnings
+    (let ((calendar-date-style 'iso))
+      (diary-date year month day mark))))
 
 ;; Define the `org-class' function
 (defun org-class (y1 m1 d1 y2 m2 d2 dayname &rest skip-weeks)
@@ -5740,26 +5815,6 @@ then those holidays will be skipped."
              (delq nil (mapcar (lambda(g) (member g skip-weeks)) h))))
      entry)))
 
-(defun org-diary-class (m1 d1 y1 m2 d2 y2 dayname &rest skip-weeks)
-  "Like `org-class', but honor `calendar-date-style'.
-The order of the first 2 times 3 arguments depends on the variable
-`calendar-date-style' or, if that is not defined, on `european-calendar-style'.
-So for American calendars, give this as MONTH DAY YEAR, for European as
-DAY MONTH YEAR, and for ISO as YEAR MONTH DAY.
-DAYNAME is a number between 0 (Sunday) and 6 (Saturday).  SKIP-WEEKS
-is any number of ISO weeks in the block period for which the item should
-be skipped.
-
-This function is here only for backward compatibility and it is deprecated,
-please use `org-class' instead."
-  (let* ((date1 (org-order-calendar-date-args m1 d1 y1))
-        (date2 (org-order-calendar-date-args m2 d2 y2)))
-    (org-class
-     (nth 2 date1) (car date1) (nth 1 date1)
-     (nth 2 date2) (car date2) (nth 1 date2)
-     dayname skip-weeks)))
-(make-obsolete 'org-diary-class 'org-class "")
-
 (defalias 'org-get-closed 'org-agenda-get-progress)
 (defun org-agenda-get-progress ()
   "Return the logged TODO entries for agenda display."
@@ -5794,7 +5849,7 @@ please use `org-class' instead."
                            (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
                    1 11))))
         (org-agenda-search-headline-for-time nil)
-        marker hdmarker priority category category-pos level tags closedp
+        marker hdmarker priority category level tags closedp
         statep clockp state ee txt extra timestr rest clocked inherited-tags)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
@@ -5806,7 +5861,6 @@ please use `org-class' instead."
              clockp (not (or closedp statep))
              state (and statep (match-string 2))
              category (org-get-category (match-beginning 0))
-             category-pos (get-text-property (match-beginning 0) 
'org-category-position)
              timestr (buffer-substring (match-beginning 0) (point-at-eol)))
        (when (string-match "\\]" timestr)
          ;; substring should only run to end of time stamp
@@ -5858,9 +5912,7 @@ please use `org-class' instead."
          (setq priority 100000)
          (org-add-props txt props
            'org-marker marker 'org-hd-marker hdmarker 'face 'org-agenda-done
-           'priority priority 'org-category category
-           'org-category-position category-pos
-           'level level
+           'priority priority 'level level
            'type "closed" 'date date
            'undone-face 'org-warning 'done-face 'org-agenda-done)
          (push txt ee))
@@ -5876,7 +5928,7 @@ See also the user option 
`org-agenda-clock-consistency-checks'."
         (re (concat "^[ \t]*"
                     org-clock-string
                     "[ \t]+"
-                    "\\(\\[.*?\\]\\)" ; group 1 is first stamp
+                    "\\(\\[.*?\\]\\)"  ; group 1 is first stamp
                     "\\(-\\{1,3\\}\\(\\[.*?\\]\\)\\)?")) ; group 3 is second
         (tlstart 0.)
         (tlend 0.)
@@ -5913,9 +5965,9 @@ See also the user option 
`org-agenda-clock-consistency-checks'."
            (setq ts (match-string 1)
                  te (match-string 3)
                  ts (float-time
-                     (apply 'encode-time (org-parse-time-string ts)))
+                     (apply #'encode-time (org-parse-time-string ts)))
                  te (float-time
-                     (apply 'encode-time (org-parse-time-string te)))
+                     (apply #'encode-time (org-parse-time-string te)))
                  dt (- te ts))))
        (cond
         ((> dt (* 60 maxtime))
@@ -6001,312 +6053,348 @@ specification like [h]h:mm."
         (regexp (if with-hour
                     org-deadline-time-hour-regexp
                   org-deadline-time-regexp))
-        (todayp (org-agenda-todayp date)) ; DATE bound by calendar
-        (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
-        (dl0 (car org-agenda-deadline-leaders))
-        (dl1 (nth 1 org-agenda-deadline-leaders))
-        (dl2 (or (nth 2 org-agenda-deadline-leaders) dl1))
-        d2 diff dfrac wdays pos pos1 category category-pos level
-        tags suppress-prewarning ee txt head face s todo-state
-        show-all upcomingp donep timestr warntime inherited-tags ts-date)
+        (today (org-today))
+        (today? (org-agenda-today-p date)) ; DATE bound by calendar.
+        (current (calendar-absolute-from-gregorian date))
+        deadline-items)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
+       (unless (save-match-data (org-at-planning-p)) (throw :skip nil))
        (org-agenda-skip)
-       (setq s (match-string 1)
-             txt nil
-             pos (1- (match-beginning 1))
-             todo-state (save-match-data (org-get-todo-state))
-             show-all (or (eq org-agenda-repeating-timestamp-show-all t)
-                          (member todo-state
-                                  org-agenda-repeating-timestamp-show-all))
-             d2 (org-time-string-to-absolute
-                 s d1 'past show-all (current-buffer) pos)
-             diff (- d2 d1))
-       (setq suppress-prewarning
-             (let ((ds (and org-agenda-skip-deadline-prewarning-if-scheduled
-                            (let ((item (buffer-substring (point-at-bol)
-                                                          (point-at-eol))))
-                              (save-match-data
-                                (and (string-match
-                                      org-scheduled-time-regexp item)
-                                     (match-string 1 item)))))))
-               (cond
-                ((not ds) nil)
-                ;; The current item has a scheduled date (in ds), so
-                ;; evaluate its prewarning lead time.
-                ((integerp org-agenda-skip-deadline-prewarning-if-scheduled)
-                 ;; Use global prewarning-restart lead time.
-                 org-agenda-skip-deadline-prewarning-if-scheduled)
-                ((eq org-agenda-skip-deadline-prewarning-if-scheduled
-                     'pre-scheduled)
-                 ;; Set prewarning to no earlier than scheduled.
-                 (min (- d2 (org-time-string-to-absolute
-                             ds d1 'past show-all (current-buffer) pos))
-                      org-deadline-warning-days))
-                ;; Set prewarning to deadline.
-                (t 0))))
-       (setq wdays (if suppress-prewarning
-                       (let ((org-deadline-warning-days suppress-prewarning))
-                         (org-get-wdays s))
-                     (org-get-wdays s))
-             dfrac (- 1 (/ (* 1.0 diff) (max wdays 1)))
-             upcomingp (and todayp (> diff 0)))
-       ;; When to show a deadline in the calendar:
-       ;; If the expiration is within wdays warning time.
-       ;; Past-due deadlines are only shown on the current date
-       (if (and (or (and (<= diff wdays)
-                         (and todayp (not org-agenda-only-exact-dates)))
-                    (= diff 0)))
-           (save-excursion
-             ;; (setq todo-state (org-get-todo-state))
-             (setq donep (member todo-state org-done-keywords))
-             (if (and donep
-                      (or org-agenda-skip-deadline-if-done
-                          (not (= diff 0))))
-                 (setq txt nil)
-               (setq category (org-get-category)
-                     warntime (get-text-property (point) 'org-appt-warntime)
-                     category-pos (get-text-property (point) 
'org-category-position))
-               (if (not (re-search-backward "^\\*+[ \t]+" nil t))
-                   (throw :skip nil)
-                 (goto-char (match-end 0))
-                 (setq pos1 (match-beginning 0))
-                 (setq level (make-string (org-reduced-level 
(org-outline-level)) ? ))
-                 (setq inherited-tags
-                       (or (eq org-agenda-show-inherited-tags 'always)
-                           (and (listp org-agenda-show-inherited-tags)
-                                (memq 'agenda org-agenda-show-inherited-tags))
-                           (and (eq org-agenda-show-inherited-tags t)
-                                (or (eq org-agenda-use-tag-inheritance t)
-                                    (memq 'agenda 
org-agenda-use-tag-inheritance))))
-                       tags (org-get-tags-at pos1 (not inherited-tags)))
-                 (setq head (buffer-substring
-                             (point)
-                             (progn (skip-chars-forward "^\r\n")
-                                    (point))))
-                 (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
-                     (setq timestr
-                           (concat (substring s (match-beginning 1)) " "))
-                   (setq timestr 'time))
-                 (setq txt (org-agenda-format-item
-                            (cond ((= diff 0) dl0)
-                                  ((> diff 0)
-                                   (if (functionp dl1)
-                                       (funcall dl1 diff date)
-                                     (format dl1 diff)))
-                                  (t
-                                   (if (functionp dl2)
-                                       (funcall dl2 diff date)
-                                     (format dl2 (if (string= dl2 dl1)
-                                                     diff (abs diff))))))
-                            head level category tags
-                            (if (not (= diff 0)) nil timestr)))))
-             (when txt
-               (setq face (org-agenda-deadline-face dfrac))
-               (org-add-props txt props
-                 'org-marker (org-agenda-new-marker pos)
-                 'warntime warntime
-                 'level level
-                 'ts-date d2
-                 'org-hd-marker (org-agenda-new-marker pos1)
-                 'priority (+ (- diff)
-                              (org-get-priority txt))
-                 'org-category category
-                 'org-category-position category-pos
-                 'todo-state todo-state
-                 'type (if upcomingp "upcoming-deadline" "deadline")
-                 'date (if upcomingp date d2)
-                 'face (if donep 'org-agenda-done face)
-                 'undone-face face 'done-face 'org-agenda-done)
-               (push txt ee))))))
-    (nreverse ee)))
+       (let* ((s (match-string 1))
+              (pos (1- (match-beginning 1)))
+              (todo-state (save-match-data (org-get-todo-state)))
+              (done? (member todo-state org-done-keywords))
+              (show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                            (member todo-state
+                                    org-agenda-repeating-timestamp-show-all)))
+              (sexp? (string-prefix-p "%%" s))
+              ;; DEADLINE is the bare deadline date, i.e., without
+              ;; any repeater, or the last repeat if SHOW-ALL is
+              ;; non-nil.  REPEAT is closest repeat after CURRENT, if
+              ;; all repeated time stamps are to be shown, or after
+              ;; TODAY otherwise.  REPEAT only applies to future
+              ;; dates.
+              (deadline (cond
+                         (sexp? (org-agenda--timestamp-to-absolute s current))
+                         (show-all (org-agenda--timestamp-to-absolute s))
+                         (t (org-agenda--timestamp-to-absolute
+                             s today 'past (current-buffer) pos))))
+              (repeat (cond (sexp? deadline)
+                            ((< current today) deadline)
+                            (t
+                             (org-agenda--timestamp-to-absolute
+                              s (if show-all current today) 'future
+                              (current-buffer) pos))))
+              (diff (- deadline current))
+              (suppress-prewarning
+               (let ((scheduled
+                      (and org-agenda-skip-deadline-prewarning-if-scheduled
+                           (org-entry-get nil "SCHEDULED"))))
+                 (cond
+                  ((not scheduled) nil)
+                  ;; The current item has a scheduled date, so
+                  ;; evaluate its prewarning lead time.
+                  ((integerp org-agenda-skip-deadline-prewarning-if-scheduled)
+                   ;; Use global prewarning-restart lead time.
+                   org-agenda-skip-deadline-prewarning-if-scheduled)
+                  ((eq org-agenda-skip-deadline-prewarning-if-scheduled
+                       'pre-scheduled)
+                   ;; Set pre-warning to no earlier than SCHEDULED.
+                   (min (- deadline
+                           (org-agenda--timestamp-to-absolute scheduled))
+                        org-deadline-warning-days))
+                  ;; Set pre-warning to deadline.
+                  (t 0))))
+              (wdays (if suppress-prewarning
+                         (let ((org-deadline-warning-days suppress-prewarning))
+                           (org-get-wdays s))
+                       (org-get-wdays s))))
+         ;; When to show a deadline in the calendar: if the
+         ;; expiration is within WDAYS warning time.  Past-due
+         ;; deadlines are only shown on today agenda.
+         (when (cond ((= current deadline) nil)
+                     ((< deadline today)
+                      (and (not today?)
+                           (or (< current today) (/= repeat current))))
+                     ((> deadline current)
+                      (or (not today?) (> diff wdays)))
+                     (t (/= repeat current)))
+           (throw :skip nil))
+         ;; Possibly skip done tasks.
+         (when (and done?
+                    (or org-agenda-skip-deadline-if-done
+                        (/= deadline current)))
+           (throw :skip nil))
+         (save-excursion
+           (re-search-backward "^\\*+[ \t]+" nil t)
+           (goto-char (match-end 0))
+           (let* ((category (org-get-category))
+                  (level
+                   (make-string (org-reduced-level (org-outline-level)) ?\s))
+                  (head (buffer-substring (point) (line-end-position)))
+                  (inherited-tags
+                   (or (eq org-agenda-show-inherited-tags 'always)
+                       (and (listp org-agenda-show-inherited-tags)
+                            (memq 'agenda org-agenda-show-inherited-tags))
+                       (and (eq org-agenda-show-inherited-tags t)
+                            (or (eq org-agenda-use-tag-inheritance t)
+                                (memq 'agenda
+                                      org-agenda-use-tag-inheritance)))))
+                  (tags (org-get-tags-at nil (not inherited-tags)))
+                  (time
+                   (cond
+                    ;; No time of day designation if it is only
+                    ;; a reminder.
+                    ((and (/= current deadline) (/= current repeat)) nil)
+                    ((string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
+                     (concat (substring s (match-beginning 1)) " "))
+                    (t 'time)))
+                  (item
+                   (org-agenda-format-item
+                    ;; Insert appropriate suffixes before deadlines.
+                    (pcase-let ((`(,now ,future ,past)
+                                 org-agenda-deadline-leaders))
+                      (cond
+                       ;; Future (i.e., repeated) deadlines are
+                       ;; displayed as new headlines.
+                       ((> current today) now)
+                       ;; When SHOW-ALL is nil, prefer repeated
+                       ;; deadlines over reminders of past deadlines.
+                       ((and (not show-all) (= repeat today)) now)
+                       ((= deadline current) now)
+                       ((< deadline current) (format past (- diff)))
+                       (t (format future diff))))
+                    head level category tags
+                    (and (or (= repeat current) (= deadline current))
+                         time)))
+                  (face (org-agenda-deadline-face
+                         (- 1 (/ (float (- deadline current)) (max wdays 1)))))
+                  (upcoming? (and today? (> deadline today)))
+                  (warntime (get-text-property (point) 'org-appt-warntime)))
+             (org-add-props item props
+               'org-marker (org-agenda-new-marker pos)
+               'org-hd-marker (org-agenda-new-marker (line-beginning-position))
+               'warntime warntime
+               'level level
+               'ts-date deadline
+               'priority
+               ;; Adjust priority to today reminders about deadlines.
+               ;; Overdue deadlines get the highest priority
+               ;; increase, then imminent deadlines and eventually
+               ;; more distant deadlines.
+               (let ((adjust (cond ((not today?) 0)
+                                   ((and (not show-all) (= repeat current)) 0)
+                                   (t (- diff)))))
+                 (+ adjust (org-get-priority item)))
+               'todo-state todo-state
+               'type (if upcoming? "upcoming-deadline" "deadline")
+               'date (if upcoming? date deadline)
+               'face (if done? 'org-agenda-done face)
+               'undone-face face
+               'done-face 'org-agenda-done)
+             (push item deadline-items))))))
+    (nreverse deadline-items)))
 
 (defun org-agenda-deadline-face (fraction)
   "Return the face to displaying a deadline item.
 FRACTION is what fraction of the head-warning time has passed."
-  (let ((faces org-agenda-deadline-faces) f)
-    (catch 'exit
-      (while (setq f (pop faces))
-       (if (>= fraction (car f)) (throw 'exit (cdr f)))))))
+  (assoc-default fraction org-agenda-deadline-faces #'<=))
 
-(defun org-agenda-get-scheduled (&optional deadline-results with-hour)
+(defun org-agenda-get-scheduled (&optional deadlines with-hour)
   "Return the scheduled information for agenda display.
-When WITH-HOUR is non-nil, only return scheduled items with
-an hour specification like [h]h:mm."
+Optional argument DEADLINES is a list of deadline items to be
+displayed in agenda view.  When WITH-HOUR is non-nil, only return
+scheduled items with an hour specification like [h]h:mm."
   (let* ((props (list 'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
                      'org-complex-heading-regexp org-complex-heading-regexp
                      'done-face 'org-agenda-done
                      'mouse-face 'highlight
                      'help-echo
-                     (format "mouse-2 or RET jump to org file %s"
+                     (format "mouse-2 or RET jump to Org file %s"
                              (abbreviate-file-name buffer-file-name))))
         (regexp (if with-hour
                     org-scheduled-time-hour-regexp
                   org-scheduled-time-regexp))
-        (todayp (org-agenda-todayp date)) ; DATE bound by calendar
-        (d1 (calendar-absolute-from-gregorian date))  ; DATE bound by calendar
-        mm
-        (deadline-position-alist
-         (mapcar (lambda (a) (and (setq mm (get-text-property
-                                            0 'org-hd-marker a))
-                                  (cons (marker-position mm) a)))
-                 deadline-results))
-        d2 diff pos pos1 category category-pos level tags donep
-        ee txt head pastschedp todo-state face timestr s habitp show-all
-        did-habit-check-p warntime inherited-tags ts-date suppress-delay
-        ddays)
+        (today (org-today))
+        (todayp (org-agenda-today-p date)) ; DATE bound by calendar.
+        (current (calendar-absolute-from-gregorian date))
+        (deadline-pos
+         (mapcar (lambda (d)
+                   (let ((m (get-text-property 0 'org-hd-marker d)))
+                     (and m (marker-position m))))
+                 deadlines))
+        scheduled-items)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
+       (unless (save-match-data (org-at-planning-p)) (throw :skip nil))
        (org-agenda-skip)
-       (setq s (match-string 1)
-             txt nil
-             pos (1- (match-beginning 1))
-             todo-state (save-match-data (org-get-todo-state))
-             show-all (or (eq org-agenda-repeating-timestamp-show-all t)
-                          (member todo-state
-                                  org-agenda-repeating-timestamp-show-all))
-             d2 (org-time-string-to-absolute
-                 s d1 'past show-all (current-buffer) pos)
-             diff (- d2 d1)
-             warntime (get-text-property (point) 'org-appt-warntime))
-       (setq pastschedp (and todayp (< diff 0)))
-       (setq did-habit-check-p nil)
-       (setq suppress-delay
-             (let ((ds (and org-agenda-skip-scheduled-delay-if-deadline
-                            (let ((item (buffer-substring (point-at-bol) 
(point-at-eol))))
-                              (save-match-data
-                                (and (string-match
-                                      org-deadline-time-regexp item)
-                                     (match-string 1 item)))))))
+       (let* ((s (match-string 1))
+              (pos (1- (match-beginning 1)))
+              (todo-state (save-match-data (org-get-todo-state)))
+              (donep (member todo-state org-done-keywords))
+              (show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                            (member todo-state
+                                    org-agenda-repeating-timestamp-show-all)))
+              (sexp? (string-prefix-p "%%" s))
+              ;; SCHEDULE is the bare scheduled date, i.e., without
+              ;; any repeater if non-nil, or last repeat if SHOW-ALL
+              ;; is nil.  REPEAT is the closest repeat after CURRENT,
+              ;; if all repeated time stamps are to be shown, or
+              ;; after TODAY otherwise.  REPEAT only applies to
+              ;; future dates.
+              (schedule (cond
+                         (sexp? (org-agenda--timestamp-to-absolute s current))
+                         (show-all (org-agenda--timestamp-to-absolute s))
+                         (t (org-agenda--timestamp-to-absolute
+                             s today 'past (current-buffer) pos))))
+              (repeat (cond
+                       (sexp? schedule)
+                       ((< current today) schedule)
+                       (t
+                        (org-agenda--timestamp-to-absolute
+                         s (if show-all current today) 'future
+                         (current-buffer) pos))))
+              (diff (- current schedule))
+              (warntime (get-text-property (point) 'org-appt-warntime))
+              (pastschedp (< schedule today))
+              (habitp (and (fboundp 'org-is-habit-p) (org-is-habit-p)))
+              (suppress-delay
+               (let ((deadline (and org-agenda-skip-scheduled-delay-if-deadline
+                                    (org-entry-get nil "DEADLINE"))))
+                 (cond
+                  ((not deadline) nil)
+                  ;; The current item has a deadline date, so
+                  ;; evaluate its delay time.
+                  ((integerp org-agenda-skip-scheduled-delay-if-deadline)
+                   ;; Use global delay time.
+                   (- org-agenda-skip-scheduled-delay-if-deadline))
+                  ((eq org-agenda-skip-scheduled-delay-if-deadline
+                       'post-deadline)
+                   ;; Set delay to no later than DEADLINE.
+                   (min (- schedule
+                           (org-agenda--timestamp-to-absolute deadline))
+                        org-scheduled-delay-days))
+                  (t 0))))
+              (ddays
                (cond
-                ((not ds) nil)
-                ;; The current item has a deadline date (in ds), so
-                ;; evaluate its delay time.
-                ((integerp org-agenda-skip-scheduled-delay-if-deadline)
-                 ;; Use global delay time.
-                 (- org-agenda-skip-scheduled-delay-if-deadline))
-                ((eq org-agenda-skip-scheduled-delay-if-deadline
-                     'post-deadline)
-                 ;; Set delay to no later than deadline.
-                 (min (- d2 (org-time-string-to-absolute
-                             ds d1 'past show-all (current-buffer) pos))
-                      org-scheduled-delay-days))
-                (t 0))))
-       (setq ddays (if suppress-delay
-                       (let ((org-scheduled-delay-days suppress-delay))
-                         (org-get-wdays s t t))
-                     (org-get-wdays s t)))
-       ;; Use a delay of 0 when there is a repeater and the delay is
-       ;; of the form --3d
-       (when (and (save-match-data (string-match "--[0-9]+[hdwmy]" s))
-                  (< (org-time-string-to-absolute s)
-                     (org-time-string-to-absolute
-                      s d2 'past nil (current-buffer) pos)))
-         (setq ddays 0))
-       ;; When to show a scheduled item in the calendar:
-       ;; If it is on or past the date.
-       (when (or (and (> ddays 0) (= diff (- ddays)))
-                 (and (zerop ddays) (= diff 0))
-                 (and (< (+ diff ddays) 0)
-                      (< (abs diff) org-scheduled-past-days)
-                      (and todayp (not org-agenda-only-exact-dates)))
-                 ;; org-is-habit-p uses org-entry-get, which is expansive
-                 ;; so we go extra mile to only call it once
-                 (and todayp
-                      (boundp 'org-habit-show-all-today)
-                      org-habit-show-all-today
-                      (setq did-habit-check-p t)
-                      (setq habitp (and (functionp 'org-is-habit-p)
-                                        (org-is-habit-p)))))
-         (save-excursion
-           (setq donep (member todo-state org-done-keywords))
-           (if (and donep
+                ;; Nullify delay when a repeater triggered already
+                ;; and the delay is of the form --Xd.
+                ((and (string-match-p "--[0-9]+[hdwmy]" s)
+                      (> current schedule))
+                 0)
+                (suppress-delay
+                 (let ((org-scheduled-delay-days suppress-delay))
+                   (org-get-wdays s t t)))
+                (t (org-get-wdays s t)))))
+         ;; Display scheduled items at base date (SCHEDULE), today if
+         ;; scheduled before the current date, and at any repeat past
+         ;; today.  However, skip delayed items and items that have
+         ;; been displayed for more than `org-scheduled-past-days'.
+         (unless (and todayp
+                      habitp
+                      (bound-and-true-p org-habit-show-all-today))
+           (when (or (and (> ddays 0) (< diff ddays))
+                     (> diff org-scheduled-past-days)
+                     (> schedule current)
+                     (and (< schedule current)
+                          (not todayp)
+                          (/= repeat current)))
+             (throw :skip nil)))
+         ;; Possibly skip done tasks.
+         (when (and donep
                     (or org-agenda-skip-scheduled-if-done
-                        (not (= diff 0))
-                        (and (functionp 'org-is-habit-p)
-                             (org-is-habit-p))))
-               (setq txt nil)
-             (setq habitp (if did-habit-check-p habitp
-                            (and (functionp 'org-is-habit-p)
-                                 (org-is-habit-p))))
-             (setq category (org-get-category)
-                   category-pos (get-text-property (point) 
'org-category-position))
-             (if (and (eq org-agenda-skip-scheduled-if-deadline-is-shown
-                          'repeated-after-deadline)
-                      (org-get-deadline-time (point))
-                      (<= 0 (- d2 (time-to-days (org-get-deadline-time 
(point))))))
-                 (throw :skip nil))
-             (if (not (re-search-backward "^\\*+[ \t]+" nil t))
-                 (throw :skip nil)
-               (goto-char (match-end 0))
-               (setq pos1 (match-beginning 0))
-               (if habitp
-                   (if (or (not org-habit-show-habits)
-                           (and (not todayp)
-                                (boundp 'org-habit-show-habits-only-for-today)
-                                org-habit-show-habits-only-for-today))
-                       (throw :skip nil))
-                 (if (and
-                      (or (eq t org-agenda-skip-scheduled-if-deadline-is-shown)
-                          (and (eq 
org-agenda-skip-scheduled-if-deadline-is-shown 'not-today)
-                               pastschedp))
-                      (setq mm (assoc pos1 deadline-position-alist)))
-                     (throw :skip nil)))
-               (setq inherited-tags
-                     (or (eq org-agenda-show-inherited-tags 'always)
-                         (and (listp org-agenda-show-inherited-tags)
-                              (memq 'agenda org-agenda-show-inherited-tags))
-                         (and (eq org-agenda-show-inherited-tags t)
-                              (or (eq org-agenda-use-tag-inheritance t)
-                                  (memq 'agenda 
org-agenda-use-tag-inheritance))))
-
-                     tags (org-get-tags-at nil (not inherited-tags)))
-               (setq level (make-string (org-reduced-level 
(org-outline-level)) ? ))
-               (setq head (buffer-substring
-                           (point)
-                           (progn (skip-chars-forward "^\r\n") (point))))
-               (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
-                   (setq timestr
-                         (concat (substring s (match-beginning 1)) " "))
-                 (setq timestr 'time))
-               (setq txt (org-agenda-format-item
-                          (if (= diff 0)
-                              (car org-agenda-scheduled-leaders)
-                            (format (nth 1 org-agenda-scheduled-leaders)
-                                    (- 1 diff)))
-                          head level category tags
-                          (if (not (= diff 0)) nil timestr)
-                          nil habitp))))
-           (when txt
-             (setq face
+                        (/= schedule current)))
+           (throw :skip nil))
+         ;; Skip entry if it already appears as a deadline, per
+         ;; `org-agenda-skip-scheduled-if-deadline-is-shown'.  This
+         ;; doesn't apply to habits.
+         (when (pcase org-agenda-skip-scheduled-if-deadline-is-shown
+                 ((guard
+                   (or (not (memq (line-beginning-position 0) deadline-pos))
+                       habitp))
+                  nil)
+                 (`repeated-after-deadline
+                  (>= repeat (time-to-days (org-get-deadline-time (point)))))
+                 (`not-today pastschedp)
+                 (`t t)
+                 (_ nil))
+           (throw :skip nil))
+         ;; Skip habits if `org-habit-show-habits' is nil, or if we
+         ;; only show them for today.  Also skip done habits.
+         (when (and habitp
+                    (or donep
+                        (not (bound-and-true-p org-habit-show-habits))
+                        (and (not todayp)
+                             (bound-and-true-p
+                              org-habit-show-habits-only-for-today))))
+           (throw :skip nil))
+         (save-excursion
+           (re-search-backward "^\\*+[ \t]+" nil t)
+           (goto-char (match-end 0))
+           (let* ((category (org-get-category))
+                  (inherited-tags
+                   (or (eq org-agenda-show-inherited-tags 'always)
+                       (and (listp org-agenda-show-inherited-tags)
+                            (memq 'agenda org-agenda-show-inherited-tags))
+                       (and (eq org-agenda-show-inherited-tags t)
+                            (or (eq org-agenda-use-tag-inheritance t)
+                                (memq 'agenda
+                                      org-agenda-use-tag-inheritance)))))
+                  (tags (org-get-tags-at nil (not inherited-tags)))
+                  (level
+                   (make-string (org-reduced-level (org-outline-level)) ?\s))
+                  (head (buffer-substring (point) (line-end-position)))
+                  (time
                    (cond
-                    ((and (not habitp) pastschedp)
-                     'org-scheduled-previously)
-                    (todayp 'org-scheduled-today)
-                    (t 'org-scheduled))
-                   habitp (and habitp (org-habit-parse-todo)))
-             (org-add-props txt props
+                    ;; No time of day designation if it is only
+                    ;; a reminder.
+                    ((and (/= current schedule) (/= current repeat)) nil)
+                    ((string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
+                     (concat (substring s (match-beginning 1)) " "))
+                    (t 'time)))
+                  (item
+                   (org-agenda-format-item
+                    (pcase-let ((`(,first ,next) org-agenda-scheduled-leaders))
+                      (cond
+                       ;; If CURRENT is in the future, don't use past
+                       ;; scheduled prefix.
+                       ((> current today) first)
+                       ;; SHOW-ALL focuses on future repeats.  If one
+                       ;; such repeat happens today, ignore late
+                       ;; schedule reminder.  However, still report
+                       ;; such reminders when repeat happens later.
+                       ((and (not show-all) (= repeat today)) first)
+                       ;; Initial report.
+                       ((= schedule current) first)
+                       ;; Subsequent reminders.  Count from base
+                       ;; schedule.
+                       (t (format next diff))))
+                    head level category tags time nil habitp))
+                  (face (cond ((and (not habitp) pastschedp)
+                               'org-scheduled-previously)
+                              (todayp 'org-scheduled-today)
+                              (t 'org-scheduled)))
+                  (habitp (and habitp (org-habit-parse-todo))))
+             (org-add-props item props
                'undone-face face
                'face (if donep 'org-agenda-done face)
                'org-marker (org-agenda-new-marker pos)
-               'org-hd-marker (org-agenda-new-marker pos1)
+               'org-hd-marker (org-agenda-new-marker (line-beginning-position))
                'type (if pastschedp "past-scheduled" "scheduled")
-               'date (if pastschedp d2 date)
-               'ts-date d2
+               'date (if pastschedp schedule date)
+               'ts-date schedule
                'warntime warntime
                'level level
-               'priority (if habitp
-                             (org-habit-get-priority habitp)
-                           (+ 94 (- 5 diff) (org-get-priority txt)))
-               'org-category category
-               'category-position category-pos
+               'priority (if habitp (org-habit-get-priority habitp)
+                           (+ 99 diff (org-get-priority item)))
                'org-habit-p habitp
                'todo-state todo-state)
-             (push txt ee))))))
-    (nreverse ee)))
+             (push item scheduled-items))))))
+    (nreverse scheduled-items)))
 
 (defun org-agenda-get-blocks ()
   "Return the date-range information for agenda display."
@@ -6320,7 +6408,7 @@ an hour specification like [h]h:mm."
                              (abbreviate-file-name buffer-file-name))))
         (regexp org-tr-regexp)
         (d0 (calendar-absolute-from-gregorian date))
-        marker hdmarker ee txt d1 d2 s1 s2 category category-pos
+        marker hdmarker ee txt d1 d2 s1 s2 category
         level todo-state tags pos head donep inherited-tags)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
@@ -6341,9 +6429,8 @@ an hour specification like [h]h:mm."
                (setq donep (member todo-state org-done-keywords))
                (if (and donep org-agenda-skip-timestamp-if-done)
                    (throw :skip t))
-               (setq marker (org-agenda-new-marker (point)))
-               (setq category (org-get-category)
-                     category-pos (get-text-property (point) 
'org-category-position))
+               (setq marker (org-agenda-new-marker (point))
+                     category (org-get-category))
                (if (not (re-search-backward org-outline-regexp-bol nil t))
                    (throw :skip nil)
                  (goto-char (match-beginning 0))
@@ -6358,7 +6445,7 @@ an hour specification like [h]h:mm."
 
                        tags (org-get-tags-at nil (not inherited-tags)))
                  (setq level (make-string (org-reduced-level 
(org-outline-level)) ? ))
-                 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
+                 (looking-at "\\*+[ \t]+\\(.*\\)")
                  (setq head (match-string 1))
                  (let ((remove-re
                         (if org-agenda-remove-timeranges-from-blocks
@@ -6385,8 +6472,7 @@ an hour specification like [h]h:mm."
                  'type "block" 'date date
                  'level level
                  'todo-state todo-state
-                 'priority (org-get-priority txt) 'org-category category
-                 'org-category-position category-pos)
+                 'priority (org-get-priority txt))
                (push txt ee))))
        (goto-char pos)))
     ;; Sort the entries by expiration date.
@@ -6413,11 +6499,11 @@ The flag is set if the currently compiled format 
contains a `%b'.")
 
 (defun org-agenda-get-category-icon (category)
   "Return an image for CATEGORY according to `org-agenda-category-icon-alist'."
-  (dolist (entry org-agenda-category-icon-alist)
-    (when (org-string-match-p (car entry) category)
+  (cl-dolist (entry org-agenda-category-icon-alist)
+    (when (string-match-p (car entry) category)
       (if (listp (cadr entry))
-         (return (cadr entry))
-       (return (apply 'create-image (cdr entry)))))))
+         (cl-return (cadr entry))
+       (cl-return (apply #'create-image (cdr entry)))))))
 
 (defun org-agenda-format-item (extra txt &optional level category tags dotime
                                     remove-re habitp)
@@ -6444,8 +6530,8 @@ Any match of REMOVE-RE will be removed from TXT."
   ;; buffer
   (let* ((bindings (car org-prefix-format-compiled))
         (formatter (cadr org-prefix-format-compiled)))
-    (loop for (var value) in bindings
-         do (set var value))
+    (cl-loop for (var value) in bindings
+            do (set var value))
     (save-match-data
       ;; Diary entries sometimes have extra whitespace at the beginning
       (setq txt (org-trim txt))
@@ -6457,9 +6543,6 @@ Any match of REMOVE-RE will be removed from TXT."
                 org-agenda-hide-tags-regexp))
 
       (let* ((category (or category
-                          (if (stringp org-category)
-                              org-category
-                            (and org-category (symbol-name org-category)))
                           (if buffer-file-name
                               (file-name-sans-extension
                                (file-name-nondirectory buffer-file-name))
@@ -6468,15 +6551,17 @@ Any match of REMOVE-RE will be removed from TXT."
             (category-icon (if category-icon
                                (propertize " " 'display category-icon)
                              ""))
+            (effort (and (not (string= txt ""))
+                         (get-text-property 1 'effort txt)))
             ;; time, tag, effort are needed for the eval of the prefix format
             (tag (if tags (nth (1- (length tags)) tags) ""))
-            time effort neffort
+            time
             (ts (if dotime (concat
                             (if (stringp dotime) dotime "")
                             (and org-agenda-search-headline-for-time txt))))
             (time-of-day (and dotime (org-get-time-of-day ts)))
             stamp plain s0 s1 s2 rtn srp l
-            duration thecategory breadcrumbs)
+            duration breadcrumbs)
        (and (derived-mode-p 'org-mode) buffer-file-name
             (add-to-list 'org-agenda-contributing-files buffer-file-name))
        (when (and dotime time-of-day)
@@ -6516,8 +6601,7 @@ Any match of REMOVE-RE will be removed from TXT."
            (setq duration (- (org-hh:mm-string-to-minutes s2)
                              (org-hh:mm-string-to-minutes s1)))))
 
-       (when (string-match (org-re "\\([ 
\t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$")
-                           txt)
+       (when (string-match "\\([ \t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ 
\t]*$" txt)
          ;; Tags are in the string
          (if (or (eq org-agenda-remove-tags t)
                  (and org-agenda-remove-tags
@@ -6527,16 +6611,6 @@ Any match of REMOVE-RE will be removed from TXT."
                       (concat (make-string (max (- 50 (length txt)) 1) ?\ )
                               (match-string 2 txt))
                       t t txt))))
-       (when (derived-mode-p 'org-mode)
-         (setq effort (ignore-errors (get-text-property 0 'org-effort txt))))
-
-       ;; org-agenda-add-time-grid-maybe calls us with *Agenda* as
-       ;; current buffer, so move this check outside of above
-       (if effort
-           (setq neffort (org-duration-string-to-minutes effort)
-                 effort (setq effort (concat "[" effort "]")))
-         ;; prevent erroring out with %e format when there is no effort
-         (setq effort ""))
 
        (when remove-re
          (while (string-match remove-re txt)
@@ -6563,7 +6637,6 @@ Any match of REMOVE-RE will be removed from TXT."
                         (t ""))
              extra (or (and (not habitp) extra) "")
              category (if (symbolp category) (symbol-name category) category)
-             thecategory (copy-sequence category)
              level (or level ""))
        (if (string-match org-bracket-link-regexp category)
            (progn
@@ -6584,14 +6657,12 @@ Any match of REMOVE-RE will be removed from TXT."
        ;; And finally add the text properties
        (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) 
rtn)
        (org-add-props rtn nil
-         'org-category (if thecategory (downcase thecategory) category)
+         'org-category category
          'tags (mapcar 'org-downcase-keep-props tags)
          'org-highest-priority org-highest-priority
          'org-lowest-priority org-lowest-priority
          'time-of-day time-of-day
          'duration duration
-         'effort effort
-         'effort-minutes neffort
          'breadcrumbs breadcrumbs
          'txt txt
          'level level
@@ -6605,7 +6676,7 @@ Any match of REMOVE-RE will be removed from TXT."
 The modified list may contain inherited tags, and tags matched by
 `org-agenda-hide-tags-regexp' will be removed."
   (when (or add-inherited hide-re)
-    (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ 
\t]*$") txt)
+    (if (string-match "\\([ \t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$" 
txt)
        (setq txt (substring txt 0 (match-beginning 0))))
     (setq tags
          (delq nil
@@ -6710,12 +6781,12 @@ and stored in the variable 
`org-prefix-format-compiled'."
            c (or (match-string 3 s) "")
            opt (match-beginning 1)
            start (1+ (match-beginning 0)))
-      (if (equal var 'time) (setq org-prefix-has-time t))
-      (if (equal var 'tag)  (setq org-prefix-has-tag  t))
-      (if (equal var 'effort) (setq org-prefix-has-effort t))
-      (if (equal var 'breadcrumbs) (setq org-prefix-has-breadcrumbs t))
+      (if (eq var 'time) (setq org-prefix-has-time t))
+      (if (eq var 'tag)  (setq org-prefix-has-tag  t))
+      (if (eq var 'effort) (setq org-prefix-has-effort t))
+      (if (eq var 'breadcrumbs) (setq org-prefix-has-breadcrumbs t))
       (setq f (concat "%" (match-string 2 s) "s"))
-      (when (equal var 'category)
+      (when (eq var 'category)
        (setq org-prefix-category-length
              (floor (abs (string-to-number (match-string 2 s)))))
        (setq org-prefix-category-max-length
@@ -6727,10 +6798,13 @@ and stored in the variable 
`org-prefix-format-compiled'."
          (setq varform `(format ,f (org-eval ,(read (match-string 4 s)))))
        (if opt
            (setq varform
-                 `(if (equal "" ,var)
+                 `(if (or (equal "" ,var) (equal nil ,var))
                       ""
-                    (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
-         (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c 
(get-text-property 0 'extra-space ,var)))))))
+                    (format ,f (concat ,var ,c))))
+         (setq varform
+               `(format ,f (if (or (equal ,var "")
+                                   (equal ,var nil)) ""
+                             (concat ,var ,c (get-text-property 0 'extra-space 
,var)))))))
       (setq s (replace-match "%s" t nil s))
       (push varform vars))
     (setq vars (nreverse vars))
@@ -6817,7 +6891,7 @@ The optional argument TYPE tells the agenda type."
                        (t org-agenda-max-tags)))
        (max-entries (cond ((listp org-agenda-max-entries)
                            (cdr (assoc type org-agenda-max-entries)))
-                          (t org-agenda-max-entries))) l)
+                          (t org-agenda-max-entries))))
     (when org-agenda-before-sorting-filter-function
       (setq list
            (delq nil
@@ -6827,7 +6901,9 @@ The optional argument TYPE tells the agenda type."
          list (mapcar 'identity (sort list 'org-entries-lessp)))
     (when max-effort
       (setq list (org-agenda-limit-entries
-                 list 'effort-minutes max-effort 'identity)))
+                 list 'effort-minutes max-effort
+                 (lambda (e) (or e (if org-sort-agenda-noeffort-is-high
+                                       32767 -1))))))
     (when max-todo
       (setq list (org-agenda-limit-entries list 'todo-state max-todo)))
     (when max-tags
@@ -6845,26 +6921,39 @@ The optional argument TYPE tells the agenda type."
          (delq nil
                (mapcar
                 (lambda (e)
-                  (let ((pval (funcall fun (get-text-property 1 prop e))))
+                  (let ((pval (funcall
+                               fun (get-text-property (1- (length e))
+                                                      prop e))))
                     (if pval (setq lim (+ lim pval)))
                     (cond ((and pval (<= lim (abs limit))) e)
                           ((and include (not pval)) e))))
                 list)))
       list)))
 
-(defun org-agenda-limit-interactively ()
+(defun org-agenda-limit-interactively (remove)
   "In agenda, interactively limit entries to various maximums."
-  (interactive)
-  (let* ((max (read-char "Number of [e]ntries [t]odos [T]ags [E]ffort? "))
-        (num (string-to-number (read-from-minibuffer "How many? "))))
-    (cond ((equal max ?e)
-          (let ((org-agenda-max-entries num)) (org-agenda-redo)))
-         ((equal max ?t)
-          (let ((org-agenda-max-todos num)) (org-agenda-redo)))
-         ((equal max ?T)
-          (let ((org-agenda-max-tags num)) (org-agenda-redo)))
-         ((equal max ?E)
-          (let ((org-agenda-max-effort num)) (org-agenda-redo)))))
+  (interactive "P")
+  (if remove
+      (progn (setq org-agenda-max-entries nil
+                  org-agenda-max-todos nil
+                  org-agenda-max-tags nil
+                  org-agenda-max-effort nil)
+            (org-agenda-redo))
+    (let* ((max (read-char "Number of [e]ntries [t]odos [T]ags [E]ffort? "))
+          (msg (cond ((= max ?E) "How many minutes? ")
+                     ((= max ?e) "How many entries? ")
+                     ((= max ?t) "How many TODO entries? ")
+                     ((= max ?T) "How many tagged entries? ")
+                     (t (user-error "Wrong input"))))
+          (num (string-to-number (read-from-minibuffer msg))))
+      (cond ((equal max ?e)
+            (let ((org-agenda-max-entries num)) (org-agenda-redo)))
+           ((equal max ?t)
+            (let ((org-agenda-max-todos num)) (org-agenda-redo)))
+           ((equal max ?T)
+            (let ((org-agenda-max-tags num)) (org-agenda-redo)))
+           ((equal max ?E)
+            (let ((org-agenda-max-effort num)) (org-agenda-redo))))))
   (org-agenda-fit-window-to-buffer))
 
 (defun org-agenda-highlight-todo (x)
@@ -6910,25 +6999,31 @@ The optional argument TYPE tells the agenda type."
                            (substring x (match-end 3)))))))
       x)))
 
-(defsubst org-cmp-priority (a b)
-  "Compare the priorities of string A and B."
-  (let ((pa (or (get-text-property 1 'priority a) 0))
-       (pb (or (get-text-property 1 'priority b) 0)))
+(defsubst org-cmp-values (a b property)
+  "Compare the numeric value of text PROPERTY for string A and B."
+  (let ((pa (or (get-text-property (1- (length a)) property a) 0))
+       (pb (or (get-text-property (1- (length b)) property b) 0)))
     (cond ((> pa pb) +1)
          ((< pa pb) -1))))
 
 (defsubst org-cmp-effort (a b)
   "Compare the effort values of string A and B."
   (let* ((def (if org-sort-agenda-noeffort-is-high 32767 -1))
-        (ea (or (get-text-property 1 'effort-minutes a) def))
-        (eb (or (get-text-property 1 'effort-minutes b) def)))
+        ;; `effort-minutes' property is not directly accessible from
+        ;; the strings, but is stored as a property in `txt'.
+        (ea (or (get-text-property
+                 0 'effort-minutes (get-text-property 0 'txt a))
+                def))
+        (eb (or (get-text-property
+                 0 'effort-minutes (get-text-property 0 'txt b))
+                def)))
     (cond ((> ea eb) +1)
          ((< ea eb) -1))))
 
 (defsubst org-cmp-category (a b)
   "Compare the string values of categories of strings A and B."
-  (let ((ca (or (get-text-property 1 'org-category a) ""))
-       (cb (or (get-text-property 1 'org-category b) "")))
+  (let ((ca (or (get-text-property (1- (length a)) 'org-category a) ""))
+       (cb (or (get-text-property (1- (length b)) 'org-category b) "")))
     (cond ((string-lessp ca cb) -1)
          ((string-lessp cb ca) +1))))
 
@@ -6959,7 +7054,8 @@ The optional argument TYPE tells the agenda type."
   (let* ((pla (text-property-any 0 (length a) 'org-heading t a))
         (plb (text-property-any 0 (length b) 'org-heading t b))
         (ta (and pla (substring a pla)))
-        (tb (and plb (substring b plb))))
+        (tb (and plb (substring b plb)))
+        (case-fold-search nil))
     (when pla
       (if (string-match (concat "\\`[ \t]*" (or (get-text-property 0 
'org-todo-regexp a) "")
                                "\\([ \t]*\\[[a-zA-Z0-9]\\]\\)? *") ta)
@@ -7038,8 +7134,11 @@ their type."
         (time-up         (and (org-em 'time-up 'time-down ss)
                               (org-cmp-time a b)))
         (time-down       (if time-up (- time-up) nil))
+        (stats-up        (and (org-em 'stats-up 'stats-down ss)
+                              (org-cmp-values a b 'org-stats)))
+        (stats-down      (if stats-up (- stats-up) nil))
         (priority-up     (and (org-em 'priority-up 'priority-down ss)
-                              (org-cmp-priority a b)))
+                              (org-cmp-values a b 'priority)))
         (priority-down   (if priority-up (- priority-up) nil))
         (effort-up       (and (org-em 'effort-up 'effort-down ss)
                               (org-cmp-effort a b)))
@@ -7080,15 +7179,16 @@ their type."
             'face 'org-agenda-restriction-lock)
 (overlay-put org-agenda-restriction-lock-overlay
             'help-echo "Agendas are currently limited to this subtree.")
-(org-detach-overlay org-agenda-restriction-lock-overlay)
+(delete-overlay org-agenda-restriction-lock-overlay)
 
 ;;;###autoload
 (defun org-agenda-set-restriction-lock (&optional type)
   "Set restriction lock for agenda, to current subtree or file.
-Restriction will be the file if TYPE is `file', or if TYPE is the
-universal prefix `(4)', or if the cursor is before the first headline
+Restriction will be the file if TYPE is `file', or if type is the
+universal prefix \\='(4), or if the cursor is before the first headline
 in the file.  Otherwise, restriction will be to the current subtree."
   (interactive "P")
+  (org-agenda-remove-restriction-lock 'noupdate)
   (and (equal type '(4)) (setq type 'file))
   (setq type (cond
              (type type)
@@ -7125,8 +7225,8 @@ in the file.  Otherwise, restriction will be to the 
current subtree."
 (defun org-agenda-remove-restriction-lock (&optional noupdate)
   "Remove the agenda restriction lock."
   (interactive "P")
-  (org-detach-overlay org-agenda-restriction-lock-overlay)
-  (org-detach-overlay org-speedbar-restriction-lock-overlay)
+  (delete-overlay org-agenda-restriction-lock-overlay)
+  (delete-overlay org-speedbar-restriction-lock-overlay)
   (setq org-agenda-overriding-restriction nil)
   (setq org-agenda-restrict nil)
   (put 'org-agenda-files 'org-restrict nil)
@@ -7138,7 +7238,9 @@ in the file.  Otherwise, restriction will be to the 
current subtree."
 
 (defun org-agenda-maybe-redo ()
   "If there is any window showing the agenda view, update it."
-  (let ((w (get-buffer-window org-agenda-buffer-name t))
+  (let ((w (get-buffer-window (or org-agenda-this-buffer-name
+                                 org-agenda-buffer-name)
+                             t))
        (w0 (selected-window)))
     (when w
       (select-window w)
@@ -7154,7 +7256,7 @@ in the file.  Otherwise, restriction will be to the 
current subtree."
 (defun org-agenda-check-type (error &rest types)
   "Check if agenda buffer is of allowed type.
 If ERROR is non-nil, throw an error, otherwise just return nil.
-Allowed types are 'agenda 'timeline 'todo 'tags 'search."
+Allowed types are `agenda' `timeline' `todo' `tags' `search'."
   (if (not org-agenda-type)
       (error "No Org agenda currently displayed")
     (if (memq org-agenda-type types)
@@ -7164,77 +7266,76 @@ Allowed types are 'agenda 'timeline 'todo 'tags 
'search."
        nil))))
 
 (defun org-agenda-Quit ()
-  "Exit the agenda and kill buffers loaded by `org-agenda'.
-Also restore the window configuration."
+  "Exit the agenda, killing the agenda buffer.
+Like `org-agenda-quit', but kill the buffer even when
+`org-agenda-sticky' is non-nil."
   (interactive)
-  (if org-agenda-columns-active
-      (org-columns-quit)
-    (let ((buf (current-buffer)))
-      (if (eq org-agenda-window-setup 'other-frame)
-         (progn
-           (org-agenda-reset-markers)
-           (kill-buffer buf)
-           (org-columns-remove-overlays)
-           (setq org-agenda-archives-mode nil)
-           (delete-frame))
-       (and (not (eq org-agenda-window-setup 'current-window))
-            (not (one-window-p))
-            (delete-window))
-       (org-agenda-reset-markers)
-       (kill-buffer buf)
-       (org-columns-remove-overlays)
-       (setq org-agenda-archives-mode nil)))
-    (setq org-agenda-buffer nil)
-    ;; Maybe restore the pre-agenda window configuration.
-    (and org-agenda-restore-windows-after-quit
-        (not (eq org-agenda-window-setup 'other-frame))
-        org-agenda-pre-window-conf
-        (set-window-configuration org-agenda-pre-window-conf)
-        (setq org-agenda-pre-window-conf nil))))
+  (org-agenda--quit))
 
 (defun org-agenda-quit ()
-  "Exit the agenda and restore the window configuration.
-When `org-agenda-sticky' is non-nil, only bury the agenda."
+  "Exit the agenda.
+
+When `org-agenda-sticky' is non-nil, bury the agenda buffer
+instead of killing it.
+
+When `org-agenda-restore-windows-after-quit' is non-nil, restore
+the pre-agenda window configuration.
+
+When column view is active, exit column view instead of the
+agenda."
   (interactive)
-  (if (and (eq org-indirect-buffer-display 'other-window)
-          org-last-indirect-buffer)
-      (let ((org-last-indirect-window
-            (get-buffer-window org-last-indirect-buffer)))
-       (if org-last-indirect-window
-           (delete-window org-last-indirect-window))))
+  (org-agenda--quit org-agenda-sticky))
+
+(defun org-agenda--quit (&optional bury)
   (if org-agenda-columns-active
       (org-columns-quit)
-    (if org-agenda-sticky
-       (let ((buf (current-buffer)))
-         (if (eq org-agenda-window-setup 'other-frame)
-             (progn
-               (delete-frame))
-           (and (not (eq org-agenda-window-setup 'current-window))
-                (not (one-window-p))
-                (delete-window)))
+    (let ((wconf org-agenda-pre-window-conf)
+         (buf (current-buffer))
+         (org-agenda-last-indirect-window
+          (and (eq org-indirect-buffer-display 'other-window)
+               org-agenda-last-indirect-buffer
+               (get-buffer-window org-agenda-last-indirect-buffer))))
+      (cond
+       ((eq org-agenda-window-setup 'other-frame)
+       (delete-frame))
+       ((and org-agenda-restore-windows-after-quit
+            wconf)
+       ;; Maybe restore the pre-agenda window configuration.  Reset
+       ;; `org-agenda-pre-window-conf' before running
+       ;; `set-window-configuration', which loses the current buffer.
+       (setq org-agenda-pre-window-conf nil)
+       (set-window-configuration wconf))
+       (t
+       (when org-agenda-last-indirect-window
+         (delete-window org-agenda-last-indirect-window))
+       (and (not (eq org-agenda-window-setup 'current-window))
+            (not (one-window-p))
+            (delete-window))))
+      (if bury
+         ;; Set the agenda buffer as the current buffer instead of
+         ;; passing it as an argument to `bury-buffer' so that
+         ;; `bury-buffer' removes it from the window.
          (with-current-buffer buf
-           (bury-buffer)
-           ;; Maybe restore the pre-agenda window configuration.
-           (and org-agenda-restore-windows-after-quit
-                (not (eq org-agenda-window-setup 'other-frame))
-                org-agenda-pre-window-conf
-                (set-window-configuration org-agenda-pre-window-conf)
-                (setq org-agenda-pre-window-conf nil))))
-      (org-agenda-Quit))))
+           (bury-buffer))
+       (kill-buffer buf)
+       (setq org-agenda-archives-mode nil
+             org-agenda-buffer nil)))))
 
 (defun org-agenda-exit ()
-  "Exit the agenda and restore the window configuration.
-Also kill Org-mode buffers loaded by `org-agenda'.  Org-mode
-buffers visited directly by the user will not be touched."
+  "Exit the agenda, killing Org buffers loaded by the agenda.
+Like `org-agenda-Quit', but kill any buffers that were created by
+the agenda.  Org buffers visited directly by the user will not be
+touched.  Also, exit the agenda even if it is in column view."
   (interactive)
+  (when org-agenda-columns-active
+    (org-columns-quit))
   (org-release-buffers org-agenda-new-buffers)
   (setq org-agenda-new-buffers nil)
   (org-agenda-Quit))
 
 (defun org-agenda-kill-all-agenda-buffers ()
   "Kill all buffers in `org-agenda-mode'.
-This is used when toggling sticky agendas.
-You can also explicitly invoke it with `C-c a C-k'."
+This is used when toggling sticky agendas."
   (interactive)
   (let (blist)
     (dolist (buf (buffer-list))
@@ -7267,6 +7368,9 @@ in the agenda."
         (cat-preset (get 'org-agenda-category-filter :preset-filter))
         (re-filter org-agenda-regexp-filter)
         (re-preset (get 'org-agenda-regexp-filter :preset-filter))
+        (effort-filter org-agenda-effort-filter)
+        (effort-preset (get 'org-agenda-effort-filter :preset-filter))
+        (org-agenda-tag-filter-while-redo (or tag-filter tag-preset))
         (cols org-agenda-columns-active)
         (line (org-current-line))
         (window-line (- line (org-current-line (window-start))))
@@ -7284,6 +7388,7 @@ in the agenda."
     (put 'org-agenda-tag-filter :preset-filter nil)
     (put 'org-agenda-category-filter :preset-filter nil)
     (put 'org-agenda-regexp-filter :preset-filter nil)
+    (put 'org-agenda-effort-filter :preset-filter nil)
     (and cols (org-columns-quit))
     (message "Rebuilding agenda buffer...")
     (if series-redo-cmd
@@ -7294,19 +7399,23 @@ in the agenda."
          org-agenda-tag-filter tag-filter
          org-agenda-category-filter cat-filter
          org-agenda-regexp-filter re-filter
+         org-agenda-effort-filter effort-filter
          org-agenda-top-headline-filter top-hl-filter)
     (message "Rebuilding agenda buffer...done")
     (put 'org-agenda-tag-filter :preset-filter tag-preset)
     (put 'org-agenda-category-filter :preset-filter cat-preset)
     (put 'org-agenda-regexp-filter :preset-filter re-preset)
+    (put 'org-agenda-effort-filter :preset-filter effort-preset)
     (let ((tag (or tag-filter tag-preset))
          (cat (or cat-filter cat-preset))
-         (re  (or re-filter re-preset)))
-      (when tag (org-agenda-filter-apply tag 'tag))
+         (effort (or effort-filter effort-preset))
+         (re (or re-filter re-preset)))
+      (when tag (org-agenda-filter-apply tag 'tag t))
       (when cat (org-agenda-filter-apply cat 'category))
+      (when effort (org-agenda-filter-apply effort 'effort))
       (when re  (org-agenda-filter-apply re 'regexp)))
     (and top-hl-filter (org-agenda-filter-top-headline-apply top-hl-filter))
-    (and cols (org-called-interactively-p 'any) (org-agenda-columns))
+    (and cols (called-interactively-p 'any) (org-agenda-columns))
     (org-goto-line line)
     (recenter window-line)))
 
@@ -7315,32 +7424,36 @@ in the agenda."
 (defvar org-agenda-filtered-by-category nil)
 
 (defun org-agenda-filter-by-category (strip)
-  "Keep only those lines in the agenda buffer that have a specific category.
-The category is that of the current line."
+  "Filter lines in the agenda buffer that have a specific category.
+The category is that of the current line.
+Without prefix argument, keep only the lines of that category.
+With a prefix argument, exclude the lines of that category.
+"
   (interactive "P")
   (if (and org-agenda-filtered-by-category
           org-agenda-category-filter)
       (org-agenda-filter-show-all-cat)
-    (let ((cat (org-no-properties (get-text-property (point) 'org-category))))
+    (let ((cat (org-no-properties (org-get-at-eol 'org-category 1))))
       (cond
        ((and cat strip)
         (org-agenda-filter-apply
          (push (concat "-" cat) org-agenda-category-filter) 'category))
-       ((and cat)
+       (cat
         (org-agenda-filter-apply
          (setq org-agenda-category-filter
               (list (concat "+" cat))) 'category))
        (t (error "No category at point"))))))
 
 (defun org-find-top-headline (&optional pos)
-  "Find the topmost parent headline and return it."
+  "Find the topmost parent headline and return it.
+POS when non-nil is the marker or buffer position to start the
+search from."
   (save-excursion
-    (with-current-buffer (if pos (marker-buffer pos) (current-buffer))
-      (if pos (goto-char pos))
-      ;; Skip up to the topmost parent
-      (while (ignore-errors (outline-up-heading 1) t))
-      (ignore-errors
-       (nth 4 (org-heading-components))))))
+    (with-current-buffer (if (markerp pos) (marker-buffer pos) 
(current-buffer))
+      (when pos (goto-char pos))
+      ;; Skip up to the topmost parent.
+      (while (org-up-heading-safe))
+      (ignore-errors (nth 4 (org-heading-components))))))
 
 (defvar org-agenda-filtered-by-top-headline nil)
 (defun org-agenda-filter-by-top-headline (strip)
@@ -7375,6 +7488,49 @@ With two prefix arguments, remove the regexp filters."
     (org-agenda-filter-show-all-re)
     (message "Regexp filter removed")))
 
+(defvar org-agenda-effort-filter nil)
+(defun org-agenda-filter-by-effort (strip)
+  "Filter agenda entries by effort.
+With no prefix argument, keep entries matching the effort condition.
+With one prefix argument, filter out entries matching the condition.
+With two prefix arguments, remove the effort filters."
+  (interactive "P")
+  (cond
+   ((member strip '(nil 4))
+    (let* ((efforts (split-string
+                    (or (cdr (assoc (concat org-effort-property "_ALL")
+                                    org-global-properties))
+                        "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00")))
+          ;; XXX: the following handles only up to 10 different
+          ;; effort values.
+          (allowed-keys (if (null efforts) nil
+                          (mapcar (lambda (n) (mod n 10)) ;turn 10 into 0
+                                  (number-sequence 1 (length efforts)))))
+          (op nil))
+      (while (not (memq op '(?< ?> ?=)))
+       (setq op (read-char-exclusive "Effort operator? (> = or <)")))
+      ;; Select appropriate duration.  Ignore non-digit characters.
+      (let ((prompt
+            (apply #'format
+                   (concat "Effort %c "
+                           (mapconcat (lambda (s) (concat "[%d]" s))
+                                      efforts
+                                      " "))
+                   op allowed-keys))
+           (eff -1))
+       (while (not (memq eff allowed-keys))
+         (message prompt)
+         (setq eff (- (read-char-exclusive) 48)))
+       (setq org-agenda-effort-filter
+             (list (concat (if strip "-" "+")
+                           (char-to-string op)
+                           ;; Numbering is 1 2 3 ... 9 0, but we want
+                           ;; 0 1 2 ... 8 9.
+                           (nth (mod (1- eff) 10) efforts)))))
+      (org-agenda-filter-apply org-agenda-effort-filter 'effort)))
+   (t (org-agenda-filter-show-all-effort)
+      (message "Effort filter removed"))))
+
 (defun org-agenda-filter-remove-all ()
   "Remove all filters from the current agenda buffer."
   (interactive)
@@ -7386,15 +7542,24 @@ With two prefix arguments, remove the regexp filters."
     (org-agenda-filter-show-all-re))
   (when org-agenda-top-headline-filter
     (org-agenda-filter-show-all-top-filter))
+  (when org-agenda-effort-filter
+    (org-agenda-filter-show-all-effort))
   (org-agenda-finalize))
 
-(defun org-agenda-filter-by-tag (strip &optional char narrow)
+(defun org-agenda-filter-by-tag (arg &optional char exclude)
   "Keep only those lines in the agenda buffer that have a specific tag.
+
 The tag is selected with its fast selection letter, as configured.
-With prefix argument STRIP, remove all lines that do have the tag.
-A lisp caller can specify CHAR.  NARROW means that the new tag should be
-used to narrow the search - the interactive user can also press `-' or `+'
-to switch to narrowing."
+
+With a `\\[universal-argument]' prefix, exclude the agenda search.
+
+With a `\\[universal-argument] \\[universal-argument]' prefix, filter the 
literal tag, \
+i.e. don't
+filter on all its group members.
+
+A lisp caller can specify CHAR.  EXCLUDE means that the new tag
+should be used to exclude the search - the interactive user can
+also press `-' or `+' to switch between filtering and excluding."
   (interactive "P")
   (let* ((alist org-tag-alist-for-agenda)
         (tag-chars (mapconcat
@@ -7402,54 +7567,34 @@ to switch to narrowing."
                                          (cdr x))
                                     (char-to-string (cdr x))
                                   ""))
-                    alist ""))
-        (efforts (org-split-string
-                  (or (cdr (assoc (concat org-effort-property "_ALL")
-                                  org-global-properties))
-                      "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"
-                      "")))
-        (effort-op org-agenda-filter-effort-default-operator)
-        (effort-prompt "")
+                    org-tag-alist-for-agenda ""))
+        (valid-char-list (append '(?\t ?\r ?/ ?. ?\s ?q)
+                                 (string-to-list tag-chars)))
+        (exclude (or exclude (equal arg '(4))))
+        (expand (not (equal arg '(16))))
         (inhibit-read-only t)
         (current org-agenda-tag-filter)
-        maybe-refresh a n tag)
+        a n tag)
     (unless char
-      (message
-       "%s by tag [%s ], [TAB], %s[/]:off, [+-]:narrow, [>=<?]:effort: "
-       (if narrow "Narrow" "Filter") tag-chars
-       (if org-agenda-auto-exclude-function "[RET], " ""))
-      (setq char (read-char-exclusive)))
-    (when (member char '(?+ ?-))
-      ;; Narrowing down
-      (cond ((equal char ?-) (setq strip t narrow t))
-           ((equal char ?+) (setq strip nil narrow t)))
-      (message
-       "Narrow by tag [%s ], [TAB], [/]:off, [>=<]:effort: " tag-chars)
-      (setq char (read-char-exclusive)))
-    (when (member char '(?< ?> ?= ??))
-      ;; An effort operator
-      (setq effort-op (char-to-string char))
-      (setq alist nil) ; to make sure it will be interpreted as effort.
-      (unless (equal char ??)
-       (loop for i from 0 to 9 do
-             (setq effort-prompt
-                   (concat
-                    effort-prompt " ["
-                    (if (= i 9) "0" (int-to-string (1+ i)))
-                    "]" (nth i efforts))))
-       (message "Effort%s: %s " effort-op effort-prompt)
+      (while (not (memq char valid-char-list))
+       (message
+        "%s by tag [%s ], [TAB], %s[/]:off, [+/-]:filter/exclude%s, [q]:quit"
+        (if exclude "Exclude" "Filter") tag-chars
+        (if org-agenda-auto-exclude-function "[RET], " "")
+        (if expand "" ", no grouptag expand"))
        (setq char (read-char-exclusive))
-       (when (or (< char ?0) (> char ?9))
-         (error "Need 1-9,0 to select effort"))))
-    (when (equal char ?\t)
+       ;; Excluding or filtering down
+       (cond ((eq char ?-) (setq exclude t))
+             ((eq char ?+) (setq exclude nil)))))
+    (when (eq char ?\t)
       (unless (local-variable-p 'org-global-tags-completion-table 
(current-buffer))
-       (org-set-local 'org-global-tags-completion-table
-                      (org-global-tags-completion-table)))
+       (setq-local org-global-tags-completion-table
+                   (org-global-tags-completion-table)))
       (let ((completion-ignore-case t))
-       (setq tag (org-icompleting-read
+       (setq tag (completing-read
                   "Tag: " org-global-tags-completion-table))))
     (cond
-     ((equal char ?\r)
+     ((eq char ?\r)
       (org-agenda-filter-show-all-tag)
       (when org-agenda-auto-exclude-function
        (setq org-agenda-tag-filter nil)
@@ -7458,39 +7603,27 @@ to switch to narrowing."
            (if modifier
                (push modifier org-agenda-tag-filter))))
        (if (not (null org-agenda-tag-filter))
-           (org-agenda-filter-apply org-agenda-tag-filter 'tag)))
-      (setq maybe-refresh t))
-     ((equal char ?/)
+           (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))))
+     ((eq char ?/)
       (org-agenda-filter-show-all-tag)
       (when (get 'org-agenda-tag-filter :preset-filter)
-       (org-agenda-filter-apply org-agenda-tag-filter 'tag))
-      (setq maybe-refresh t))
-     ((equal char ?. )
+       (org-agenda-filter-apply org-agenda-tag-filter 'tag expand)))
+     ((eq char ?.)
       (setq org-agenda-tag-filter
            (mapcar (lambda(tag) (concat "+" tag))
                    (org-get-at-bol 'tags)))
-      (org-agenda-filter-apply org-agenda-tag-filter 'tag)
-      (setq maybe-refresh t))
-     ((or (equal char ?\ )
+      (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))
+     ((eq char ?q)) ;If q, abort (even if there is a q-key for a tag...)
+     ((or (eq char ?\s)
          (setq a (rassoc char alist))
-         (and (>= char ?0) (<= char ?9)
-              (setq n (if (= char ?0) 9 (- char ?0 1))
-                    tag (concat effort-op (nth n efforts))
-                    a (cons tag nil)))
-         (and (= char ??)
-              (setq tag "?eff")
-              a (cons tag nil))
          (and tag (setq a (cons tag nil))))
       (org-agenda-filter-show-all-tag)
       (setq tag (car a))
       (setq org-agenda-tag-filter
-           (cons (concat (if strip "-" "+") tag)
-                 (if narrow current nil)))
-      (org-agenda-filter-apply org-agenda-tag-filter 'tag)
-      (setq maybe-refresh t))
-     (t (error "Invalid tag selection character %c" char)))
-    (when maybe-refresh
-      (org-agenda-redo))))
+           (cons (concat (if exclude "-" "+") tag)
+                 current))
+      (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))
+     (t (error "Invalid tag selection character %c" char)))))
 
 (defun org-agenda-get-represented-tags ()
   "Get a list of all tags currently represented in the agenda."
@@ -7503,13 +7636,11 @@ to switch to narrowing."
              (get-text-property (point) 'tags))))
     tags))
 
-(defun org-agenda-filter-by-tag-refine (strip &optional char)
-  "Refine the current filter.  See `org-agenda-filter-by-tag'."
-  (interactive "P")
-  (org-agenda-filter-by-tag strip char 'refine))
 
-(defun org-agenda-filter-make-matcher (filter type)
-  "Create the form that tests a line for agenda filter."
+(defun org-agenda-filter-make-matcher (filter type &optional expand)
+  "Create the form that tests a line for agenda filter.  Optional
+argument EXPAND can be used for the TYPE tag and will expand the
+tags in the FILTER if any of the tags in FILTER are grouptags."
   (let (f f1)
     (cond
      ;; Tag filter
@@ -7519,28 +7650,11 @@ to switch to narrowing."
             (append (get 'org-agenda-tag-filter :preset-filter)
                     filter)))
       (dolist (x filter)
-       (let ((nfilter (org-agenda-filter-expand-tags filter)) nf nf1
-             (ffunc
-              (lambda (nf0 nf01 fltr notgroup op)
-                (dolist (x fltr)
-                  (if (member x '("-" "+"))
-                      (setq nf01 (if (equal x "-") 'tags '(not tags)))
-                    (if (string-match "[<=>?]" x)
-                        (setq nf01 (org-agenda-filter-effort-form x))
-                      (setq nf01 (list 'member (downcase (substring x 1))
-                                       'tags)))
-                    (when (equal (string-to-char x) ?-)
-                      (setq nf01 (list 'not nf01))
-                      (when (not notgroup) (setq op 'and))))
-                  (push nf01 nf0))
-                (if notgroup
-                    (push (cons 'and nf0) f)
-                  (push (cons (or op 'or) nf0) f)))))
-         (cond ((equal filter '("+"))
-                (setq f (list (list 'not 'tags))))
-               ((equal nfilter filter)
-                (funcall ffunc f1 f filter t nil))
-               (t (funcall ffunc nf1 nf nfilter nil nil))))))
+       (let ((op (string-to-char x)))
+         (if expand (setq x (org-agenda-filter-expand-tags (list x) t))
+           (setq x (list x)))
+         (setq f1 (org-agenda-filter-make-matcher-tag-exp x op))
+         (push f1 f))))
      ;; Category filter
      ((eq type 'category)
       (setq filter
@@ -7562,9 +7676,35 @@ to switch to narrowing."
        (if (equal "-" (substring x 0 1))
            (setq f1 (list 'not (list 'string-match (substring x 1) 'txt)))
          (setq f1 (list 'string-match (substring x 1) 'txt)))
-       (push f1 f))))
+       (push f1 f)))
+     ;; Effort filter
+     ((eq type 'effort)
+      (setq filter
+           (delete-dups
+            (append (get 'org-agenda-effort-filter :preset-filter)
+                    filter)))
+      (dolist (x filter)
+       (push (org-agenda-filter-effort-form x) f))))
     (cons 'and (nreverse f))))
 
+(defun org-agenda-filter-make-matcher-tag-exp (tags op)
+  "Return a form associated to tag-expression TAGS.
+Build a form testing a line for agenda filter for
+tag-expressions.  OP is an operator of type CHAR that allows the
+function to set the right switches in the returned form."
+  (let (form)
+    ;; Any of the expressions can match if OP is +, all must match if
+    ;; the operator is -.
+    (dolist (x tags (cons (if (eq op ?-) 'and 'or) form))
+      (let* ((tag (substring x 1))
+            (f (cond
+                ((string= "" tag) '(not tags))
+                ((and (string-match-p "\\`{" tag) (string-match-p "}\\'" tag))
+                 ;; TAG is a regexp.
+                 (list 'org-match-any-p (substring tag 1 -1) 'tags))
+                (t (list 'member (downcase tag) 'tags)))))
+       (push (if (eq op ?-) (list 'not f) f) form)))))
+
 (defun org-agenda-filter-effort-form (e)
   "Return the form to compare the effort of the current line with what E says.
 E looks like \"+<2:25\"."
@@ -7581,11 +7721,12 @@ E looks like \"+<2:25\"."
 (defun org-agenda-compare-effort (op value)
   "Compare the effort of the current line with VALUE, using OP.
 If the line does not have an effort defined, return nil."
-  (let ((eff (org-get-at-bol 'effort-minutes)))
-    (if (equal op ??)
-       (not eff)
-      (funcall op (or eff (if org-sort-agenda-noeffort-is-high 32767 0))
-              value))))
+  ;; `effort-minutes' property cannot be extracted directly from
+  ;; current line but is stored as a property in `txt'.
+  (let ((effort (get-text-property 0 'effort-minutes (org-get-at-bol 'txt))))
+    (funcall op
+            (or effort (if org-sort-agenda-noeffort-is-high 32767 -1))
+            value)))
 
 (defun org-agenda-filter-expand-tags (filter &optional no-operator)
   "Expand group tags in FILTER for the agenda.
@@ -7605,12 +7746,14 @@ When NO-OPERATOR is non-nil, do not add the + operator 
to returned tags."
        (reverse rtn))
     filter))
 
-(defun org-agenda-filter-apply (filter type)
-  "Set FILTER as the new agenda filter and apply it."
+(defun org-agenda-filter-apply (filter type &optional expand)
+  "Set FILTER as the new agenda filter and apply it.  Optional
+argument EXPAND can be used for the TYPE tag and will expand the
+tags in the FILTER if any of the tags in FILTER are grouptags."
   ;; Deactivate `org-agenda-entry-text-mode' when filtering
   (if org-agenda-entry-text-mode (org-agenda-entry-text-mode))
   (let (tags cat txt)
-    (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type))
+    (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type 
expand))
     ;; Only set `org-agenda-filtered-by-category' to t when a unique
     ;; category is used as the filter:
     (setq org-agenda-filtered-by-category
@@ -7622,13 +7765,9 @@ When NO-OPERATOR is non-nil, do not add the + operator 
to returned tags."
       (while (not (eobp))
        (if (org-get-at-bol 'org-marker)
            (progn
-             (setq tags ; used in eval
-                   (apply 'append
-                          (mapcar (lambda (f)
-                                    (org-agenda-filter-expand-tags (list f) t))
-                                  (org-get-at-bol 'tags)))
-                   cat (get-text-property (point) 'org-category)
-                   txt (get-text-property (point) 'txt))
+             (setq tags (org-get-at-bol 'tags)
+                   cat (org-get-at-eol 'org-category 1)
+                   txt (org-get-at-bol 'txt))
              (if (not (eval org-agenda-filter-form))
                  (org-agenda-filter-hide-line type))
              (beginning-of-line 2))
@@ -7681,6 +7820,8 @@ When NO-OPERATOR is non-nil, do not add the + operator to 
returned tags."
   (org-agenda-remove-filter 'tag))
 (defun org-agenda-filter-show-all-re nil
   (org-agenda-remove-filter 'regexp))
+(defun org-agenda-filter-show-all-effort nil
+  (org-agenda-remove-filter 'effort))
 (defun org-agenda-filter-show-all-cat nil
   (org-agenda-remove-filter 'category))
 (defun org-agenda-filter-show-all-top-filter nil
@@ -7779,7 +7920,7 @@ Negative selection means regexp must not match for 
selection of an entry."
      (tdpos (goto-char tdpos))
      ((eq org-agenda-type 'agenda)
       (let* ((sd (org-agenda-compute-starting-span
-                 (org-today) (or curspan org-agenda-ndays org-agenda-span)))
+                 (org-today) (or curspan org-agenda-span)))
             (org-agenda-overriding-arguments args))
        (setf (nth 1 org-agenda-overriding-arguments) sd)
        (org-agenda-redo)
@@ -7792,27 +7933,40 @@ Negative selection means regexp must not match for 
selection of an entry."
        (text-property-any (point-min) (point-max) 'org-today t)
        (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda)
        (and (get-text-property (min (1- (point-max)) (point)) 'org-series)
-           (org-agenda-goto-block-beginning))
+           (org-agenda-backward-block))
        (point-min))))
 
-(defun org-agenda-goto-block-beginning ()
-  "Go the agenda block beginning."
+(defun org-agenda-backward-block ()
+  "Move backward by one agenda block."
   (interactive)
-  (if (not (derived-mode-p 'org-agenda-mode))
-      (error "Cannot execute this command outside of org-agenda-mode buffers")
-    (let (dest)
-      (save-excursion
-       (unless (looking-at "\\'")
-         (forward-char))
-       (let* ((prop 'org-agenda-structural-header)
-              (p (previous-single-property-change (point) prop))
-              (n (next-single-property-change (or (and (looking-at "\\`") 1)
-                                                  (1- (point))) prop)))
-         (setq dest (cond ((eq n (point-at-eol)) (1- n)) (p (1- p))))))
-      (if (not dest)
-         (error "Cannot find the beginning of the blog")
-       (goto-char dest)
-       (move-beginning-of-line 1)))))
+  (org-agenda-forward-block 'backward))
+
+(defun org-agenda-forward-block (&optional backward)
+  "Move forward by one agenda block.
+When optional argument BACKWARD is set, go backward"
+  (interactive)
+  (cond ((not (derived-mode-p 'org-agenda-mode))
+        (user-error
+         "Cannot execute this command outside of org-agenda-mode buffers"))
+       ((looking-at (if backward "\\`" "\\'"))
+        (message "Already at the %s block" (if backward "first" "last")))
+       (t (let ((pos (prog1 (point)
+                       (ignore-errors (if backward (backward-char 1)
+                                        (move-end-of-line 1)))))
+                (f (if backward
+                       'previous-single-property-change
+                     'next-single-property-change))
+                moved dest)
+            (while (and (setq dest (funcall
+                                    f (point) 'org-agenda-structural-header))
+                        (not (get-text-property
+                              (point) 'org-agenda-structural-header)))
+              (setq moved t)
+              (goto-char dest))
+            (if moved (move-beginning-of-line 1)
+              (goto-char (if backward (point-min) (point-max)))
+              (move-beginning-of-line 1)
+              (message "No %s block" (if backward "previous" "further")))))))
 
 (defun org-agenda-later (arg)
   "Go forward in time by the current span.
@@ -7866,71 +8020,77 @@ With prefix ARG, go backward that many times the 
current span."
   (message "View: [d]ay  [w]eek  for[t]night  [m]onth  [y]ear  [SPC]reset  
[q]uit/abort
       time[G]rid   [[]inactive  [f]ollow      [l]og    [L]og-all   [c]lockcheck
       [a]rch-trees [A]rch-files clock[R]eport include[D]iary       
[E]ntryText")
-  (let ((a (read-char-exclusive)))
-    (case a
-      (?\  (call-interactively 'org-agenda-reset-view))
-      (?d (call-interactively 'org-agenda-day-view))
-      (?w (call-interactively 'org-agenda-week-view))
-      (?t (call-interactively 'org-agenda-fortnight-view))
-      (?m (call-interactively 'org-agenda-month-view))
-      (?y (call-interactively 'org-agenda-year-view))
-      (?l (call-interactively 'org-agenda-log-mode))
-      (?L (org-agenda-log-mode '(4)))
-      (?c (org-agenda-log-mode 'clockcheck))
-      ((?F ?f) (call-interactively 'org-agenda-follow-mode))
-      (?a (call-interactively 'org-agenda-archives-mode))
-      (?A (org-agenda-archives-mode 'files))
-      ((?R ?r) (call-interactively 'org-agenda-clockreport-mode))
-      ((?E ?e) (call-interactively 'org-agenda-entry-text-mode))
-      (?G (call-interactively 'org-agenda-toggle-time-grid))
-      (?D (call-interactively 'org-agenda-toggle-diary))
-      (?\! (call-interactively 'org-agenda-toggle-deadlines))
-      (?\[ (let ((org-agenda-include-inactive-timestamps t))
-            (org-agenda-check-type t 'timeline 'agenda)
-            (org-agenda-redo))
-          (message "Display now includes inactive timestamps as well"))
-      (?q (message "Abort"))
-      (otherwise (error "Invalid key" )))))
+  (pcase (read-char-exclusive)
+    (?\ (call-interactively 'org-agenda-reset-view))
+    (?d (call-interactively 'org-agenda-day-view))
+    (?w (call-interactively 'org-agenda-week-view))
+    (?t (call-interactively 'org-agenda-fortnight-view))
+    (?m (call-interactively 'org-agenda-month-view))
+    (?y (call-interactively 'org-agenda-year-view))
+    (?l (call-interactively 'org-agenda-log-mode))
+    (?L (org-agenda-log-mode '(4)))
+    (?c (org-agenda-log-mode 'clockcheck))
+    ((or ?F ?f) (call-interactively 'org-agenda-follow-mode))
+    (?a (call-interactively 'org-agenda-archives-mode))
+    (?A (org-agenda-archives-mode 'files))
+    ((or ?R ?r) (call-interactively 'org-agenda-clockreport-mode))
+    ((or ?E ?e) (call-interactively 'org-agenda-entry-text-mode))
+    (?G (call-interactively 'org-agenda-toggle-time-grid))
+    (?D (call-interactively 'org-agenda-toggle-diary))
+    (?\! (call-interactively 'org-agenda-toggle-deadlines))
+    (?\[ (let ((org-agenda-include-inactive-timestamps t))
+          (org-agenda-check-type t 'timeline 'agenda)
+          (org-agenda-redo))
+        (message "Display now includes inactive timestamps as well"))
+    (?q (message "Abort"))
+    (key (user-error "Invalid key: %s" key))))
 
 (defun org-agenda-reset-view ()
   "Switch to default view for agenda."
   (interactive)
-  (org-agenda-change-time-span (or org-agenda-ndays org-agenda-span)))
+  (org-agenda-change-time-span org-agenda-span))
+
 (defun org-agenda-day-view (&optional day-of-month)
   "Switch to daily view for agenda.
 With argument DAY-OF-MONTH, switch to that day of the month."
   (interactive "P")
   (org-agenda-change-time-span 'day day-of-month))
+
 (defun org-agenda-week-view (&optional iso-week)
-  "Switch to daily view for agenda.
+  "Switch to weekly view for agenda.
 With argument ISO-WEEK, switch to the corresponding ISO week.
-If ISO-WEEK has more then 2 digits, only the last two encode the
-week.  Any digits before this encode a year.  So 200712 means
-week 12 of year 2007.  Years in the range 1938-2037 can also be
-written as 2-digit years."
+If ISO-WEEK has more then 2 digits, only the last two encode
+the week.  Any digits before this encode a year.  So 200712
+means week 12 of year 2007.  Years ranging from 70 years ago
+to 30 years in the future can also be written as 2-digit years."
   (interactive "P")
   (org-agenda-change-time-span 'week iso-week))
+
 (defun org-agenda-fortnight-view (&optional iso-week)
-  "Switch to daily view for agenda.
+  "Switch to fortnightly view for agenda.
 With argument ISO-WEEK, switch to the corresponding ISO week.
-If ISO-WEEK has more then 2 digits, only the last two encode the
-week.  Any digits before this encode a year.  So 200712 means
-week 12 of year 2007.  Years in the range 1938-2037 can also be
-written as 2-digit years."
+If ISO-WEEK has more then 2 digits, only the last two encode
+the week.  Any digits before this encode a year.  So 200712
+means week 12 of year 2007.  Years ranging from 70 years ago
+to 30 years in the future can also be written as 2-digit years."
   (interactive "P")
   (org-agenda-change-time-span 'fortnight iso-week))
+
 (defun org-agenda-month-view (&optional month)
   "Switch to monthly view for agenda.
-With argument MONTH, switch to that month."
+With argument MONTH, switch to that month.  If MONTH has more
+then 2 digits, only the last two encode the month.  Any digits
+before this encode a year.  So 200712 means December year 2007.
+Years ranging from 70 years ago to 30 years in the future can
+also be written as 2-digit years."
   (interactive "P")
   (org-agenda-change-time-span 'month month))
+
 (defun org-agenda-year-view (&optional year)
   "Switch to yearly view for agenda.
-With argument YEAR, switch to that year.
-If MONTH has more then 2 digits, only the last two encode the
-month.  Any digits before this encode a year.  So 200712 means
-December year 2007.  Years in the range 1938-2037 can also be
-written as 2-digit years."
+With argument YEAR, switch to that year.  Years ranging from 70
+years ago to 30 years in the future can also be written as
+2-digit years."
   (interactive "P")
   (when year
     (setq year (org-small-year-to-year year)))
@@ -7988,7 +8148,7 @@ so that the date SD will be in that range."
            (setq y1 (org-small-year-to-year (/ n 100))
                  n (mod n 100)))
          (setq sd
-               (calendar-absolute-from-iso
+               (calendar-iso-to-absolute
                 (list n 1
                       (or y1 (nth 2 (calendar-iso-from-absolute sd)))))))))
      ((eq span 'month)
@@ -8034,7 +8194,7 @@ so that the date SD will be in that range."
 
 (defun org-unhighlight ()
   "Detach overlay INDEX."
-  (org-detach-overlay org-hl))
+  (delete-overlay org-hl))
 
 (defun org-unhighlight-once ()
   "Remove the highlight from its position, and this function from the hook."
@@ -8091,9 +8251,12 @@ so that the date SD will be in that range."
 
 (defun org-agenda-log-mode (&optional special)
   "Toggle log mode in an agenda buffer.
+
 With argument SPECIAL, show all possible log items, not only the ones
 configured in `org-agenda-log-mode-items'.
-With a double `C-u' prefix arg, show *only* log items, nothing else."
+
+With a `\\[universal-argument] \\[universal-argument]' prefix, show *only* \
+log items, nothing else."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline)
   (setq org-agenda-show-log
@@ -8107,8 +8270,7 @@ With a double `C-u' prefix arg, show *only* log items, 
nothing else."
   (setq org-agenda-start-with-log-mode org-agenda-show-log)
   (org-agenda-set-mode-name)
   (org-agenda-redo)
-  (message "Log mode is %s"
-          (if org-agenda-show-log "on" "off")))
+  (message "Log mode is %s" (if org-agenda-show-log "on" "off")))
 
 (defun org-agenda-archives-mode (&optional with-files)
   "Toggle inclusion of items in trees marked with :ARCHIVE:.
@@ -8180,7 +8342,7 @@ When called with a prefix argument, include all archive 
files as well."
               (t ""))
              (if (or org-agenda-category-filter
                      (get 'org-agenda-category-filter :preset-filter))
-                 '(:eval (org-propertize
+                 '(:eval (propertize
                           (concat " <"
                                   (mapconcat
                                    'identity
@@ -8193,7 +8355,7 @@ When called with a prefix argument, include all archive 
files as well."
                           'help-echo "Category used in filtering")) "")
              (if (or org-agenda-tag-filter
                      (get 'org-agenda-tag-filter :preset-filter))
-                 '(:eval (org-propertize
+                 '(:eval (propertize
                           (concat " {"
                                   (mapconcat
                                    'identity
@@ -8204,9 +8366,22 @@ When called with a prefix argument, include all archive 
files as well."
                                   "}")
                           'face 'org-agenda-filter-tags
                           'help-echo "Tags used in filtering")) "")
+             (if (or org-agenda-effort-filter
+                     (get 'org-agenda-effort-filter :preset-filter))
+                 '(:eval (propertize
+                          (concat " {"
+                                  (mapconcat
+                                   'identity
+                                   (append
+                                    (get 'org-agenda-effort-filter 
:preset-filter)
+                                    org-agenda-effort-filter)
+                                   "")
+                                  "}")
+                          'face 'org-agenda-filter-effort
+                          'help-echo "Effort conditions used in filtering")) 
"")
              (if (or org-agenda-regexp-filter
                      (get 'org-agenda-regexp-filter :preset-filter))
-                 '(:eval (org-propertize
+                 '(:eval (propertize
                           (concat " ["
                                   (mapconcat
                                    'identity
@@ -8225,9 +8400,6 @@ When called with a prefix argument, include all archive 
files as well."
              (if org-agenda-clockreport-mode " Clock" "")))
   (force-mode-line-update))
 
-(define-obsolete-function-alias
-  'org-agenda-post-command-hook 'org-agenda-update-agenda-type "24.3")
-
 (defun org-agenda-update-agenda-type ()
   "Update the agenda type after each command."
   (setq org-agenda-type
@@ -8290,7 +8462,7 @@ When called with a prefix argument, include all archive 
files as well."
       (message "No tags associated with this line"))))
 
 (defun org-agenda-goto (&optional highlight)
-  "Go to the Org-mode file which contains the item at point."
+  "Go to the entry at point in the corresponding Org file."
   (interactive)
   (let* ((marker (or (org-get-at-bol 'org-marker)
                     (org-agenda-error)))
@@ -8302,12 +8474,11 @@ When called with a prefix argument, include all archive 
files as well."
     (goto-char pos)
     (when (derived-mode-p 'org-mode)
       (org-show-context 'agenda)
-      (save-excursion
-       (and (outline-next-heading)
-            (org-flag-heading nil))))  ; show the next heading
-    (when (outline-invisible-p)
-      (show-entry))                    ; display invisible text
-    (recenter (/ (window-height) 2))
+      (recenter (/ (window-height) 2))
+      (org-back-to-heading t)
+      (let ((case-fold-search nil))
+       (when (re-search-forward org-complex-heading-regexp nil t)
+         (goto-char (match-beginning 4)))))
     (run-hooks 'org-agenda-after-show-hook)
     (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
 
@@ -8394,7 +8565,7 @@ Point is in the buffer where the item originated.")
                  (org-remove-subtree-entries-from-agenda))
                (org-back-to-heading t)
                (funcall cmd)))
-         (error "Archiving works only in Org-mode files"))))))
+         (error "Archiving works only in Org files"))))))
 
 (defun org-remove-subtree-entries-from-agenda (&optional buf beg end)
   "Remove all lines in the agenda that correspond to a given subtree.
@@ -8424,9 +8595,16 @@ If this information is not given, the function uses the 
tree at point."
 (defun org-agenda-refile (&optional goto rfloc no-update)
   "Refile the item at point.
 
-When GOTO is 0 or '(64), clear the refile cache.
-When GOTO is '(16), go to the location of the last refiled item.
+When called with `\\[universal-argument] \\[universal-argument]', \
+go to the location of the last
+refiled item.
+
+When called with `\\[universal-argument] \\[universal-argument] \
+\\[universal-argument]' prefix or when GOTO is 0, clear
+the refile cache.
+
 RFLOC can be a refile location obtained in a different way.
+
 When NO-UPDATE is non-nil, don't redo the agenda buffer."
   (interactive "P")
   (cond
@@ -8445,13 +8623,11 @@ When NO-UPDATE is non-nil, don't redo the agenda 
buffer."
                       (if goto "Goto" "Refile to") buffer
                       org-refile-allow-creating-parent-nodes))))
       (with-current-buffer buffer
-       (save-excursion
-         (save-restriction
-           (widen)
-           (goto-char marker)
-           (let ((org-agenda-buffer-name buffer-orig))
-             (org-remove-subtree-entries-from-agenda))
-           (org-refile goto buffer rfloc)))))
+       (org-with-wide-buffer
+        (goto-char marker)
+        (let ((org-agenda-buffer-name buffer-orig))
+          (org-remove-subtree-entries-from-agenda))
+        (org-refile goto buffer rfloc))))
     (unless no-update (org-agenda-redo)))))
 
 (defun org-agenda-open-link (&optional arg)
@@ -8476,13 +8652,11 @@ It also looks at the text of the entry itself."
                  (setq trg (and (string-match org-bracket-link-regexp l)
                                 (match-string 1 l)))
                  (if (or (not trg) (string-match org-any-link-re trg))
-                     (save-excursion
-                       (save-restriction
-                         (widen)
-                         (goto-char marker)
-                         (when (search-forward l nil lkend)
-                           (goto-char (match-beginning 0))
-                           (org-open-at-point))))
+                     (org-with-wide-buffer
+                      (goto-char marker)
+                      (when (search-forward l nil lkend)
+                        (goto-char (match-beginning 0))
+                        (org-open-at-point)))
                    ;; This is an internal link, widen the buffer
                    (switch-to-buffer-other-window buffer)
                    (widen)
@@ -8502,11 +8676,14 @@ It also looks at the text of the entry itself."
   "Get a variable from a referenced buffer and install it here."
   (let ((m (org-get-at-bol 'org-marker)))
     (when (and m (buffer-live-p (marker-buffer m)))
-      (org-set-local var (with-current-buffer (marker-buffer m)
-                          (symbol-value var))))))
+      (set (make-local-variable var)
+          (with-current-buffer (marker-buffer m)
+            (symbol-value var))))))
 
 (defun org-agenda-switch-to (&optional delete-other-windows)
-  "Go to the Org-mode file which contains the item at point."
+  "Go to the Org mode file which contains the item at point.
+When optional argument DELETE-OTHER-WINDOWS is non-nil, the
+displayed Org file fills the frame."
   (interactive)
   (if (and org-return-follows-link
           (not (org-get-at-bol 'org-marker))
@@ -8516,44 +8693,40 @@ It also looks at the text of the entry itself."
                       (org-agenda-error)))
           (buffer (marker-buffer marker))
           (pos (marker-position marker)))
-      (org-pop-to-buffer-same-window buffer)
-      (and delete-other-windows (delete-other-windows))
+      (unless buffer (user-error "Trying to switch to non-existent buffer"))
+      (pop-to-buffer-same-window buffer)
+      (when delete-other-windows (delete-other-windows))
       (widen)
       (goto-char pos)
       (when (derived-mode-p 'org-mode)
        (org-show-context 'agenda)
-       (save-excursion
-         (and (outline-next-heading)
-              (org-flag-heading nil))) ; show the next heading
-       (when (outline-invisible-p)
-         (show-entry))                 ; display invisible text
        (run-hooks 'org-agenda-after-show-hook)))))
 
 (defun org-agenda-goto-mouse (ev)
-  "Go to the Org-mode file which contains the item at the mouse click."
+  "Go to the Org file which contains the item at the mouse click."
   (interactive "e")
   (mouse-set-point ev)
   (org-agenda-goto))
 
 (defun org-agenda-show (&optional full-entry)
-  "Display the Org-mode file which contains the item at point.
+  "Display the Org file which contains the item at point.
 With prefix argument FULL-ENTRY, make the entire entry visible
 if it was hidden in the outline."
   (interactive "P")
   (let ((win (selected-window)))
-    (if full-entry
-       (let ((org-show-entry-below t))
-         (org-agenda-goto t))
-      (org-agenda-goto t))
+    (org-agenda-goto t)
+    (when full-entry (org-show-entry))
     (select-window win)))
 
 (defvar org-agenda-show-window nil)
 (defun org-agenda-show-and-scroll-up (&optional arg)
-  "Display the Org-mode file which contains the item at point.
+  "Display the Org file which contains the item at point.
+
 When called repeatedly, scroll the window that is displaying the buffer.
-With a \\[universal-argument] prefix, use `org-show-entry' instead of
-`show-subtree' to display the item, so that drawers and logbooks stay
-folded."
+
+With a `\\[universal-argument]' prefix, use `org-show-entry' instead of \
+`outline-show-subtree'
+to display the item, so that drawers and logbooks stay folded."
   (interactive "P")
   (let ((win (selected-window)))
     (if (and (window-live-p org-agenda-show-window)
@@ -8562,7 +8735,7 @@ folded."
          (select-window org-agenda-show-window)
          (ignore-errors (scroll-up)))
       (org-agenda-goto t)
-      (if arg (org-show-entry) (show-subtree))
+      (if arg (org-show-entry) (outline-show-subtree))
       (setq org-agenda-show-window (selected-window)))
     (select-window win)))
 
@@ -8576,7 +8749,7 @@ folded."
       (select-window win))))
 
 (defun org-agenda-show-1 (&optional more)
-  "Display the Org-mode file which contains the item at point.
+  "Display the Org file which contains the item at point.
 The prefix arg selects the amount of information to display:
 
 0   hide the subtree
@@ -8594,50 +8767,46 @@ if it was hidden in the outline."
     (set-window-start (selected-window) (point-at-bol))
     (cond
      ((= more 0)
-      (hide-subtree)
+      (outline-hide-subtree)
       (save-excursion
        (org-back-to-heading)
        (run-hook-with-args 'org-cycle-hook 'folded))
       (message "Remote: FOLDED"))
-     ((and (org-called-interactively-p 'any) (= more 1))
+     ((and (called-interactively-p 'any) (= more 1))
       (message "Remote: show with default settings"))
      ((= more 2)
-      (show-entry)
-      (show-children)
+      (outline-show-entry)
+      (org-show-children)
       (save-excursion
        (org-back-to-heading)
        (run-hook-with-args 'org-cycle-hook 'children))
       (message "Remote: CHILDREN"))
      ((= more 3)
-      (show-subtree)
+      (outline-show-subtree)
       (save-excursion
        (org-back-to-heading)
        (run-hook-with-args 'org-cycle-hook 'subtree))
       (message "Remote: SUBTREE"))
      ((= more 4)
-      (let* ((org-drawers (delete "LOGBOOK" (copy-sequence org-drawers)))
-            (org-drawer-regexp
-             (concat "^[ \t]*:\\("
-                     (mapconcat 'regexp-quote org-drawers "\\|")
-                     "\\):[ \t]*$")))
-       (show-subtree)
-       (save-excursion
-         (org-back-to-heading)
-         (org-cycle-hide-drawers 'subtree)))
+      (outline-show-subtree)
+      (save-excursion
+       (org-back-to-heading)
+       (org-cycle-hide-drawers 'subtree '("LOGBOOK")))
       (message "Remote: SUBTREE AND LOGBOOK"))
      ((> more 4)
-      (show-subtree)
+      (outline-show-subtree)
       (message "Remote: SUBTREE AND ALL DRAWERS")))
     (select-window win)))
 
 (defvar org-agenda-cycle-counter nil)
 (defun org-agenda-cycle-show (&optional n)
   "Show the current entry in another window, with default settings.
-Default settings are taken from `org-show-hierarchy-above' and siblings.
-When use repeatedly in immediate succession, the remote entry will cycle
-through visibility
 
-children -> subtree -> folded
+Default settings are taken from `org-show-context-detail'.  When
+use repeatedly in immediate succession, the remote entry will
+cycle through visibility
+
+  children -> subtree -> folded
 
 When called with a numeric prefix arg, that arg will be passed through to
 `org-agenda-show-1'.  For the interpretation of that argument, see the
@@ -8655,7 +8824,7 @@ docstring of `org-agenda-show-1'."
   (org-agenda-show-1 org-agenda-cycle-counter))
 
 (defun org-agenda-recenter (arg)
-  "Display the Org-mode file which contains the item at point and recenter."
+  "Display the Org file which contains the item at point and recenter."
   (interactive "P")
   (let ((win (selected-window)))
     (org-agenda-goto t)
@@ -8663,7 +8832,7 @@ docstring of `org-agenda-show-1'."
     (select-window win)))
 
 (defun org-agenda-show-mouse (ev)
-  "Display the Org-mode file which contains the item at the mouse click."
+  "Display the Org file which contains the item at the mouse click."
   (interactive "e")
   (mouse-set-point ev)
   (org-agenda-show))
@@ -8674,7 +8843,8 @@ docstring of `org-agenda-show-1'."
       (org-agenda-error)))
 
 (defun org-agenda-error ()
-  (error "Command not allowed in this line"))
+  "Throw an error when a command is not allowed in the agenda."
+  (user-error "Command not allowed in this line"))
 
 (defun org-agenda-tree-to-indirect-buffer (arg)
   "Show the subtree corresponding to the current entry in an indirect buffer.
@@ -8682,8 +8852,10 @@ This calls the command `org-tree-to-indirect-buffer' 
from the original buffer.
 
 With a numerical prefix ARG, go up to this level and then take that tree.
 With a negative numeric ARG, go up by this number of levels.
-With a \\[universal-argument] prefix, make a separate frame for this tree 
(i.e. don't
-use the dedicated frame)."
+
+With a `\\[universal-argument]' prefix, make a separate frame for this tree, \
+i.e. don't use
+the dedicated frame."
   (interactive "P")
   (if current-prefix-arg
       (org-agenda-do-tree-to-indirect-buffer arg)
@@ -8701,7 +8873,8 @@ use the dedicated frame)."
          (and indirect-window (select-window indirect-window))
          (switch-to-buffer org-last-indirect-buffer :norecord)
          (fit-window-to-buffer indirect-window)))
-      (select-window (get-buffer-window agenda-buffer)))))
+      (select-window (get-buffer-window agenda-buffer))
+      (setq org-agenda-last-indirect-buffer org-last-indirect-buffer))))
 
 (defun org-agenda-do-tree-to-indirect-buffer (arg)
   "Same as `org-agenda-tree-to-indirect-buffer' without saving window."
@@ -8730,9 +8903,9 @@ by a remote command from the agenda.")
   (org-agenda-todo 'previousset))
 
 (defun org-agenda-todo (&optional arg)
-  "Cycle TODO state of line at point, also in Org-mode file.
+  "Cycle TODO state of line at point, also in Org file.
 This changes the line at point, all other lines in the agenda referring to
-the same tree node, and the headline of the tree node in the Org-mode file."
+the same tree node, and the headline of the tree node in the Org file."
   (interactive "P")
   (org-agenda-check-no-diary)
   (let* ((col (current-column))
@@ -8741,7 +8914,7 @@ the same tree node, and the headline of the tree node in 
the Org-mode file."
         (buffer (marker-buffer marker))
         (pos (marker-position marker))
         (hdmarker (org-get-at-bol 'org-hd-marker))
-        (todayp (org-agenda-todayp (org-get-at-bol 'day)))
+        (todayp (org-agenda-today-p (org-get-at-bol 'day)))
         (inhibit-read-only t)
         org-agenda-headline-snapshot-before-repeat newhead just-one)
     (org-with-remote-undo buffer
@@ -8749,14 +8922,11 @@ the same tree node, and the headline of the tree node 
in the Org-mode file."
        (widen)
        (goto-char pos)
        (org-show-context 'agenda)
-       (save-excursion
-         (and (outline-next-heading)
-              (org-flag-heading nil)))   ; show the next heading
        (let ((current-prefix-arg arg))
          (call-interactively 'org-todo))
        (and (bolp) (forward-char 1))
        (setq newhead (org-get-heading))
-       (when (and (org-bound-and-true-p
+       (when (and (bound-and-true-p
                    org-agenda-headline-snapshot-before-repeat)
                   (not (equal org-agenda-headline-snapshot-before-repeat
                               newhead))
@@ -8769,11 +8939,12 @@ the same tree node, and the headline of the tree node 
in the Org-mode file."
       (beginning-of-line 1)
       (save-window-excursion
        (org-agenda-change-all-lines newhead hdmarker 'fixface just-one))
-      (when (org-bound-and-true-p org-clock-out-when-done)
+      (when (bound-and-true-p org-clock-out-when-done)
        (string-match (concat "^" (regexp-opt org-done-keywords-for-agenda))
                      newhead)
        (org-agenda-unmark-clocking-task))
-      (org-move-to-column col))))
+      (org-move-to-column col)
+      (org-agenda-mark-clocking-task))))
 
 (defun org-agenda-add-note (&optional arg)
   "Add a time-stamped note to the entry at point."
@@ -8789,9 +8960,6 @@ the same tree node, and the headline of the tree node in 
the Org-mode file."
       (widen)
       (goto-char pos)
       (org-show-context 'agenda)
-      (save-excursion
-       (and (outline-next-heading)
-            (org-flag-heading nil)))   ; show the next heading
       (org-add-note))))
 
 (defun org-agenda-change-all-lines (newhead hdmarker
@@ -8808,9 +8976,9 @@ If FORCE-TAGS is non nil, the car of it returns the new 
tags."
         (line (org-current-line))
         (org-agenda-buffer (current-buffer))
         (thetags (with-current-buffer (marker-buffer hdmarker)
-                   (save-excursion (save-restriction (widen)
-                                                     (goto-char hdmarker)
-                                                     (org-get-tags-at)))))
+                   (org-with-wide-buffer
+                    (goto-char hdmarker)
+                    (org-get-tags-at))))
         props m pl undone-face done-face finish new dotime level cat tags)
     (save-excursion
       (goto-char (point-max))
@@ -8822,7 +8990,7 @@ If FORCE-TAGS is non nil, the car of it returns the new 
tags."
                   (equal m hdmarker))
          (setq props (text-properties-at (point))
                dotime (org-get-at-bol 'dotime)
-               cat (org-get-at-bol 'org-category)
+               cat (org-get-at-eol 'org-category 1)
                level (org-get-at-bol 'level)
                tags thetags
                new
@@ -8831,20 +8999,25 @@ If FORCE-TAGS is non nil, the car of it returns the new 
tags."
                           org-prefix-format-compiled))
                      (extra (org-get-at-bol 'extra)))
                  (with-current-buffer (marker-buffer hdmarker)
-                   (save-excursion
-                     (save-restriction
-                       (widen)
-                       (org-agenda-format-item extra newhead level cat tags 
dotime)))))
+                   (org-with-wide-buffer
+                    (org-agenda-format-item extra newhead level cat tags 
dotime))))
                pl (text-property-any (point-at-bol) (point-at-eol) 
'org-heading t)
                undone-face (org-get-at-bol 'undone-face)
                done-face (org-get-at-bol 'done-face))
          (beginning-of-line 1)
          (cond
-          ((equal new "")
-           (and (looking-at ".*\n?") (replace-match "")))
+          ((equal new "") (delete-region (point) (line-beginning-position 2)))
           ((looking-at ".*")
-           (replace-match new t t)
-           (beginning-of-line 1)
+           ;; When replacing the whole line, preserve bulk mark
+           ;; overlay, if any.
+           (let ((mark (catch :overlay
+                         (dolist (o (overlays-in (point) (+ 2 (point))))
+                           (when (eq (overlay-get o 'type)
+                                     'org-marked-entry-overlay)
+                             (throw :overlay o))))))
+             (replace-match new t t)
+             (beginning-of-line)
+             (when mark (move-overlay mark (point) (+ 2 (point)))))
            (add-text-properties (point-at-bol) (point-at-eol) props)
            (when fixface
              (add-text-properties
@@ -8865,7 +9038,7 @@ If FORCE-TAGS is non nil, the car of it returns the new 
tags."
   (let ((inhibit-read-only t) l c)
     (save-excursion
       (goto-char (if line (point-at-bol) (point-min)))
-      (while (re-search-forward (org-re "\\([ 
\t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$")
+      (while (re-search-forward "\\([ 
\t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"
                                (if line (point-at-eol) nil) t)
        (add-text-properties
         (match-beginning 2) (match-end 2)
@@ -8889,19 +9062,19 @@ If FORCE-TAGS is non nil, the car of it returns the new 
tags."
       (org-font-lock-add-tag-faces (point-max)))))
 
 (defun org-agenda-priority-up ()
-  "Increase the priority of line at point, also in Org-mode file."
+  "Increase the priority of line at point, also in Org file."
   (interactive)
   (org-agenda-priority 'up))
 
 (defun org-agenda-priority-down ()
-  "Decrease the priority of line at point, also in Org-mode file."
+  "Decrease the priority of line at point, also in Org file."
   (interactive)
   (org-agenda-priority 'down))
 
 (defun org-agenda-priority (&optional force-direction)
-  "Set the priority of line at point, also in Org-mode file.
+  "Set the priority of line at point, also in Org file.
 This changes the line at point, all other lines in the agenda referring to
-the same tree node, and the headline of the tree node in the Org-mode file.
+the same tree node, and the headline of the tree node in the Org file.
 Called with a universal prefix arg, show the priority instead of setting it."
   (interactive "P")
   (if (equal force-direction '(4))
@@ -8922,9 +9095,6 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
          (widen)
          (goto-char pos)
          (org-show-context 'agenda)
-         (save-excursion
-           (and (outline-next-heading)
-                (org-flag-heading nil)))   ; show the next heading
          (funcall 'org-priority force-direction)
          (end-of-line 1)
          (setq newhead (org-get-heading)))
@@ -8936,7 +9106,7 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
   "Set tags for the current headline."
   (interactive)
   (org-agenda-check-no-diary)
-  (if (and (org-region-active-p) (org-called-interactively-p 'any))
+  (if (and (org-region-active-p) (called-interactively-p 'any))
       (call-interactively 'org-change-tag-in-region)
     (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker)
                         (org-agenda-error)))
@@ -8948,12 +9118,7 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
        (with-current-buffer buffer
          (widen)
          (goto-char pos)
-         (save-excursion
-           (org-show-context 'agenda))
-         (save-excursion
-           (and (outline-next-heading)
-                (org-flag-heading nil)))   ; show the next heading
-         (goto-char pos)
+         (org-show-context 'agenda)
          (if tag
              (org-toggle-tag tag onoff)
            (call-interactively 'org-set-tags))
@@ -8976,12 +9141,7 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
       (with-current-buffer buffer
        (widen)
        (goto-char pos)
-       (save-excursion
-         (org-show-context 'agenda))
-       (save-excursion
-         (and (outline-next-heading)
-              (org-flag-heading nil)))   ; show the next heading
-       (goto-char pos)
+       (org-show-context 'agenda)
        (call-interactively 'org-set-property)))))
 
 (defun org-agenda-set-effort ()
@@ -8998,12 +9158,7 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
       (with-current-buffer buffer
        (widen)
        (goto-char pos)
-       (save-excursion
-         (org-show-context 'agenda))
-       (save-excursion
-         (and (outline-next-heading)
-              (org-flag-heading nil))) ; show the next heading
-       (goto-char pos)
+       (org-show-context 'agenda)
        (call-interactively 'org-set-effort)
        (end-of-line 1)
        (setq newhead (org-get-heading)))
@@ -9024,9 +9179,6 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
        (widen)
        (goto-char pos)
        (org-show-context 'agenda)
-       (save-excursion
-         (and (outline-next-heading)
-              (org-flag-heading nil)))   ; show the next heading
        (call-interactively 'org-toggle-archive-tag)
        (end-of-line 1)
        (setq newhead (org-get-heading)))
@@ -9140,18 +9292,10 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
        (when (equal marker (org-get-at-bol 'org-marker))
          (remove-text-properties (point-at-bol) (point-at-eol) '(display))
          (org-move-to-column (- (window-width) (length stamp)) t)
-          (if (featurep 'xemacs)
-             ;; Use `duplicable' property to trigger undo recording
-              (let ((ex (make-extent nil nil))
-                    (gl (make-glyph stamp)))
-                (set-glyph-face gl 'secondary-selection)
-                (set-extent-properties
-                 ex (list 'invisible t 'end-glyph gl 'duplicable t))
-                (insert-extent ex (1- (point)) (point-at-eol)))
-            (add-text-properties
-            (1- (point)) (point-at-eol)
-            (list 'display (org-add-props stamp nil
-                             'face '(secondary-selection default)))))
+          (add-text-properties
+          (1- (point)) (point-at-eol)
+          (list 'display (org-add-props stamp nil
+                           'face '(secondary-selection default))))
          (beginning-of-line 1))
        (beginning-of-line 0)))))
 
@@ -9187,7 +9331,6 @@ ARG is passed through to `org-schedule'."
         (type (marker-insertion-type marker))
         (buffer (marker-buffer marker))
         (pos (marker-position marker))
-        (org-insert-labeled-timestamps-at-point nil)
         ts)
     (set-marker-insertion-type marker t)
     (org-with-remote-undo buffer
@@ -9208,7 +9351,6 @@ ARG is passed through to `org-deadline'."
                     (org-agenda-error)))
         (buffer (marker-buffer marker))
         (pos (marker-position marker))
-        (org-insert-labeled-timestamps-at-point nil)
         ts)
     (org-with-remote-undo buffer
       (with-current-buffer buffer
@@ -9235,7 +9377,6 @@ ARG is passed through to `org-deadline'."
          (widen)
          (goto-char pos)
          (org-show-context 'agenda)
-         (org-show-entry)
          (org-cycle-hide-drawers 'children)
          (org-clock-in arg)
          (setq newhead (org-get-heading)))
@@ -9250,14 +9391,12 @@ ARG is passed through to `org-deadline'."
   (let ((marker (make-marker)) (col (current-column)) newhead)
     (org-with-remote-undo (marker-buffer org-clock-marker)
       (with-current-buffer (marker-buffer org-clock-marker)
-       (save-excursion
-         (save-restriction
-           (widen)
-           (goto-char org-clock-marker)
-           (org-back-to-heading t)
-           (move-marker marker (point))
-           (org-clock-out)
-           (setq newhead (org-get-heading))))))
+       (org-with-wide-buffer
+        (goto-char org-clock-marker)
+        (org-back-to-heading t)
+        (move-marker marker (point))
+        (org-clock-out)
+        (setq newhead (org-get-heading)))))
     (org-agenda-change-all-lines newhead marker)
     (move-marker marker nil)
     (org-move-to-column col)
@@ -9284,7 +9423,7 @@ buffer, display it in another window."
     (cond (pos (goto-char pos))
          ;; If the currently clocked entry is not in the agenda
          ;; buffer, we visit it in another window:
-         (org-clock-current-task
+         ((bound-and-true-p org-clock-current-task)
           (org-switch-to-buffer-other-window (org-clock-goto)))
          (t (message "No running clock, use `C-c C-x C-j' to jump to the most 
recent one")))))
 
@@ -9334,11 +9473,13 @@ buffer, display it in another window."
   "Where in `org-agenda-diary-file' should new entries be added?
 Valid values:
 
-date-tree    in the date tree, as child of the date
-top-level    as top-level entries at the end of the file."
+date-tree         in the date tree, as first child of the date
+date-tree-last    in the date tree, as last child of the date
+top-level         as top-level entries at the end of the file."
   :group 'org-agenda
   :type '(choice
-         (const :tag "in a date tree" date-tree)
+         (const :tag "first in a date tree" date-tree)
+         (const :tag "last in a date tree" date-tree-last)
          (const :tag "as top level at end of file" top-level)))
 
 (defcustom org-agenda-insert-diary-extract-time nil
@@ -9434,40 +9575,43 @@ Add TEXT as headline, and position the cursor in the 
second line so that
 a timestamp can be added there."
   (widen)
   (goto-char (point-max))
-  (or (bolp) (insert "\n"))
-  (insert "* " text "\n")
-  (if org-adapt-indentation (org-indent-to-column 2)))
+  (unless (bolp) (insert "\n"))
+  (org-insert-heading nil t t)
+  (insert text)
+  (org-end-of-meta-data)
+  (unless (bolp) (insert "\n"))
+  (when org-adapt-indentation (indent-to-column 2)))
 
 (defun org-agenda-insert-diary-make-new-entry (text)
-  "Make a new entry with TEXT as the first child of the current subtree.
-Position the point in the line right after the new heading so
-that a timestamp can be added there."
-  (let ((org-show-following-heading t)
-       (org-show-siblings t)
-       (org-show-hierarchy-above t)
-       (org-show-entry-below t)
-       col)
+  "Make a new entry with TEXT as a child of the current subtree.
+Position the point in the heading's first body line so that
+a timestamp can be added there."
+  (cond
+   ((eq org-agenda-insert-diary-strategy 'date-tree-last)
+    (end-of-line)
+    (org-insert-heading '(4) t)
+    (org-do-demote))
+   (t
     (outline-next-heading)
     (org-back-over-empty-lines)
-    (or (looking-at "[ \t]*$")
-       (progn (insert "\n") (backward-char 1)))
+    (unless (looking-at "[ \t]*$") (save-excursion (insert "\n")))
     (org-insert-heading nil t)
-    (org-do-demote)
-    (setq col (current-column))
-    (insert text "\n")
-    (if org-adapt-indentation (org-indent-to-column col))
-    (let ((org-show-following-heading t)
-         (org-show-siblings t)
-         (org-show-hierarchy-above t)
-         (org-show-entry-below t))
-      (org-show-context))))
+    (org-do-demote)))
+  (let ((col (current-column)))
+    (insert text)
+    (org-end-of-meta-data)
+    ;; Ensure point is left on a blank line, at proper indentation.
+    (unless (bolp) (insert "\n"))
+    (unless (looking-at-p "^[ \t]*$") (save-excursion (insert "\n")))
+    (when org-adapt-indentation (indent-to-column col)))
+  (org-show-set-visibility 'lineage))
 
 (defun org-agenda-diary-entry ()
   "Make a diary entry, like the `i' command from the calendar.
 All the standard commands work: block, weekly etc.
 When `org-agenda-diary-file' points to a file,
 `org-agenda-diary-entry-in-org-file' is called instead to create
-entries in that Org-mode file."
+entries in that Org file."
   (interactive)
   (if (not (eq org-agenda-diary-file 'diary-file))
       (org-agenda-diary-entry-in-org-file)
@@ -9476,13 +9620,13 @@ entries in that Org-mode file."
                   (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early 
[a]nniversary [b]lock [c]yclic")
                   (read-char-exclusive)))
           (cmd (cdr (assoc char
-                           '((?d . insert-diary-entry)
-                             (?w . insert-weekly-diary-entry)
-                             (?m . insert-monthly-diary-entry)
-                             (?y . insert-yearly-diary-entry)
-                             (?a . insert-anniversary-diary-entry)
-                             (?b . insert-block-diary-entry)
-                             (?c . insert-cyclic-diary-entry)))))
+                           '((?d . diary-insert-entry)
+                             (?w . diary-insert-weekly-entry)
+                             (?m . diary-insert-monthly-entry)
+                             (?y . diary-insert-yearly-entry)
+                             (?a . diary-insert-anniversary-entry)
+                             (?b . diary-insert-block-entry)
+                             (?c . diary-insert-cyclic-entry)))))
           (oldf (symbol-function 'calendar-cursor-to-date))
           ;; (buf (get-file-buffer (substitute-in-file-name diary-file)))
           (point (point))
@@ -9538,7 +9682,7 @@ entries in that Org-mode file."
 (defun org-agenda-holidays ()
   "Display the holidays for the 3 months around the cursor date."
   (interactive)
-  (org-agenda-execute-calendar-command 'list-calendar-holidays))
+  (org-agenda-execute-calendar-command 'calendar-list-holidays))
 
 (defvar calendar-longitude)      ; defined in calendar.el
 (defvar calendar-latitude)       ; defined in calendar.el
@@ -9572,12 +9716,16 @@ argument, latitude and longitude will be prompted for."
 
 ;;;###autoload
 (defun org-calendar-goto-agenda ()
-  "Compute the Org-mode agenda for the calendar date displayed at the cursor.
+  "Compute the Org agenda for the calendar date displayed at the cursor.
 This is a command that has to be installed in `calendar-mode-map'."
   (interactive)
-  (org-agenda-list nil (calendar-absolute-from-gregorian
-                       (calendar-cursor-to-date))
-                  nil))
+  ;; Temporarily disable sticky agenda since user clearly wants to
+  ;; refresh view anyway.
+  (let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*")
+       (org-agenda-sticky nil))
+    (org-agenda-list nil (calendar-absolute-from-gregorian
+                         (calendar-cursor-to-date))
+                    nil)))
 
 (defun org-agenda-convert-date ()
   (interactive)
@@ -9610,6 +9758,7 @@ This is a command that has to be installed in 
`calendar-mode-map'."
 ;;; Bulk commands
 
 (defun org-agenda-bulk-marked-p ()
+  "Non-nil when current entry is marked for bulk action."
   (eq (get-char-property (point-at-bol) 'type)
       'org-marked-entry-overlay))
 
@@ -9651,9 +9800,12 @@ This is a command that has to be installed in 
`calendar-mode-map'."
       (goto-char (next-single-property-change (point) 'org-hd-marker))
       (while (and (re-search-forward regexp nil t)
                  (setq txt-at-point (get-text-property (point) 'txt)))
-       (when (string-match regexp txt-at-point)
-         (setq entries-marked (1+ entries-marked))
-         (call-interactively 'org-agenda-bulk-mark))))
+       (if (get-char-property (point) 'invisible)
+           (beginning-of-line 2)
+         (when (string-match regexp txt-at-point)
+           (setq entries-marked (1+ entries-marked))
+           (call-interactively 'org-agenda-bulk-mark)))))
+
     (if (not entries-marked)
        (message "No entry matching this regexp."))))
 
@@ -9712,7 +9864,6 @@ This will remove the markers and the overlays."
   (interactive)
   (if (null org-agenda-bulk-marked-entries)
       (message "No entry to unmark")
-    (mapc (lambda (m) (move-marker m nil)) org-agenda-bulk-marked-entries)
     (setq org-agenda-bulk-marked-entries nil)
     (org-agenda-bulk-remove-overlays (point-min) (point-max))))
 
@@ -9786,21 +9937,21 @@ The prefix arg is passed through to the command if 
possible."
                redo-at-end t))
 
         ((equal action ?t)
-         (setq state (org-icompleting-read
+         (setq state (completing-read
                       "Todo state: "
                       (with-current-buffer (marker-buffer (car entries))
-                        (mapcar 'list org-todo-keywords-1))))
+                        (mapcar #'list org-todo-keywords-1))))
          (setq cmd `(let ((org-inhibit-blocking t)
                           (org-inhibit-logging 'note))
                       (org-agenda-todo ,state))))
 
         ((memq action '(?- ?+))
-         (setq tag (org-icompleting-read
+         (setq tag (completing-read
                     (format "Tag to %s: " (if (eq action ?+) "add" "remove"))
                     (with-current-buffer (marker-buffer (car entries))
                       (delq nil
-                            (mapcar (lambda (x)
-                                      (if (stringp (car x)) x)) 
org-tag-alist)))))
+                            (mapcar (lambda (x) (and (stringp (car x)) x))
+                                    org-current-tag-alist)))))
          (setq cmd `(org-agenda-set-tags ,tag ,(if (eq action ?+) ''on 
''off))))
 
         ((memq action '(?s ?d))
@@ -9810,8 +9961,17 @@ The prefix arg is passed through to the command if 
possible."
                     nil nil nil
                     (if (eq action ?s) "(Re)Schedule to" "(Re)Set Deadline to")
                     org-overriding-default-time)))
-                (c1 (if (eq action ?s) 'org-agenda-schedule 
'org-agenda-deadline)))
-           (setq cmd `(eval '(,c1 arg ,time)))))
+                (c1 (if (eq action ?s) 'org-agenda-schedule
+                      'org-agenda-deadline)))
+           ;; Make sure to not prompt for a note when bulk
+           ;; rescheduling as Org cannot cope with simultaneous
+           ;; notes.  Besides, it could be annoying depending on the
+           ;; number of items re-scheduled.
+           (setq cmd `(eval '(let ((org-log-reschedule
+                                    (and org-log-reschedule 'time))
+                                   (org-log-redeadline
+                                    (and org-log-redeadline 'time)))
+                               (,c1 arg ,time))))))
 
         ((equal action ?S)
          (if (not (org-agenda-check-type nil 'agenda 'timeline 'todo))
@@ -9828,13 +9988,13 @@ The prefix arg is passed through to the command if 
possible."
                                   (calendar-gregorian-from-absolute 
(org-today)))))
                             (dotimes (i (1+ dist))
                               (while (member day-of-week 
org-agenda-weekend-days)
-                                (incf distance)
-                                (incf day-of-week)
-                                (if (= day-of-week 7)
-                                    (setq day-of-week 0)))
-                              (incf day-of-week)
-                              (if (= day-of-week 7)
-                                  (setq day-of-week 0)))))
+                                (cl-incf distance)
+                                (cl-incf day-of-week)
+                                (when (= day-of-week 7)
+                                  (setq day-of-week 0)))
+                              (cl-incf day-of-week)
+                              (when (= day-of-week 7)
+                                (setq day-of-week 0)))))
                       ;; silently fail when try to replan a sexp entry
                       (condition-case nil
                           (let* ((date (calendar-gregorian-from-absolute
@@ -9850,8 +10010,8 @@ The prefix arg is passed through to the command if 
possible."
 
         ((equal action ?f)
          (setq cmd (list (intern
-                          (org-icompleting-read "Function: "
-                                                obarray 'fboundp t nil nil)))))
+                          (completing-read "Function: "
+                                           obarray 'fboundp t nil nil)))))
 
         (t (user-error "Invalid bulk action")))
 
@@ -9874,6 +10034,11 @@ The prefix arg is passed through to the command if 
possible."
            (goto-char pos)
            (let (org-loop-over-headlines-in-active-region)
              (eval cmd))
+           ;; `post-command-hook' is not run yet.  We make sure any
+           ;; pending log note is processed.
+           (when (or (memq 'org-add-log-note (default-value 
'post-command-hook))
+                     (memq 'org-add-log-note post-command-hook))
+             (org-add-log-note))
            (setq cnt (1+ cnt))))
        (when redo-at-end (org-agenda-redo))
        (unless org-agenda-persistent-marks
@@ -9903,12 +10068,14 @@ current HH:MM time."
 (defun org-agenda-reapply-filters ()
   "Re-apply all agenda filters."
   (mapcar
-   (lambda(f) (when (car f) (org-agenda-filter-apply (car f) (cadr f))))
+   (lambda(f) (when (car f) (org-agenda-filter-apply (car f) (cadr f) t)))
    `((,org-agenda-tag-filter tag)
      (,org-agenda-category-filter category)
      (,org-agenda-regexp-filter regexp)
+     (,org-agenda-effort-filter effort)
      (,(get 'org-agenda-tag-filter :preset-filter) tag)
      (,(get 'org-agenda-category-filter :preset-filter) category)
+     (,(get 'org-agenda-effort-filter :preset-filter) effort)
      (,(get 'org-agenda-regexp-filter :preset-filter) regexp))))
 
 (defun org-agenda-drag-line-forward (arg &optional backward)
@@ -9969,7 +10136,9 @@ tag and (if present) the flagging note."
        (replace-match "\n" t t))
       (goto-char (point-min))
       (select-window win)
-      (message "Flagging note pushed to kill ring.  Press [?] again to remove 
tag and note"))))
+      (message "%s" (substitute-command-keys "Flagging note pushed to \
+kill ring.  Press `\\[org-agenda-show-the-flagging-note]' again to remove \
+tag and note")))))
 
 (defun org-agenda-remove-flag (marker)
   "Remove the FLAGGED tag and any flagging note in the entry."
@@ -9992,7 +10161,8 @@ tag and (if present) the flagging note."
 ;;;###autoload
 (defun org-agenda-to-appt (&optional refresh filter &rest args)
   "Activate appointments found in `org-agenda-files'.
-With a \\[universal-argument] prefix, refresh the list of
+
+With a `\\[universal-argument]' prefix, refresh the list of \
 appointments.
 
 If FILTER is t, interactively prompt the user for a regular
@@ -10008,8 +10178,8 @@ argument: an entry from `org-agenda-get-day-entries'.
 FILTER can also be an alist with the car of each cell being
 either `headline' or `category'.  For example:
 
-  ((headline \"IMPORTANT\")
-   (category \"Work\"))
+  \\='((headline \"IMPORTANT\")
+    (category \"Work\"))
 
 will only add headlines containing IMPORTANT or headlines
 belonging to the \"Work\" category.
@@ -10026,75 +10196,78 @@ to override `appt-message-warning-time'."
   (if refresh (setq appt-time-msg-list nil))
   (if (eq filter t)
       (setq filter (read-from-minibuffer "Regexp filter: ")))
-  (let* ((cnt 0) ; count added events
-        (scope (or args '(:deadline* :scheduled* :timestamp)))
-        (org-agenda-new-buffers nil)
-        (org-deadline-warning-days 0)
-        ;; Do not use `org-today' here because appt only takes
-        ;; time and without date as argument, so it may pass wrong
-        ;; information otherwise
-        (today (org-date-to-gregorian
-                (time-to-days (current-time))))
-        (org-agenda-restrict nil)
-        (files (org-agenda-files 'unrestricted)) entries file
-        (org-agenda-buffer nil))
+  (let* ((cnt 0)                        ; count added events
+         (scope (or args '(:deadline* :scheduled* :timestamp)))
+         (org-agenda-new-buffers nil)
+         (org-deadline-warning-days 0)
+         ;; Do not use `org-today' here because appt only takes
+         ;; time and without date as argument, so it may pass wrong
+         ;; information otherwise
+         (today (org-date-to-gregorian
+                 (time-to-days (current-time))))
+         (org-agenda-restrict nil)
+         (files (org-agenda-files 'unrestricted)) entries file
+         (org-agenda-buffer nil))
     ;; Get all entries which may contain an appt
     (org-agenda-prepare-buffers files)
     (while (setq file (pop files))
       (setq entries
-           (delq nil
-                 (append entries
-                         (apply 'org-agenda-get-day-entries
-                                file today scope)))))
+            (delq nil
+                  (append entries
+                          (apply 'org-agenda-get-day-entries
+                                 file today scope)))))
     ;; Map thru entries and find if we should filter them out
     (mapc
-     (lambda(x)
+     (lambda (x)
        (let* ((evt (org-trim
-                   (replace-regexp-in-string
-                    org-bracket-link-regexp "\\3"
-                    (or (get-text-property 1 'txt x) ""))))
-             (cat (get-text-property 1 'org-category x))
-             (tod (get-text-property 1 'time-of-day x))
-             (ok (or (null filter)
-                     (and (stringp filter) (string-match filter evt))
-                     (and (functionp filter) (funcall filter x))
-                     (and (listp filter)
-                          (let ((cat-filter (cadr (assoc 'category filter)))
-                                (evt-filter (cadr (assoc 'headline filter))))
-                            (or (and (stringp cat-filter)
-                                     (string-match cat-filter cat))
-                                (and (stringp evt-filter)
-                                     (string-match evt-filter evt)))))))
-             (wrn (get-text-property 1 'warntime x)))
-        ;; FIXME: Shall we remove text-properties for the appt text?
-        ;; (setq evt (set-text-properties 0 (length evt) nil evt))
-        (when (and ok tod)
-          (setq tod (concat "00" (number-to-string tod))
-                tod (when (string-match
-                           "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)\\'" tod)
-                      (concat (match-string 1 tod) ":"
-                              (match-string 2 tod))))
-          (if (version< emacs-version "23.3")
-              (appt-add tod evt)
-            (appt-add tod evt wrn))
-          (setq cnt (1+ cnt))))) entries)
+                    (replace-regexp-in-string
+                     org-bracket-link-regexp "\\3"
+                     (or (get-text-property 1 'txt x) ""))))
+              (cat (get-text-property (1- (length x)) 'org-category x))
+              (tod (get-text-property 1 'time-of-day x))
+              (ok (or (null filter)
+                      (and (stringp filter) (string-match filter evt))
+                      (and (functionp filter) (funcall filter x))
+                      (and (listp filter)
+                           (let ((cat-filter (cadr (assq 'category filter)))
+                                 (evt-filter (cadr (assq 'headline filter))))
+                             (or (and (stringp cat-filter)
+                                      (string-match cat-filter cat))
+                                 (and (stringp evt-filter)
+                                      (string-match evt-filter evt)))))))
+              (wrn (get-text-property 1 'warntime x)))
+         ;; FIXME: Shall we remove text-properties for the appt text?
+         ;; (setq evt (set-text-properties 0 (length evt) nil evt))
+         (when (and ok tod (not (string-match "\\`DONE\\|CANCELLED" evt)))
+           (setq tod (concat "00" (number-to-string tod)))
+           (setq tod (when (string-match
+                            "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)\\'" tod)
+                       (concat (match-string 1 tod) ":"
+                               (match-string 2 tod))))
+           (when (if (version< emacs-version "23.3")
+                     (appt-add tod evt)
+                   (appt-add tod evt wrn))
+             (setq cnt (1+ cnt))))))
+     entries)
     (org-release-buffers org-agenda-new-buffers)
     (if (eq cnt 0)
-       (message "No event to add")
+        (message "No event to add")
       (message "Added %d event%s for today" cnt (if (> cnt 1) "s" "")))))
 
-(defun org-agenda-todayp (date)
-  "Does DATE mean today, when considering `org-extend-today-until'?"
-  (let ((today (org-today))
-       (date (if (and date (listp date)) (calendar-absolute-from-gregorian 
date)
-               date)))
-    (eq date today)))
+(defun org-agenda-today-p (date)
+  "Non nil when DATE means today.
+DATE is either a list of the form (month day year) or a number of
+days as returned by `calendar-absolute-from-gregorian' or
+`org-today'.  This function considers `org-extend-today-until'
+when defining today."
+  (eq (org-today)
+      (if (consp date) (calendar-absolute-from-gregorian date) date)))
 
 (defun org-agenda-todo-yesterday (&optional arg)
   "Like `org-agenda-todo' but the time of change will be 23:59 of yesterday."
   (interactive "P")
-  (let* ((hour (third (decode-time
-                       (org-current-time))))
+  (let* ((org-use-effective-time t)
+        (hour (nth 2 (decode-time (org-current-time))))
          (org-extend-today-until (1+ hour)))
     (org-agenda-todo arg)))
 
diff --git a/lisp/org/org-archive.el b/lisp/org/org-archive.el
index 39a6581..ce1f35d 100644
--- a/lisp/org/org-archive.el
+++ b/lisp/org/org-archive.el
@@ -1,4 +1,4 @@
-;;; org-archive.el --- Archiving for Org-mode
+;;; org-archive.el --- Archiving for Org             -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -29,10 +29,10 @@
 ;;; Code:
 
 (require 'org)
-(eval-when-compile (require 'cl))
 
-(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
+(declare-function org-element-type "org-element" (element))
 (declare-function org-datetree-find-date-create "org-datetree" (date &optional 
keep-restriction))
+(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
 
 (defcustom org-archive-default-command 'org-archive-subtree
   "The default archiving command."
@@ -57,7 +57,7 @@ See `org-archive-to-archive-sibling' for more information."
 
 (defcustom org-archive-mark-done nil
   "Non-nil means mark entries as DONE when they are moved to the archive file.
-This can be a string to set the keyword to use.  When t, Org-mode will
+This can be a string to set the keyword to use.  When non-nil, Org will
 use the first keyword in its list that means done."
   :group 'org-archive
   :type '(choice
@@ -120,9 +120,15 @@ information."
              (const :tag "Outline path" olpath)
              (const :tag "Local tags" ltags)))
 
+(defvar org-archive-hook nil
+  "Hook run after successfully archiving a subtree.
+Hook functions are called with point on the subtree in the
+original file.  At this stage, the subtree has been added to the
+archive location, but not yet deleted from the original file.")
+
 (defun org-get-local-archive-location ()
   "Get the archive location applicable at point."
-  (let ((re "^#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$")
+  (let ((re "^[ \t]*#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$")
        prop)
     (save-excursion
       (save-restriction
@@ -154,21 +160,24 @@ archive file is."
 
 (defun org-all-archive-files ()
   "Get a list of all archive files used in the current buffer."
-  (let (file files)
-    (save-excursion
-      (save-restriction
-       (goto-char (point-min))
-       (while (re-search-forward
-               "^\\(#\\+\\|[ \t]*:\\)ARCHIVE:[ \t]+\\(.*\\)"
-               nil t)
-         (setq file (org-extract-archive-file
-                     (org-match-string-no-properties 2)))
-         (and file (> (length file) 0) (file-exists-p file)
-              (pushnew file files :test #'equal)))))
+  (let ((case-fold-search t)
+       files)
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (while (re-search-forward
+            "^[ \t]*\\(#\\+\\|:\\)ARCHIVE:[ \t]+\\(.*\\)"
+            nil t)
+       (when (save-match-data
+              (if (eq (match-string 1) ":") (org-at-property-p)
+                (eq (org-element-type (org-element-at-point)) 'keyword)))
+        (let ((file (org-extract-archive-file
+                     (match-string-no-properties 2))))
+          (when (and (org-string-nw-p file) (file-exists-p file))
+            (push file files))))))
     (setq files (nreverse files))
-    (setq file (org-extract-archive-file))
-    (and file (> (length file) 0) (file-exists-p file)
-        (pushnew file files :test #'equal))
+    (let ((file (org-extract-archive-file)))
+      (when (and (org-string-nw-p file) (file-exists-p file))
+       (push file files)))
     files))
 
 (defun org-extract-archive-file (&optional location)
@@ -195,15 +204,19 @@ if LOCATION is not given, the value of 
`org-archive-location' is used."
 ;;;###autoload
 (defun org-archive-subtree (&optional find-done)
   "Move the current subtree to the archive.
-The archive can be a certain top-level heading in the current file, or in
-a different file.  The tree will be moved to that location, the subtree
-heading be marked DONE, and the current time will be added.
-
-When called with prefix argument FIND-DONE, find whole trees without any
-open TODO items and archive them (after getting confirmation from the user).
-If the cursor is not at a headline when this command is called, try all level
-1 trees.  If the cursor is on a headline, only try the direct children of
-this heading."
+The archive can be a certain top-level heading in the current
+file, or in a different file.  The tree will be moved to that
+location, the subtree heading be marked DONE, and the current
+time will be added.
+
+When called with a single prefix argument FIND-DONE, find whole
+trees without any open TODO items and archive them (after getting
+confirmation from the user).  When called with a double prefix
+argument, find whole trees with timestamps before today and
+archive them (after getting confirmation from the user).  If the
+cursor is not at a headline when these commands are called, try
+all level 1 trees.  If the cursor is on a headline, only try the
+direct children of this heading."
   (interactive "P")
   (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
       (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
@@ -213,46 +226,36 @@ this heading."
         `(progn (setq org-map-continue-from (progn (org-back-to-heading) 
(point)))
                 (org-archive-subtree ,find-done))
         org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
-    (if find-done
-       (org-archive-all-done)
+        cl (if (org-invisible-p) (org-end-of-subtree nil t))))
+    (cond
+     ((equal find-done '(4))  (org-archive-all-done))
+     ((equal find-done '(16)) (org-archive-all-old))
+     (t
       ;; Save all relevant TODO keyword-relatex variables
-      (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite 
compiler
-           (tr-org-todo-keywords-1 org-todo-keywords-1)
-           (tr-org-todo-kwd-alist org-todo-kwd-alist)
-           (tr-org-done-keywords org-done-keywords)
-           (tr-org-todo-regexp org-todo-regexp)
-           (tr-org-todo-line-regexp org-todo-line-regexp)
-           (tr-org-odd-levels-only org-odd-levels-only)
-           (this-buffer (current-buffer))
-           ;; start of variables that will be used for saving context
-           ;; The compiler complains about them - keep them anyway!
-           (file (abbreviate-file-name
-                  (or (buffer-file-name (buffer-base-buffer))
-                      (error "No file associated to buffer"))))
-           (olpath (mapconcat 'identity (org-get-outline-path) "/"))
-           (time (format-time-string
-                  (substring (cdr org-time-stamp-formats) 1 -1)))
-           category todo priority ltags itags atags
-           ;; end of variables that will be used for saving context
-           location afile heading buffer level newfile-p infile-p visiting
-           datetree-date datetree-subheading-p)
-
-       ;; Find the local archive location
-       (setq location (org-get-local-archive-location)
-             afile (org-extract-archive-file location)
-             heading (org-extract-archive-heading location)
-             infile-p (equal file (abbreviate-file-name (or afile ""))))
-       (unless afile
-         (error "Invalid `org-archive-location'"))
-
-       (if (> (length afile) 0)
-           (setq newfile-p (not (file-exists-p afile))
-                 visiting (find-buffer-visiting afile)
-                 buffer (or visiting (find-file-noselect afile)))
-         (setq buffer (current-buffer)))
-       (unless buffer
-         (error "Cannot access file \"%s\"" afile))
+      (let* ((tr-org-todo-keywords-1 org-todo-keywords-1)
+            (tr-org-todo-kwd-alist org-todo-kwd-alist)
+            (tr-org-done-keywords org-done-keywords)
+            (tr-org-todo-regexp org-todo-regexp)
+            (tr-org-todo-line-regexp org-todo-line-regexp)
+            (tr-org-odd-levels-only org-odd-levels-only)
+            (this-buffer (current-buffer))
+            (time (format-time-string
+                   (substring (cdr org-time-stamp-formats) 1 -1)))
+            (file (abbreviate-file-name
+                   (or (buffer-file-name (buffer-base-buffer))
+                       (error "No file associated to buffer"))))
+            (location (org-get-local-archive-location))
+            (afile (or (org-extract-archive-file location)
+                       (error "Invalid `org-archive-location'")))
+            (heading (org-extract-archive-heading location))
+            (infile-p (equal file (abbreviate-file-name (or afile ""))))
+            (newfile-p (and (org-string-nw-p afile)
+                            (not (file-exists-p afile))))
+            (buffer (cond ((not (org-string-nw-p afile)) this-buffer)
+                          ((find-buffer-visiting afile))
+                          ((find-file-noselect afile))
+                          (t (error "Cannot access file \"%s\"" afile))))
+            level datetree-date datetree-subheading-p)
        (when (string-match "\\`datetree/" heading)
          ;; Replace with ***, to represent the 3 levels of headings the
          ;; datetree has.
@@ -266,108 +269,120 @@ this heading."
          (setq heading nil level 0))
        (save-excursion
          (org-back-to-heading t)
-         ;; Get context information that will be lost by moving the tree
-         (setq category (org-get-category nil 'force-refresh)
-               todo (and (looking-at org-todo-line-regexp)
-                         (match-string 2))
-               priority (org-get-priority
-                         (if (match-end 3) (match-string 3) ""))
-               ltags (org-get-tags)
-               itags (org-delete-all ltags (org-get-tags-at))
-               atags (org-get-tags-at))
-         (setq ltags (mapconcat 'identity ltags " ")
-               itags (mapconcat 'identity itags " "))
-         ;; We first only copy, in case something goes wrong
-         ;; we need to protect `this-command', to avoid kill-region sets it,
-         ;; which would lead to duplication of subtrees
-         (let (this-command) (org-copy-subtree 1 nil t))
-         (set-buffer buffer)
-         ;; Enforce org-mode for the archive buffer
-         (if (not (derived-mode-p 'org-mode))
-             ;; Force the mode for future visits.
-             (let ((org-insert-mode-line-in-empty-file t)
-                   (org-inhibit-startup t))
-               (call-interactively 'org-mode)))
-         (when (and newfile-p org-archive-file-header-format)
-           (goto-char (point-max))
-           (insert (format org-archive-file-header-format
-                           (buffer-file-name this-buffer))))
-         (when datetree-date
-           (require 'org-datetree)
-           (org-datetree-find-date-create datetree-date)
-           (org-narrow-to-subtree))
-         ;; Force the TODO keywords of the original buffer
-         (let ((org-todo-line-regexp tr-org-todo-line-regexp)
-               (org-todo-keywords-1 tr-org-todo-keywords-1)
-               (org-todo-kwd-alist tr-org-todo-kwd-alist)
-               (org-done-keywords tr-org-done-keywords)
-               (org-todo-regexp tr-org-todo-regexp)
-               (org-todo-line-regexp tr-org-todo-line-regexp)
-               (org-odd-levels-only
-                (if (local-variable-p 'org-odd-levels-only (current-buffer))
-                    org-odd-levels-only
-                  tr-org-odd-levels-only)))
-           (goto-char (point-min))
-           (show-all)
-           (if (and heading (not (and datetree-date (not 
datetree-subheading-p))))
-               (progn
-                 (if (re-search-forward
-                      (concat "^" (regexp-quote heading)
-                              (org-re "[ 
\t]*\\(:[[:alnum:address@hidden:]+:\\)?[ \t]*\\($\\|\r\\)"))
-                      nil t)
-                     (goto-char (match-end 0))
-                   ;; Heading not found, just insert it at the end
-                   (goto-char (point-max))
-                   (or (bolp) (insert "\n"))
-                   ;; datetrees don't need too much spacing
-                   (insert (if datetree-date "" "\n") heading "\n")
-                   (end-of-line 0))
-                 ;; Make the subtree visible
-                 (show-subtree)
-                 (if org-archive-reversed-order
-                     (progn
-                       (org-back-to-heading t)
-                       (outline-next-heading))
-                   (org-end-of-subtree t))
-                 (skip-chars-backward " \t\r\n")
-                 (and (looking-at "[ \t\r\n]*")
-                      ;; datetree archives don't need so much spacing.
-                      (replace-match (if datetree-date "\n" "\n\n"))))
-             ;; No specific heading, just go to end of file.
-             (goto-char (point-max)) (unless datetree-date (insert "\n")))
-           ;; Paste
-           (org-paste-subtree (org-get-valid-level level (and heading 1)))
-           ;; Shall we append inherited tags?
-           (and itags
-                (or (and (eq org-archive-subtree-add-inherited-tags 'infile)
-                         infile-p)
-                    (eq org-archive-subtree-add-inherited-tags t))
-                (org-set-tags-to atags))
-           ;; Mark the entry as done
-           (when (and org-archive-mark-done
-                      (looking-at org-todo-line-regexp)
-                      (or (not (match-end 2))
-                          (not (member (match-string 2) org-done-keywords))))
-             (let (org-log-done org-todo-log-states)
-               (org-todo
-                (car (or (member org-archive-mark-done org-done-keywords)
-                         org-done-keywords)))))
-
-           ;; Add the context info
-           (when org-archive-save-context-info
-             (let ((l org-archive-save-context-info) e n v)
-               (while (setq e (pop l))
-                 (when (and (setq v (symbol-value e))
-                            (stringp v) (string-match "\\S-" v))
-                   (setq n (concat "ARCHIVE_" (upcase (symbol-name e))))
-                   (org-entry-put (point) n v)))))
-
-           (widen)
-           ;; Save and kill the buffer, if it is not the same buffer.
-           (when (not (eq this-buffer buffer))
-             (save-buffer))))
-       ;; Here we are back in the original buffer.  Everything seems to have
-       ;; worked.  So now cut the tree and finish up.
+         ;; Get context information that will be lost by moving the
+         ;; tree.  See `org-archive-save-context-info'.
+         (let* ((all-tags (org-get-tags-at))
+                (local-tags (org-get-tags))
+                (inherited-tags (org-delete-all local-tags all-tags))
+                (context
+                 `((category . ,(org-get-category nil 'force-refresh))
+                   (file . ,file)
+                   (itags . ,(mapconcat #'identity inherited-tags " "))
+                   (ltags . ,(mapconcat #'identity local-tags " "))
+                   (olpath . ,(mapconcat #'identity
+                                         (org-get-outline-path)
+                                         "/"))
+                   (time . ,time)
+                   (todo . ,(org-entry-get (point) "TODO")))))
+           ;; We first only copy, in case something goes wrong
+           ;; we need to protect `this-command', to avoid kill-region sets it,
+           ;; which would lead to duplication of subtrees
+           (let (this-command) (org-copy-subtree 1 nil t))
+           (set-buffer buffer)
+           ;; Enforce Org mode for the archive buffer
+           (if (not (derived-mode-p 'org-mode))
+               ;; Force the mode for future visits.
+               (let ((org-insert-mode-line-in-empty-file t)
+                     (org-inhibit-startup t))
+                 (call-interactively 'org-mode)))
+           (when (and newfile-p org-archive-file-header-format)
+             (goto-char (point-max))
+             (insert (format org-archive-file-header-format
+                             (buffer-file-name this-buffer))))
+           (when datetree-date
+             (require 'org-datetree)
+             (org-datetree-find-date-create datetree-date)
+             (org-narrow-to-subtree))
+           ;; Force the TODO keywords of the original buffer
+           (let ((org-todo-line-regexp tr-org-todo-line-regexp)
+                 (org-todo-keywords-1 tr-org-todo-keywords-1)
+                 (org-todo-kwd-alist tr-org-todo-kwd-alist)
+                 (org-done-keywords tr-org-done-keywords)
+                 (org-todo-regexp tr-org-todo-regexp)
+                 (org-todo-line-regexp tr-org-todo-line-regexp)
+                 (org-odd-levels-only
+                  (if (local-variable-p 'org-odd-levels-only (current-buffer))
+                      org-odd-levels-only
+                    tr-org-odd-levels-only)))
+             (goto-char (point-min))
+             (outline-show-all)
+             (if (and heading (not (and datetree-date (not 
datetree-subheading-p))))
+                 (progn
+                   (if (re-search-forward
+                        (concat "^" (regexp-quote heading)
+                                "[ \t]*\\(:[[:alnum:address@hidden:]+:\\)?[ 
\t]*\\($\\|\r\\)")
+                        nil t)
+                       (goto-char (match-end 0))
+                     ;; Heading not found, just insert it at the end
+                     (goto-char (point-max))
+                     (or (bolp) (insert "\n"))
+                     ;; datetrees don't need too much spacing
+                     (insert (if datetree-date "" "\n") heading "\n")
+                     (end-of-line 0))
+                   ;; Make the subtree visible
+                   (outline-show-subtree)
+                   (if org-archive-reversed-order
+                       (progn
+                         (org-back-to-heading t)
+                         (outline-next-heading))
+                     (org-end-of-subtree t))
+                   (skip-chars-backward " \t\r\n")
+                   (and (looking-at "[ \t\r\n]*")
+                        ;; datetree archives don't need so much spacing.
+                        (replace-match (if datetree-date "\n" "\n\n"))))
+               ;; No specific heading, just go to end of file.
+               (goto-char (point-max))
+               ;; Subtree narrowing can let the buffer end on
+               ;; a headline.  `org-paste-subtree' then deletes it.
+               ;; To prevent this, make sure visible part of buffer
+               ;; always terminates on a new line, while limiting
+               ;; number of blank lines in a date tree.
+               (unless (and datetree-date (bolp)) (insert "\n")))
+             ;; Paste
+             (org-paste-subtree (org-get-valid-level level (and heading 1)))
+             ;; Shall we append inherited tags?
+             (and inherited-tags
+                  (or (and (eq org-archive-subtree-add-inherited-tags 'infile)
+                           infile-p)
+                      (eq org-archive-subtree-add-inherited-tags t))
+                  (org-set-tags-to all-tags))
+             ;; Mark the entry as done
+             (when (and org-archive-mark-done
+                        (let ((case-fold-search nil))
+                          (looking-at org-todo-line-regexp))
+                        (or (not (match-end 2))
+                            (not (member (match-string 2) org-done-keywords))))
+               (let (org-log-done org-todo-log-states)
+                 (org-todo
+                  (car (or (member org-archive-mark-done org-done-keywords)
+                           org-done-keywords)))))
+
+             ;; Add the context info.
+             (dolist (item org-archive-save-context-info)
+               (let ((value (cdr (assq item context))))
+                 (when (org-string-nw-p value)
+                   (org-entry-put
+                    (point)
+                    (concat "ARCHIVE_" (upcase (symbol-name item)))
+                    value))))
+             (widen)
+             ;; Save and kill the buffer, if it is not the same
+             ;; buffer.
+             (unless (eq this-buffer buffer) (save-buffer)))))
+       ;; Here we are back in the original buffer.  Everything seems
+       ;; to have worked.  So now run hooks, cut the tree and finish
+       ;; up.
+       (run-hooks 'org-archive-hook)
        (let (this-command) (org-cut-subtree))
        (when (featurep 'org-inlinetask)
          (org-inlinetask-remove-END-maybe))
@@ -375,7 +390,7 @@ this heading."
        (message "Subtree archived %s"
                 (if (eq this-buffer buffer)
                     (concat "under heading: " heading)
-                  (concat "in file: " (abbreviate-file-name afile))))))
+                  (concat "in file: " (abbreviate-file-name afile)))))))
     (org-reveal)
     (if (looking-at "^[ \t]*$")
        (outline-next-visible-heading 1))))
@@ -383,9 +398,12 @@ this heading."
 ;;;###autoload
 (defun org-archive-to-archive-sibling ()
   "Archive the current heading by moving it under the archive sibling.
+
 The archive sibling is a sibling of the heading with the heading name
 `org-archive-sibling-heading' and an `org-archive-tag' tag.  If this
-sibling does not exist, it will be created at the end of the subtree."
+sibling does not exist, it will be created at the end of the subtree.
+
+Archiving time is retained in the ARCHIVE_TIME node property."
   (interactive)
   (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
       (let ((cl (when (eq org-loop-over-headlines-in-active-region 
'start-level)
@@ -400,7 +418,7 @@ sibling does not exist, it will be created at the end of 
the subtree."
                 (when (org-at-heading-p)
                   (org-archive-to-archive-sibling)))
         org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
+        cl (if (org-invisible-p) (org-end-of-subtree nil t))))
     (save-restriction
       (widen)
       (let (b e pos leader level)
@@ -443,7 +461,7 @@ sibling does not exist, it will be created at the end of 
the subtree."
         (format-time-string
          (substring (cdr org-time-stamp-formats) 1 -1)))
        (outline-up-heading 1 t)
-       (hide-subtree)
+       (outline-hide-subtree)
        (org-cycle-show-empty-lines 'folded)
        (goto-char pos)))
     (org-reveal)
@@ -455,13 +473,51 @@ sibling does not exist, it will be created at the end of 
the subtree."
 If the cursor is not on a headline, try all level 1 trees.  If
 it is on a headline, try all direct children.
 When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
-  (let ((re org-not-done-heading-regexp) re1
-       (rea (concat ".*:" org-archive-tag ":"))
+  (org-archive-all-matches
+   (lambda (_beg end)
+     (let ((case-fold-search nil))
+       (unless (re-search-forward org-not-done-heading-regexp end t)
+        "no open TODO items")))
+   tag))
+
+(defun org-archive-all-old (&optional tag)
+  "Archive sublevels of the current tree with timestamps prior to today.
+If the cursor is not on a headline, try all level 1 trees.  If
+it is on a headline, try all direct children.
+When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
+  (org-archive-all-matches
+   (lambda (_beg end)
+     (let (ts)
+       (and (re-search-forward org-ts-regexp end t)
+           (setq ts (match-string 0))
+           (< (org-time-stamp-to-now ts) 0)
+           (if (not (looking-at
+                     (concat "--\\(" org-ts-regexp "\\)")))
+               (concat "old timestamp " ts)
+             (setq ts (concat "old timestamp " ts (match-string 0)))
+             (and (< (org-time-stamp-to-now (match-string 1)) 0)
+                  ts)))))
+   tag))
+
+(defun org-archive-all-matches (predicate &optional tag)
+  "Archive sublevels of the current tree that match PREDICATE.
+
+PREDICATE is a function of two arguments, BEG and END, which
+specify the beginning and end of the headline being considered.
+It is called with point positioned at BEG.  The headline will be
+archived if PREDICATE returns non-nil.  If the return value of
+PREDICATE is a string, it should describe the reason for
+archiving the heading.
+
+If the cursor is not on a headline, try all level 1 trees.  If it
+is on a headline, try all direct children.  When TAG is non-nil,
+don't move trees, but mark them with the ARCHIVE tag."
+  (let ((rea (concat ".*:" org-archive-tag ":")) re1
        (begm (make-marker))
        (endm (make-marker))
-       (question (if tag "Set ARCHIVE tag (no open TODO items)? "
-                   "Move subtree to archive (no open TODO items)? "))
-       beg end (cntarch 0))
+       (question (if tag "Set ARCHIVE tag? "
+                   "Move subtree to archive? "))
+       reason beg end (cntarch 0))
     (if (org-at-heading-p)
        (progn
          (setq re1 (concat "^" (regexp-quote
@@ -481,11 +537,14 @@ When TAG is non-nil, don't move trees, but mark them with 
the ARCHIVE tag."
        (setq beg (match-beginning 0)
              end (save-excursion (org-end-of-subtree t) (point)))
        (goto-char beg)
-       (if (re-search-forward re end t)
+       (if (not (setq reason (funcall predicate beg end)))
            (goto-char end)
          (goto-char beg)
          (if (and (or (not tag) (not (looking-at rea)))
-                  (y-or-n-p question))
+                  (y-or-n-p
+                   (if (stringp reason)
+                       (concat question "(" reason ")")
+                     question)))
              (progn
                (if tag
                    (org-toggle-tag org-archive-tag 'on)
@@ -507,14 +566,14 @@ the children that do not contain any open TODO items."
        (org-map-entries
         `(org-toggle-archive-tag ,find-done)
         org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
+        cl (if (org-invisible-p) (org-end-of-subtree nil t))))
     (if find-done
        (org-archive-all-done 'tag)
       (let (set)
        (save-excursion
          (org-back-to-heading t)
          (setq set (org-toggle-tag org-archive-tag))
-         (when set (hide-subtree)))
+         (when set (org-flag-subtree t)))
        (and set (beginning-of-line 1))
        (message "Subtree %s" (if set "archived" "unarchived"))))))
 
@@ -528,7 +587,7 @@ the children that do not contain any open TODO items."
        (org-map-entries
         'org-archive-set-tag
         org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
+        cl (if (org-invisible-p) (org-end-of-subtree nil t))))
     (org-toggle-tag org-archive-tag 'on)))
 
 ;;;###autoload
diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el
index 7d25437..a026eee 100644
--- a/lisp/org/org-attach.el
+++ b/lisp/org/org-attach.el
@@ -1,4 +1,4 @@
-;;; org-attach.el --- Manage file attachments to org-mode tasks
+;;; org-attach.el --- Manage file attachments to Org tasks -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 
@@ -22,7 +22,7 @@
 
 ;;; Commentary:
 
-;; See the Org-mode manual for information on how to use it.
+;; See the Org manual for information on how to use it.
 ;;
 ;; Attachments are managed in a special directory called "data", which
 ;; lives in the same directory as the org file itself.  If this data
@@ -37,14 +37,13 @@
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
-(require 'org-id)
+(require 'cl-lib)
 (require 'org)
+(require 'org-id)
 (require 'vc-git)
 
 (defgroup org-attach nil
-  "Options concerning entry attachments in Org-mode."
+  "Options concerning entry attachments in Org mode."
   :tag "Org Attach"
   :group 'org)
 
@@ -55,6 +54,14 @@ where the Org file lives."
   :group 'org-attach
   :type 'directory)
 
+(defcustom org-attach-commit t
+  "If non-nil commit attachments with git.
+This is only done if the Org file is in a git repository."
+  :group 'org-attach
+  :type 'boolean
+  :version "26.1"
+  :package-version '(Org . "9.0"))
+
 (defcustom org-attach-git-annex-cutoff (* 32 1024)
   "If non-nil, files larger than this will be annexed instead of stored."
   :group 'org-attach
@@ -120,6 +127,28 @@ lns   create a symbol link.  Note that this is not 
supported
          (const :tag "Link to origin location" t)
          (const :tag "Link to the attach-dir location" attached)))
 
+(defcustom org-attach-archive-delete nil
+  "Non-nil means attachments are deleted upon archiving a subtree.
+When set to `query', ask the user instead."
+  :group 'org-attach
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice
+         (const :tag "Never delete attachments" nil)
+         (const :tag "Always delete attachments" t)
+         (const :tag "Query the user" query)))
+
+(defcustom org-attach-annex-auto-get 'ask
+  "Confirmation preference for automatically getting annex files.
+If \\='ask, prompt using `y-or-n-p'.  If t, always get.  If nil, never get."
+  :group 'org-attach
+  :package-version '(Org . "9")
+  :version "26.1"
+  :type '(choice
+         (const :tag "confirm with `y-or-n-p'" ask)
+         (const :tag "always get from annex if necessary" t)
+         (const :tag "never get from annex" nil)))
+
 ;;;###autoload
 (defun org-attach ()
   "The dispatcher for attachment commands.
@@ -197,25 +226,23 @@ using the entry ID will be invoked to access the unique 
directory for the
 current entry.
 If the directory does not exist and CREATE-IF-NOT-EXISTS-P is non-nil,
 the directory and (if necessary) the corresponding ID will be created."
-  (let (attach-dir uuid inherit)
+  (let (attach-dir uuid)
     (setq org-attach-inherited (org-entry-get nil "ATTACH_DIR_INHERIT"))
     (cond
      ((setq attach-dir (org-entry-get nil "ATTACH_DIR"))
       (org-attach-check-absolute-path attach-dir))
      ((and org-attach-allow-inheritance
-          (setq inherit (org-entry-get nil "ATTACH_DIR_INHERIT" t)))
+          (org-entry-get nil "ATTACH_DIR_INHERIT" t))
       (setq attach-dir
-           (save-excursion
-             (save-restriction
-               (widen)
-               (if (marker-position org-entry-property-inherited-from)
-                   (goto-char org-entry-property-inherited-from)
-                 (org-back-to-heading t))
-               (let (org-attach-allow-inheritance)
-                 (org-attach-dir create-if-not-exists-p)))))
+           (org-with-wide-buffer
+            (if (marker-position org-entry-property-inherited-from)
+                (goto-char org-entry-property-inherited-from)
+              (org-back-to-heading t))
+            (let (org-attach-allow-inheritance)
+              (org-attach-dir create-if-not-exists-p))))
       (org-attach-check-absolute-path attach-dir)
       (setq org-attach-inherited t))
-     (t ; use the ID
+     (t                                        ; use the ID
       (org-attach-check-absolute-path nil)
       (setq uuid (org-id-get (point) create-if-not-exists-p))
       (when (or uuid create-if-not-exists-p)
@@ -261,33 +288,59 @@ the ATTACH_DIR property) their own attachment directory."
   (org-entry-put nil "ATTACH_DIR_INHERIT" "t")
   (message "Children will inherit attachment directory"))
 
+(defun org-attach-use-annex ()
+  "Return non-nil if git annex can be used."
+  (let ((git-dir (vc-git-root (expand-file-name org-attach-directory))))
+    (and org-attach-git-annex-cutoff
+         (or (file-exists-p (expand-file-name "annex" git-dir))
+             (file-exists-p (expand-file-name ".git/annex" git-dir))))))
+
+(defun org-attach-annex-get-maybe (path)
+  "Call git annex get PATH (via shell) if using git annex.
+Signals an error if the file content is not available and it was not 
retrieved."
+  (let ((path-relative (file-relative-name path)))
+    (when (and (org-attach-use-annex)
+              (not
+               (string-equal
+                "found"
+                (shell-command-to-string
+                 (format "git annex find --format=found --in=here %s"
+                         (shell-quote-argument path-relative))))))
+      (let ((should-get
+            (if (eq org-attach-annex-auto-get 'ask)
+                (y-or-n-p (format "Run git annex get %s? " path-relative))
+              org-attach-annex-auto-get)))
+       (if should-get
+           (progn (message "Running git annex get \"%s\"." path-relative)
+                  (call-process "git" nil nil nil "annex" "get" path-relative))
+         (error "File %s stored in git annex but it is not available, and was 
not retrieved"
+                path))))))
+
 (defun org-attach-commit ()
   "Commit changes to git if `org-attach-directory' is properly initialized.
 This checks for the existence of a \".git\" directory in that directory."
   (let* ((dir (expand-file-name org-attach-directory))
         (git-dir (vc-git-root dir))
+        (use-annex (org-attach-use-annex))
         (changes 0))
     (when (and git-dir (executable-find "git"))
       (with-temp-buffer
        (cd dir)
-       (let ((have-annex
-              (and org-attach-git-annex-cutoff
-                   (file-exists-p (expand-file-name "annex" git-dir)))))
-         (dolist (new-or-modified
-                  (split-string
-                   (shell-command-to-string
-                    "git ls-files -zmo --exclude-standard") "\0" t))
-           (if (and have-annex
-                    (>= (nth 7 (file-attributes new-or-modified))
-                        org-attach-git-annex-cutoff))
-               (call-process "git" nil nil nil "annex" "add" new-or-modified)
-             (call-process "git" nil nil nil "add" new-or-modified))
-           (incf changes)))
+        (dolist (new-or-modified
+                 (split-string
+                  (shell-command-to-string
+                   "git ls-files -zmo --exclude-standard") "\0" t))
+          (if (and use-annex
+                   (>= (nth 7 (file-attributes new-or-modified))
+                       org-attach-git-annex-cutoff))
+              (call-process "git" nil nil nil "annex" "add" new-or-modified)
+            (call-process "git" nil nil nil "add" new-or-modified))
+           (cl-incf changes))
        (dolist (deleted
                 (split-string
                  (shell-command-to-string "git ls-files -z --deleted") "\0" t))
          (call-process "git" nil nil nil "rm" deleted)
-         (incf changes))
+         (cl-incf changes))
        (when (> changes 0)
          (shell-command "git commit -m 'Synchronized attachments'"))))))
 
@@ -328,7 +381,8 @@ METHOD may be `cp', `mv', `ln', or `lns' default taken from
        ((eq method 'cp)        (copy-file file fname))
        ((eq method 'ln) (add-name-to-file file fname))
        ((eq method 'lns) (make-symbolic-link file fname)))
-      (org-attach-commit)
+      (when org-attach-commit
+       (org-attach-commit))
       (org-attach-tag)
       (cond ((eq org-attach-store-link-p 'attached)
             (org-attach-store-link fname))
@@ -378,7 +432,7 @@ The attachment is created as an Emacs buffer."
   (let* ((attach-dir (org-attach-dir t))
         (files (org-attach-file-list attach-dir))
         (file (or file
-                  (org-icompleting-read
+                  (completing-read
                    "Delete attachment: "
                    (mapcar (lambda (f)
                              (list (file-name-nondirectory f)))
@@ -387,7 +441,8 @@ The attachment is created as an Emacs buffer."
     (unless (file-exists-p file)
       (error "No such attachment: %s" file))
     (delete-file file)
-    (org-attach-commit)))
+    (when org-attach-commit
+      (org-attach-commit))))
 
 (defun org-attach-delete-all (&optional force)
   "Delete all attachments from the current task.
@@ -403,14 +458,16 @@ A safer way is to open the directory in dired and delete 
from there."
                 (y-or-n-p "Are you sure you want to remove all attachments of 
this entry? ")))
       (shell-command (format "rm -fr %s" attach-dir))
       (message "Attachment directory removed")
-      (org-attach-commit)
+      (when org-attach-commit
+        (org-attach-commit))
       (org-attach-untag))))
 
 (defun org-attach-sync ()
   "Synchronize the current tasks with its attachments.
 This can be used after files have been added externally."
   (interactive)
-  (org-attach-commit)
+  (when org-attach-commit
+    (org-attach-commit))
   (when (and org-attach-file-list-property (not org-attach-inherited))
     (org-entry-delete (point) org-attach-file-list-property))
   (let ((attach-dir (org-attach-dir)))
@@ -419,15 +476,15 @@ This can be used after files have been added externally."
        (and files (org-attach-tag))
        (when org-attach-file-list-property
          (dolist (file files)
-           (unless (string-match "^\\." file)
+           (unless (string-match "^\\.\\.?\\'" file)
              (org-entry-add-to-multivalued-property
               (point) org-attach-file-list-property file))))))))
 
 (defun org-attach-file-list (dir)
   "Return a list of files in the attachment directory.
-This ignores files starting with a \".\", and files ending in \"~\"."
+This ignores files ending in \"~\"."
   (delq nil
-       (mapcar (lambda (x) (if (string-match "^\\." x) nil x))
+       (mapcar (lambda (x) (if (string-match "^\\.\\.?\\'" x) nil x))
                (directory-files dir nil "[^~]\\'"))))
 
 (defun org-attach-reveal (&optional if-exists)
@@ -454,9 +511,11 @@ If IN-EMACS is non-nil, force opening in Emacs."
         (files (org-attach-file-list attach-dir))
         (file (if (= (length files) 1)
                   (car files)
-                (org-icompleting-read "Open attachment: "
-                                      (mapcar 'list files) nil t))))
-    (org-open-file (expand-file-name file attach-dir) in-emacs)))
+                (completing-read "Open attachment: "
+                                 (mapcar #'list files) nil t)))
+         (path (expand-file-name file attach-dir)))
+    (org-attach-annex-get-maybe path)
+    (org-open-file path in-emacs)))
 
 (defun org-attach-open-in-emacs ()
   "Open attachment, force opening in Emacs.
@@ -475,6 +534,17 @@ Basically, this adds the path to the attachment directory, 
and a \"file:\"
 prefix."
   (concat "file:" (org-attach-expand file)))
 
+(defun org-attach-archive-delete-maybe ()
+  "Maybe delete subtree attachments when archiving.
+This function is called by `org-archive-hook'.  The option
+`org-attach-archive-delete' controls its behavior."
+  (when (if (eq org-attach-archive-delete 'query)
+           (yes-or-no-p "Delete all attachments? ")
+         org-attach-archive-delete)
+    (org-attach-delete-all t)))
+
+(add-hook 'org-archive-hook 'org-attach-archive-delete-maybe)
+
 (provide 'org-attach)
 
 ;; Local variables:
diff --git a/lisp/org/org-bbdb.el b/lisp/org/org-bbdb.el
index e41bda4..f851668 100644
--- a/lisp/org/org-bbdb.el
+++ b/lisp/org/org-bbdb.el
@@ -1,4 +1,4 @@
-;;; org-bbdb.el --- Support for links to BBDB entries from within Org-mode
+;;; org-bbdb.el --- Support for links to BBDB entries -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -25,12 +25,12 @@
 ;;
 ;;; Commentary:
 
-;; This file implements links to BBDB database entries from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; This file implements links to BBDB database entries from within Org.
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;; It also implements an interface (based on Ivar Rummelhoff's
-;; bbdb-anniv.el) for those org-mode users, who do not use the diary
+;; bbdb-anniv.el) for those Org users, who do not use the diary
 ;; but who do want to include the anniversaries stored in the BBDB
 ;; into the org-agenda.  If you already include the `diary' into the
 ;; agenda, you might want to prefer to include the anniversaries in
@@ -94,8 +94,7 @@
 ;;; Code:
 
 (require 'org)
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 
 ;; Declare external functions and variables
 
@@ -106,6 +105,7 @@
 (declare-function bbdb-name "ext:bbdb-com" (string elidep))
 (declare-function bbdb-completing-read-record "ext:bbdb-com"
                  (prompt &optional omit-records))
+(declare-function bbdb-record-field "ext:bbdb" (recond field))
 (declare-function bbdb-record-getprop "ext:bbdb" (record property))
 (declare-function bbdb-record-name "ext:bbdb" (record))
 (declare-function bbdb-records "ext:bbdb"
@@ -124,7 +124,7 @@
 (declare-function calendar-leap-year-p "calendar" (year))
 (declare-function diary-ordinal-suffix "diary-lib" (n))
 
-(org-no-warnings (defvar date)) ;; unprefixed, from calendar.el
+(with-no-warnings (defvar date)) ;; unprefixed, from calendar.el
 
 ;; Customization
 
@@ -194,10 +194,12 @@ date year)."
   :group 'org-bbdb-anniversaries
   :require 'bbdb)
 
-
 ;; Install the link type
-(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export)
-(add-hook 'org-store-link-functions 'org-bbdb-store-link)
+(org-link-set-parameters "bbdb"
+                        :follow #'org-bbdb-open
+                        :export #'org-bbdb-export
+                        :complete #'org-bbdb-complete-link
+                        :store #'org-bbdb-store-link)
 
 ;; Implementation
 (defun org-bbdb-store-link ()
@@ -208,7 +210,7 @@ date year)."
            (name (bbdb-record-name rec))
           (company (if (fboundp 'bbdb-record-getprop)
                         (bbdb-record-getprop rec 'company)
-                      (car (bbdb-record-get-field rec 'organization))))
+                      (car (bbdb-record-field rec 'organization))))
           (link (concat "bbdb:" name)))
       (org-store-link-props :type "bbdb" :name name :company company
                            :link link :description name)
@@ -230,10 +232,9 @@ italicized, in all other cases it is left unchanged."
 (defun org-bbdb-open (name)
   "Follow a BBDB link to NAME."
   (require 'bbdb-com)
-  (let ((inhibit-redisplay (not debug-on-error))
-       (bbdb-electric-p nil))
+  (let ((inhibit-redisplay (not debug-on-error)))
     (if (fboundp 'bbdb-name)
-        (org-bbdb-open-old name)
+       (org-bbdb-open-old name)
       (org-bbdb-open-new name))))
 
 (defun org-bbdb-open-old (name)
@@ -280,14 +281,11 @@ italicized, in all other cases it is left unchanged."
   "Convert YYYY-MM-DD to (month date year).
 Argument TIME-STR is the value retrieved from BBDB.  If YYYY- is omitted
 it will be considered unknown."
-  (multiple-value-bind (a b c) (values-list (org-split-string time-str "-"))
-    (if (eq c nil)
-        (list (string-to-number a)
-              (string-to-number b)
-              nil)
-      (list (string-to-number b)
-            (string-to-number c)
-            (string-to-number a)))))
+  (pcase (org-split-string time-str "-")
+    (`(,a ,b nil) (list (string-to-number a) (string-to-number b) nil))
+    (`(,a ,b ,c) (list (string-to-number b)
+                      (string-to-number c)
+                      (string-to-number a)))))
 
 (defun org-bbdb-anniv-split (str)
   "Split multiple entries in the BBDB anniversary field.
@@ -325,9 +323,9 @@ The anniversaries are assumed to be stored 
`org-bbdb-anniversary-field'."
                       (bbdb-split "\n" annivs)))
         (while annivs
           (setq split (org-bbdb-anniv-split (pop annivs)))
-          (multiple-value-bind (m d y)
-              (values-list (funcall org-bbdb-extract-date-fun (car split)))
-            (setq tmp (gethash (list m d) org-bbdb-anniv-hash))
+         (pcase-let ((`(,m ,d ,y) (funcall org-bbdb-extract-date-fun
+                                           (car split))))
+           (setq tmp (gethash (list m d) org-bbdb-anniv-hash))
             (puthash (list m d) (cons (list y
                                             (bbdb-record-name rec)
                                             (cadr split))
@@ -335,7 +333,7 @@ The anniversaries are assumed to be stored 
`org-bbdb-anniversary-field'."
                      org-bbdb-anniv-hash))))))
   (setq org-bbdb-updated-p nil))
 
-(defun org-bbdb-updated (rec)
+(defun org-bbdb-updated (_rec)
   "Record the fact that BBDB has been updated.
 This is used by Org to re-create the anniversary hash table."
   (setq org-bbdb-updated-p t))
@@ -397,6 +395,66 @@ This is used by Org to re-create the anniversary hash 
table."
         ))
     text))
 
+;;; Return list of anniversaries for today and the next n-1 (default: n=7) 
days.
+;;; This is meant to be used in an org file instead of org-bbdb-anniversaries:
+;;;
+;;; %%(org-bbdb-anniversaries-future)
+;;;
+;;; or
+;;;
+;;; %%(org-bbdb-anniversaries-future 3)
+;;;
+;;; to override the 7-day default.
+
+(defun org-bbdb-date-list (d n)
+  "Return a list of dates in (m d y) format from the given date D to n-1 days 
hence."
+  (let ((abs (calendar-absolute-from-gregorian d)))
+    (mapcar (lambda (i) (calendar-gregorian-from-absolute (+ abs i)))
+           (number-sequence 0 (1- n)))))
+
+;;;###autoload
+(defun org-bbdb-anniversaries-future (&optional n)
+  "Return list of anniversaries for today and the next n-1 days (default n=7)."
+  (let ((n (or n 7)))
+    (when (<= n 0)
+      (error "The (optional) argument of `org-bbdb-anniversaries-future' \
+must be positive"))
+    (let (
+         ;; List of relevant dates.
+         (dates (org-bbdb-date-list date n))
+         ;; Function to annotate text of each element of l with the
+         ;; anniversary date d.
+         (annotate-descriptions
+          (lambda (d l)
+            (mapcar (lambda (x)
+                      ;; The assumption here is that x is a bbdb link
+                      ;; of the form [[bbdb:name][description]].
+                      ;; This function rather arbitrarily modifies
+                      ;; the description by adding the date to it in
+                      ;; a fixed format.
+                      (string-match "]]" x)
+                      (replace-match (format " -- %d-%02d-%02d\\&"
+                                             (nth 2 d)
+                                             (nth 0 d)
+                                             (nth 1 d))
+                                     nil nil x))
+                    l))))
+      ;; Map a function that generates anniversaries for each date
+      ;; over the dates and nconc the results into a single list. When
+      ;; it is no longer necessary to support older versions of Emacs,
+      ;; this can be done with a cl-mapcan; for now, we use the (apply
+      ;; #'nconc ...) method for compatibility.
+      (apply #'nconc
+            (mapcar
+             (lambda (d)
+               (let ((date d))
+                 ;; Rebind 'date' so that org-bbdb-anniversaries will
+                 ;; be fooled into giving us the list for the given
+                 ;; date and then annotate the descriptions for that
+                 ;; date.
+                 (funcall annotate-descriptions d (org-bbdb-anniversaries))))
+             dates)))))
+
 (defun org-bbdb-complete-link ()
   "Read a bbdb link with name completion."
   (require 'bbdb-com)
diff --git a/lisp/org/org-bibtex.el b/lisp/org/org-bibtex.el
index f8b376d..d81c9f1 100644
--- a/lisp/org/org-bibtex.el
+++ b/lisp/org/org-bibtex.el
@@ -1,4 +1,4 @@
-;;; org-bibtex.el --- Org links to BibTeX entries
+;;; org-bibtex.el --- Org links to BibTeX entries    -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
 ;;
@@ -73,7 +73,7 @@
 ;; =====================================================================
 ;;
 ;; Additionally, the following functions are now available for storing
-;; bibtex entries within Org-mode documents.
+;; bibtex entries within Org documents.
 ;;
 ;; - Run `org-bibtex' to export the current file to a .bib.
 ;;
@@ -92,27 +92,28 @@
 ;;
 ;;; History:
 ;;
-;; The link creation part has been part of Org-mode for a long time.
+;; The link creation part has been part of Org for a long time.
 ;;
 ;; Creating better capture template information was inspired by a request
 ;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112
 ;; and then implemented by Bastien Guerry.
 ;;
 ;; Eric Schulte eventually added the functions for translating between
-;; Org-mode headlines and Bibtex entries, and for fleshing out the Bibtex
-;; fields of existing Org-mode headlines.
+;; Org headlines and Bibtex entries, and for fleshing out the Bibtex
+;; fields of existing Org headlines.
 ;;
-;; Org-mode loads this module by default - if this is not what you want,
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;;; Code:
 
 (require 'org)
 (require 'bibtex)
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'org-compat)
 
+(defvar org-agenda-overriding-header)
+(defvar org-agenda-search-view-always-boolean)
 (defvar org-bibtex-description nil) ; dynamically scoped from org.el
 (defvar org-id-locations)
 
@@ -120,7 +121,6 @@
 (declare-function bibtex-generate-autokey "bibtex" ())
 (declare-function bibtex-parse-entry "bibtex" (&optional content))
 (declare-function bibtex-url "bibtex" (&optional pos no-browse))
-(declare-function org-babel-trim "ob-core" (string &optional regexp))
 
 
 ;;; Bibtex data
@@ -264,26 +264,39 @@ IDs must be unique."
 
 (defcustom org-bibtex-tags-are-keywords nil
   "Convert the value of the keywords field to tags and vice versa.
-If set to t, comma-separated entries in a bibtex entry's keywords
-field will be converted to org tags.  Note: spaces will be escaped
-with underscores, and characters that are not permitted in org
+
+When non-nil, comma-separated entries in a bibtex entry's keywords
+field will be converted to Org tags.  Note: spaces will be escaped
+with underscores, and characters that are not permitted in Org
 tags will be removed.
 
-If t, local tags in an org entry will be exported as a
-comma-separated string of keywords when exported to bibtex.  Tags
-defined in `org-bibtex-tags' or `org-bibtex-no-export-tags' will
-not be exported."
+When non-nil, local tags in an Org entry will be exported as
+a comma-separated string of keywords when exported to bibtex.
+If `org-bibtex-inherit-tags' is non-nil, inherited tags will also
+be exported as keywords.  Tags defined in `org-bibtex-tags' or
+`org-bibtex-no-export-tags' will not be exported."
   :group 'org-bibtex
   :version "24.1"
   :type 'boolean)
 
 (defcustom org-bibtex-no-export-tags nil
   "List of tag(s) that should not be converted to keywords.
-This variable is relevant only if `org-bibtex-tags-are-keywords' is t."
+This variable is relevant only if `org-bibtex-tags-are-keywords'
+is non-nil."
   :group 'org-bibtex
   :version "24.1"
   :type '(repeat :tag "Tag" (string)))
 
+(defcustom org-bibtex-inherit-tags nil
+  "Controls whether inherited tags are converted to bibtex keywords.
+It is relevant only if `org-bibtex-tags-are-keywords' is non-nil.
+Tag inheritence itself is controlled by `org-use-tag-inheritence'
+and `org-exclude-tags-from-inheritence'."
+  :group 'org-bibtex
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean)
+
 (defcustom org-bibtex-type-property-name "btype"
   "Property in which to store bibtex entry type (e.g., article)."
   :group 'org-bibtex
@@ -299,7 +312,7 @@ This variable is relevant only if 
`org-bibtex-tags-are-keywords' is t."
                (org-entry-get (point) (upcase property))
                (org-entry-get (point) (concat org-bibtex-prefix
                                               (upcase property)))))))
-    (when it (org-babel-trim it))))
+    (when it (org-trim it))))
 
 (defun org-bibtex-put (property value)
   (let ((prop (upcase (if (keywordp property)
@@ -312,27 +325,27 @@ This variable is relevant only if 
`org-bibtex-tags-are-keywords' is t."
 
 (defun org-bibtex-headline ()
   "Return a bibtex entry of the given headline as a string."
-  (let* ((val (lambda (key lst) (cdr (assoc key lst))))
-        (to (lambda (string) (intern (concat ":" string))))
-        (from (lambda (key) (substring (symbol-name key) 1)))
-        flatten ; silent compiler warning
-        (flatten (lambda (&rest lsts)
-                   (apply #'append (mapcar
-                                    (lambda (e)
-                                      (if (listp e) (apply flatten e) (list 
e)))
-                                    lsts))))
-        (notes (buffer-string))
-        (id (org-bibtex-get org-bibtex-key-property))
-        (type (org-bibtex-get org-bibtex-type-property-name))
-        (tags (when org-bibtex-tags-are-keywords
-                (delq nil
-                      (mapcar
-                       (lambda (tag)
-                         (unless (member tag
-                                         (append org-bibtex-tags
-                                                 org-bibtex-no-export-tags))
-                           tag))
-                       (org-get-local-tags-at))))))
+  (letrec ((val (lambda (key lst) (cdr (assoc key lst))))
+          (to (lambda (string) (intern (concat ":" string))))
+          (from (lambda (key) (substring (symbol-name key) 1)))
+          (flatten (lambda (&rest lsts)
+                     (apply #'append (mapcar
+                                      (lambda (e)
+                                        (if (listp e) (apply flatten e) (list 
e)))
+                                      lsts))))
+          (id (org-bibtex-get org-bibtex-key-property))
+          (type (org-bibtex-get org-bibtex-type-property-name))
+          (tags (when org-bibtex-tags-are-keywords
+                  (delq nil
+                        (mapcar
+                         (lambda (tag)
+                           (unless (member tag
+                                           (append org-bibtex-tags
+                                                   org-bibtex-no-export-tags))
+                             tag))
+                         (if org-bibtex-inherit-tags
+                             (org-get-tags-at)
+                           (org-get-local-tags-at)))))))
     (when type
       (let ((entry (format
                    "@%s{%s,\n%s\n}\n" type id
@@ -358,7 +371,7 @@ This variable is relevant only if 
`org-bibtex-tags-are-keywords' is t."
                               (mapcar
                                (lambda (field)
                                  (let ((value (or (org-bibtex-get (funcall 
from field))
-                                                  (and (equal :title field)
+                                                  (and (eq :title field)
                                                        (nth 4 
(org-heading-components))))))
                                    (when value (cons (funcall from field) 
value))))
                                (funcall flatten
@@ -421,13 +434,14 @@ With optional argument OPTIONAL, also prompt for optional 
fields."
                      (funcall val :required (funcall val type 
org-bibtex-types)))
                    (when optional (funcall val :optional (funcall val type 
org-bibtex-types)))))
       (when (consp field) ; or'd pair of fields e.g., (:editor :author)
-        (let ((present (first (remove
+        (let ((present (nth 0 (remove
                               nil
                               (mapcar
-                               (lambda (f) (when (org-bibtex-get (funcall name 
f)) f))
+                               (lambda (f)
+                                 (when (org-bibtex-get (funcall name f)) f))
                                field)))))
           (setf field (or present (funcall keyword
-                                          (org-icompleting-read
+                                          (completing-read
                                            "Field: " (mapcar name field)))))))
       (let ((name (funcall name field)))
         (unless (org-bibtex-get name)
@@ -439,8 +453,9 @@ With optional argument OPTIONAL, also prompt for optional 
fields."
 
 
 ;;; Bibtex link functions
-(org-add-link-type "bibtex" 'org-bibtex-open)
-(add-hook 'org-store-link-functions 'org-bibtex-store-link)
+(org-link-set-parameters "bibtex"
+                        :follow #'org-bibtex-open
+                        :store #'org-bibtex-store-link)
 
 (defun org-bibtex-open (path)
   "Visit the bibliography entry on PATH."
@@ -533,21 +548,23 @@ With optional argument OPTIONAL, also prompt for optional 
fields."
 (add-hook 'org-execute-file-search-functions 
'org-execute-file-search-in-bibtex)
 
 
-;;; Bibtex <-> Org-mode headline translation functions
-(defun org-bibtex (&optional filename)
+;;; Bibtex <-> Org headline translation functions
+(defun org-bibtex (filename)
   "Export each headline in the current file to a bibtex entry.
 Headlines are exported using `org-bibtex-headline'."
   (interactive
    (list (read-file-name
          "Bibtex file: " nil nil nil
-         (file-name-nondirectory
-          (concat (file-name-sans-extension (buffer-file-name)) ".bib")))))
+         (let ((file (buffer-file-name (buffer-base-buffer))))
+           (and file
+                (file-name-nondirectory
+                 (concat (file-name-sans-extension file) ".bib")))))))
   (let ((error-point
          (catch 'bib
            (let ((bibtex-entries
                   (remove nil (org-map-entries
                                (lambda ()
-                                 (condition-case foo
+                                 (condition-case nil
                                      (org-bibtex-headline)
                                    (error (throw 'bib (point)))))))))
              (with-temp-file filename
@@ -578,7 +595,7 @@ With prefix argument OPTIONAL also prompt for optional 
fields."
 With a prefix arg, query for optional fields as well.
 If nonew is t, add data to the headline of the entry at point."
   (interactive "P")
-  (let* ((type (org-icompleting-read
+  (let* ((type (completing-read
                "Type: " (mapcar (lambda (type)
                                   (substring (symbol-name (car type)) 1))
                                 org-bibtex-types)
@@ -597,7 +614,7 @@ If nonew is t, add data to the headline of the entry at 
point."
     (org-bibtex-put org-bibtex-type-property-name
                    (substring (symbol-name type) 1))
     (org-bibtex-fleshout type arg)
-    (mapc (lambda (tag) (org-toggle-tag tag 'on)) org-bibtex-tags)))
+    (dolist (tag org-bibtex-tags) (org-toggle-tag tag 'on))))
 
 (defun org-bibtex-create-in-current-entry (&optional arg)
   "Add bibliographical data to the current entry.
@@ -611,10 +628,10 @@ This uses `bibtex-parse-entry'."
   (interactive)
   (let ((keyword (lambda (str) (intern (concat ":" (downcase str)))))
        (clean-space (lambda (str) (replace-regexp-in-string
-                                   "[[:space:]\n\r]+" " " str)))
+                              "[[:space:]\n\r]+" " " str)))
        (strip-delim
-        (lambda (str)       ; strip enclosing "..." and {...}
-          (dolist (pair '((34 . 34) (123 . 125) (123 . 125)))
+        (lambda (str)               ; strip enclosing "..." and {...}
+          (dolist (pair '((34 . 34) (123 . 125)))
             (when (and (> (length str) 1)
                        (= (aref str 0) (car pair))
                        (= (aref str (1- (length str))) (cdr pair)))
@@ -622,10 +639,10 @@ This uses `bibtex-parse-entry'."
     (push (mapcar
            (lambda (pair)
              (cons (let ((field (funcall keyword (car pair))))
-                     (case field
+                     (pcase field
                        (:=type= :type)
                        (:=key= :key)
-                       (otherwise field)))
+                       (_ field)))
                    (funcall clean-space (funcall strip-delim (cdr pair)))))
            (save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry)))
           org-bibtex-entries)))
@@ -633,7 +650,7 @@ This uses `bibtex-parse-entry'."
 (defun org-bibtex-read-buffer (buffer)
   "Read all bibtex entries in BUFFER and save to `org-bibtex-entries'.
 Return the number of saved entries."
-  (interactive "bbuffer: ")
+  (interactive "bBuffer: ")
   (let ((start-length (length org-bibtex-entries)))
     (with-current-buffer buffer
       (save-excursion
@@ -643,12 +660,12 @@ Return the number of saved entries."
          (org-bibtex-read)
          (bibtex-beginning-of-entry))))
     (let ((added (- (length org-bibtex-entries) start-length)))
-      (message "parsed %d entries" added)
+      (message "Parsed %d entries" added)
       added)))
 
 (defun org-bibtex-read-file (file)
   "Read FILE with `org-bibtex-read-buffer'."
-  (interactive "ffile: ")
+  (interactive "fFile: ")
   (org-bibtex-read-buffer (find-file-noselect file 'nowarn 'rawfile)))
 
 (defun org-bibtex-write ()
@@ -666,25 +683,23 @@ Return the number of saved entries."
     (org-bibtex-put org-bibtex-type-property-name
                    (downcase (funcall val :type)))
     (dolist (pair entry)
-      (case (car pair)
+      (pcase (car pair)
        (:title    nil)
        (:type     nil)
        (:key      (org-bibtex-put org-bibtex-key-property (cdr pair)))
        (:keywords (if org-bibtex-tags-are-keywords
-                      (mapc
-                       (lambda (kw)
-                         (funcall
-                          togtag
-                          (replace-regexp-in-string
-                           "[^[:alnum:address@hidden" ""
-                           (replace-regexp-in-string "[ \t]+" "_" kw))))
-                       (split-string (cdr pair) ", *"))
+                      (dolist (kw (split-string (cdr pair) ", *"))
+                        (funcall
+                         togtag
+                         (replace-regexp-in-string
+                          "[^[:alnum:address@hidden" ""
+                          (replace-regexp-in-string "[ \t]+" "_" kw))))
                     (org-bibtex-put (car pair) (cdr pair))))
-       (otherwise (org-bibtex-put (car pair)  (cdr pair)))))
+       (_ (org-bibtex-put (car pair) (cdr pair)))))
     (mapc togtag org-bibtex-tags)))
 
 (defun org-bibtex-yank ()
-  "If kill ring holds a bibtex entry yank it as an Org-mode headline."
+  "If kill ring holds a bibtex entry yank it as an Org headline."
   (interactive)
   (let (entry)
     (with-temp-buffer (yank 1) (setf entry (org-bibtex-read)))
@@ -693,8 +708,8 @@ Return the number of saved entries."
       (error "Yanked text does not appear to contain a BibTeX entry"))))
 
 (defun org-bibtex-import-from-file (file)
-  "Read bibtex entries from FILE and insert as Org-mode headlines after point."
-  (interactive "ffile: ")
+  "Read bibtex entries from FILE and insert as Org headlines after point."
+  (interactive "fFile: ")
   (dotimes (_ (org-bibtex-read-file file))
     (save-excursion (org-bibtex-write))
     (re-search-forward org-property-end-re)
diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el
index b302113..63e23cc 100644
--- a/lisp/org/org-capture.el
+++ b/lisp/org/org-capture.el
@@ -1,4 +1,4 @@
-;;; org-capture.el --- Fast note taking in Org-mode
+;;; org-capture.el --- Fast note taking in Org       -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -47,23 +47,22 @@
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'org)
 
+(declare-function org-at-encrypted-entry-p "org-crypt" ())
 (declare-function org-datetree-find-date-create "org-datetree"
                  (date &optional keep-restriction))
-(declare-function org-table-get-specials "org-table" ())
-(declare-function org-table-goto-line "org-table" (N))
-(declare-function org-pop-to-buffer-same-window "org-compat"
-                 (&optional buffer-or-name norecord label))
-(declare-function org-at-encrypted-entry-p "org-crypt" ())
-(declare-function org-encrypt-entry "org-crypt" ())
 (declare-function org-decrypt-entry "org-crypt" ())
+(declare-function org-encrypt-entry "org-crypt" ())
+(declare-function org-table-analyze "org-table" ())
+(declare-function org-table-goto-line "org-table" (N))
 
+(defvar org-end-time-was-given)
 (defvar org-remember-default-headline)
 (defvar org-remember-templates)
 (defvar org-table-hlines)
+(defvar org-table-current-begin-pos)
 (defvar dired-buffers)
 
 (defvar org-capture-clock-was-started nil
@@ -76,6 +75,9 @@
 ;; to indicate that the link properties have already been stored
 (defvar org-capture-link-is-already-stored nil)
 
+(defvar org-capture-is-refiling nil
+  "Non-nil when capture process is refiling an entry.")
+
 (defgroup org-capture nil
   "Options concerning capturing new entries."
   :tag "Org Capture"
@@ -103,9 +105,9 @@ description  A short string describing the template, will 
be shown during
              selection.
 
 type         The type of entry.  Valid types are:
-               entry       an Org-mode node, with a headline.  Will be
-                           filed as the child of the target entry or as
-                           a top-level entry.
+               entry       an Org node, with a headline.  Will be filed
+                           as the child of the target entry or as a
+                           top-level entry.
                item        a plain list item, will be placed in the
                            first plain list at the target
                            location.
@@ -116,21 +118,22 @@ type         The type of entry.  Valid types are:
                plain       text to be inserted as it is.
 
 target       Specification of where the captured item should be placed.
-             In Org-mode files, targets usually define a node.  Entries will
+             In Org files, targets usually define a node.  Entries will
              become children of this node, other types will be added to the
              table or list in the body of this node.
 
              Most target specifications contain a file name.  If that file
              name is the empty string, it defaults to `org-default-notes-file'.
              A file can also be given as a variable, function, or Emacs Lisp
-             form.
+             form.  When an absolute path is not specified for a
+             target, it is taken as relative to `org-directory'.
 
              Valid values are:
 
              (file \"path/to/file\")
                  Text will be placed at the beginning or end of that file
 
-             (id \"id of existing org entry\")
+             (id \"id of existing Org entry\")
                  File as child of this entry, or in the body of the entry
 
              (file+headline \"path/to/file\" \"node headline\")
@@ -148,6 +151,12 @@ target       Specification of where the captured item 
should be placed.
              (file+datetree+prompt \"path/to/file\")
                  Will create a heading in a date tree, prompts for date
 
+             (file+weektree \"path/to/file\")
+                 Will create a heading in a week tree for today's date
+
+             (file+weektree+prompt \"path/to/file\")
+                 Will create a heading in a week tree, prompts for date
+
              (file+function \"path/to/file\" function-finding-location)
                  A function to find the right location in the file
 
@@ -155,8 +164,8 @@ target       Specification of where the captured item 
should be placed.
                 File to the entry that is currently being clocked
 
              (function function-finding-location)
-                Most general way, write your own function to find both
-                file and location
+                Most general way: write your own function which both visits
+                the file and moves point to the right location
 
 template     The template for creating the capture item.  If you leave this
              empty, an appropriate default template will be used.  See below
@@ -218,15 +227,20 @@ properties are:
                      is finalized.
 
 The template defines the text to be inserted.  Often this is an
-org-mode entry (so the first line should start with a star) that
+Org mode entry (so the first line should start with a star) that
 will be filed as a child of the target headline.  It can also be
 freely formatted text.  Furthermore, the following %-escapes will
-be replaced with content and expanded in this order:
+be replaced with content and expanded:
 
-  %[pathname] Insert the contents of the file given by `pathname'.
+  %[pathname] Insert the contents of the file given by
+              `pathname'.  These placeholders are expanded at the very
+              beginning of the process so they can be used to extend the
+              current template.
   %(sexp)     Evaluate elisp `(sexp)' and replace it with the results.
-              For convenience, %:keyword (see below) placeholders within
-              the expression will be expanded prior to this.
+              Only placeholders pre-existing within the template, or
+              introduced with %[pathname] are expanded this way.  Since this
+              happens after expanding non-interactive %-escapes, those can
+              be used to fill the expression.
   %<...>      The result of format-time-string on the ... format specification.
   %t          Time stamp, date only.
   %T          Time stamp with date and time.
@@ -255,8 +269,8 @@ be replaced with content and expanded in this order:
               A default value and a completion table ca be specified like this:
               %^{prompt|default|completion2|completion3|...}.
   %?          After completing the template, position cursor here.
-  %\\n         Insert the text entered at the nth %^{prompt}, where `n' is
-              a number, starting from 1.
+  %\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N
+              is a number, starting from 1.
 
 Apart from these general escapes, you can access information specific to
 the link type that is created.  For example, calling `org-capture' in emails
@@ -274,13 +288,21 @@ gnus                    |  %:from %:fromname %:fromaddress
                         |  %:date %:date-timestamp (as active timestamp)
                         |  %:date-timestamp-inactive (as inactive timestamp)
 gnus                    |  %:group, for messages also all email fields
-w3, w3m                 |  %:type %:url
+eww, w3, w3m            |  %:type %:url
 info                    |  %:type %:file %:node
-calendar                |  %:type %:date"
+calendar                |  %:type %:date
+
+When you need to insert a literal percent sign in the template,
+you can escape ambiguous cases with a backward slash, e.g., \\%i."
   :group 'org-capture
   :version "24.1"
   :type
-  '(repeat
+  (let ((file-variants '(choice :tag "Filename       "
+                               (file :tag "Literal")
+                               (function :tag "Function")
+                               (variable :tag "Variable")
+                               (sexp :tag "Form"))))
+  `(repeat
     (choice :value ("" "" entry (file "~/org/notes.org") "")
            (list :tag "Multikey description"
                  (string :tag "Keys       ")
@@ -297,39 +319,45 @@ calendar                |  %:type %:date"
                  (choice :tag "Target location"
                          (list :tag "File"
                                (const :format "" file)
-                               (file :tag "  File"))
+                               ,file-variants)
                          (list :tag "ID"
                                (const :format "" id)
                                (string :tag "  ID"))
                          (list :tag "File & Headline"
                                (const :format "" file+headline)
-                               (file   :tag "  File    ")
+                               ,file-variants
                                (string :tag "  Headline"))
                          (list :tag "File & Outline path"
                                (const :format "" file+olp)
-                               (file   :tag "  File    ")
+                               ,file-variants
                                (repeat :tag "Outline path" :inline t
                                        (string :tag "Headline")))
                          (list :tag "File & Regexp"
                                (const :format "" file+regexp)
-                               (file   :tag "  File  ")
+                               ,file-variants
                                (regexp :tag "  Regexp"))
                          (list :tag "File & Date tree"
                                (const :format "" file+datetree)
-                               (file :tag "  File"))
+                               ,file-variants)
                          (list :tag "File & Date tree, prompt for date"
                                (const :format "" file+datetree+prompt)
-                               (file :tag "  File"))
+                               ,file-variants)
+                         (list :tag "File & Week tree"
+                               (const :format "" file+weektree)
+                               ,file-variants)
+                         (list :tag "File & Week tree, prompt for date"
+                               (const :format "" file+weektree+prompt)
+                               ,file-variants)
                          (list :tag "File & function"
                                (const :format "" file+function)
-                               (file :tag "  File    ")
+                               ,file-variants
                                (sexp :tag "  Function"))
                          (list :tag "Current clocking task"
                                (const :format "" clock))
                          (list :tag "Function"
                                (const :format "" function)
                                (sexp :tag "  Function")))
-                 (choice :tag "Template"
+                 (choice :tag "Template       "
                          (string)
                          (list :tag "File"
                                (const :format "" file)
@@ -350,7 +378,7 @@ calendar                |  %:type %:date"
                                   ((const :format "%v " :clock-resume) (const 
t))
                                   ((const :format "%v " :unnarrowed) (const t))
                                   ((const :format "%v " :table-line-pos) 
(const t))
-                                  ((const :format "%v " :kill-buffer) (const 
t))))))))
+                                  ((const :format "%v " :kill-buffer) (const 
t)))))))))
 
 (defcustom org-capture-before-finalize-hook nil
   "Hook that is run right before a capture process is finalized.
@@ -421,7 +449,7 @@ to avoid conflicts with other active capture processes."
 
 (defvar org-capture-mode-map (make-sparse-keymap)
   "Keymap for `org-capture-mode', a minor mode.
-Use this map to set additional keybindings for when Org-mode is used
+Use this map to set additional keybindings for when Org mode is used
 for a capture buffer.")
 
 (defvar org-capture-mode-hook nil
@@ -432,10 +460,12 @@ for a capture buffer.")
 
 Turning on this mode runs the normal hook `org-capture-mode-hook'."
   nil " Rem" org-capture-mode-map
-  (org-set-local
-   'header-line-format
+  (setq-local
+   header-line-format
    (substitute-command-keys
-    "Capture buffer.  Finish `C-c C-c', refile `C-c C-w', abort `C-c C-k'.")))
+    "\\<org-capture-mode-map>Capture buffer.  Finish \
+`\\[org-capture-finalize]', refile `\\[org-capture-refile]', \
+abort `\\[org-capture-kill]'.")))
 (define-key org-capture-mode-map "\C-c\C-c" 'org-capture-finalize)
 (define-key org-capture-mode-map "\C-c\C-k" 'org-capture-kill)
 (define-key org-capture-mode-map "\C-c\C-w" 'org-capture-refile)
@@ -460,7 +490,7 @@ For example, if you have a capture template \"c\" and you 
want
 this template to be accessible only from `message-mode' buffers,
 use this:
 
-   ((\"c\" ((in-mode . \"message-mode\"))))
+   \\='((\"c\" ((in-mode . \"message-mode\"))))
 
 Here are the available contexts definitions:
 
@@ -478,7 +508,7 @@ accessible if there is at least one valid check.
 You can also bind a key to another agenda custom command
 depending on contextual rules.
 
-   ((\"c\" \"d\" ((in-mode . \"message-mode\"))))
+    \\='((\"c\" \"d\" ((in-mode . \"message-mode\"))))
 
 Here it means: in `message-mode buffers', use \"c\" as the
 key for the capture template otherwise associated with \"d\".
@@ -504,7 +534,8 @@ to avoid duplicates.)"
 
 (defcustom org-capture-use-agenda-date nil
   "Non-nil means use the date at point when capturing from agendas.
-When nil, you can still capture using the date at point with 
\\[org-agenda-capture]."
+When nil, you can still capture using the date at point with
+`\\[org-agenda-capture]'."
   :group 'org-capture
   :version "24.3"
   :type 'boolean)
@@ -513,17 +544,20 @@ When nil, you can still capture using the date at point 
with \\[org-agenda-captu
 (defun org-capture (&optional goto keys)
   "Capture something.
 \\<org-capture-mode-map>
-This will let you select a template from `org-capture-templates', and then
-file the newly captured information.  The text is immediately inserted
-at the target location, and an indirect buffer is shown where you can
-edit it.  Pressing \\[org-capture-finalize] brings you back to the previous 
state
-of Emacs, so that you can continue your work.
-
-When called interactively with a \\[universal-argument] prefix argument GOTO, 
don't capture
-anything, just go to the file/headline where the selected template
-stores its notes.  With a double prefix argument \
-\\[universal-argument] \\[universal-argument], go to the last note
-stored.
+This will let you select a template from `org-capture-templates', and
+then file the newly captured information.  The text is immediately
+inserted at the target location, and an indirect buffer is shown where
+you can edit it.  Pressing `\\[org-capture-finalize]' brings you back to the \
+previous
+state of Emacs, so that you can continue your work.
+
+When called interactively with a `\\[universal-argument]' prefix argument \
+GOTO, don't
+capture anything, just go to the file/headline where the selected
+template stores its notes.
+
+With a `\\[universal-argument] \\[universal-argument]' prefix argument, go to \
+the last note stored.
 
 When called with a `C-0' (zero) prefix, insert a template at point.
 
@@ -564,7 +598,7 @@ of the day at point (if any) or the current HH:MM time."
        ((equal entry "C")
        (customize-variable 'org-capture-templates))
        ((equal entry "q")
-       (error "Abort"))
+       (user-error "Abort"))
        (t
        (org-capture-set-plist entry)
        (org-capture-get-template)
@@ -596,10 +630,10 @@ of the day at point (if any) or the current HH:MM time."
            (org-capture-insert-template-here)
          (condition-case error
              (org-capture-place-template
-              (equal (car (org-capture-get :target)) 'function))
+              (eq (car (org-capture-get :target)) 'function))
            ((error quit)
             (if (and (buffer-base-buffer (current-buffer))
-                     (string-match "\\`CAPTURE-" (buffer-name)))
+                     (string-prefix-p "CAPTURE-" (buffer-name)))
                 (kill-buffer (current-buffer)))
             (set-window-configuration (org-capture-get :return-to-wconf))
             (error "Capture template `%s': %s"
@@ -613,7 +647,7 @@ of the day at point (if any) or the current HH:MM time."
                        (org-capture-put :interrupted-clock
                                         (copy-marker org-clock-marker)))
                    (org-clock-in)
-                   (org-set-local 'org-capture-clock-was-started t))
+                   (setq-local org-capture-clock-was-started t))
                (error
                 "Could not start the clock in this capture buffer")))
          (if (org-capture-get :immediate-finish)
@@ -646,7 +680,7 @@ captured item after finalizing."
     (setq stay-with-capture t))
   (unless (and org-capture-mode
               (buffer-base-buffer (current-buffer)))
-    (error "This does not seem to be a capture buffer for Org-mode"))
+    (error "This does not seem to be a capture buffer for Org mode"))
 
   (run-hooks 'org-capture-prepare-finalize-hook)
 
@@ -682,23 +716,13 @@ captured item after finalizing."
              (m2 (org-capture-get :end-marker 'local)))
          (if (and m1 m2 (= m1 beg) (= m2 end))
              (progn
-               (setq m2 (if (cdr (assoc 'heading org-blank-before-new-entry))
+               (setq m2 (if (cdr (assq 'heading org-blank-before-new-entry))
                             m2 (1+ m2))
                      m2 (if (< (point-max) m2) (point-max) m2))
                (setq abort-note 'clean)
                (kill-region m1 m2))
            (setq abort-note 'dirty)))
 
-      ;; Make sure that the empty lines after are correct
-      (when (and (> (point-max) end) ; indeed, the buffer was still narrowed
-                (member (org-capture-get :type 'local)
-                        '(entry item checkitem plain)))
-       (save-excursion
-         (goto-char end)
-         (or (bolp) (newline))
-         (org-capture-empty-lines-after
-          (or (org-capture-get :empty-lines-after 'local)
-              (org-capture-get :empty-lines 'local) 0))))
       ;; Postprocessing:  Update Statistics cookies, do the sorting
       (when (derived-mode-p 'org-mode)
        (save-excursion
@@ -715,8 +739,7 @@ captured item after finalizing."
       ;; Store this place as the last one where we stored something
       ;; Do the marking in the base buffer, so that it makes sense after
       ;; the indirect buffer has been killed.
-      (when org-capture-bookmark
-       (org-capture-bookmark-last-stored-position))
+      (org-capture-store-last-position)
 
       ;; Run the hook
       (run-hooks 'org-capture-before-finalize-hook))
@@ -770,11 +793,12 @@ captured item after finalizing."
     ;; Special cases
     (cond
      (abort-note
-      (cond
-       ((equal abort-note 'clean)
-       (message "Capture process aborted and target buffer cleaned up"))
-       ((equal abort-note 'dirty)
-       (error "Capture process aborted, but target buffer could not be cleaned 
up correctly"))))
+      (cl-case abort-note
+       (clean
+        (message "Capture process aborted and target buffer cleaned up"))
+       (dirty
+        (error "Capture process aborted, but target buffer could not be \
+cleaned up correctly"))))
      (stay-with-capture
       (org-capture-goto-last-stored)))
     ;; Return if we did store something
@@ -786,19 +810,28 @@ Refiling is done from the base buffer, because the 
indirect buffer is then
 already gone.  Any prefix argument will be passed to the refile command."
   (interactive)
   (unless (eq (org-capture-get :type 'local) 'entry)
-    (error
-     "Refiling from a capture buffer makes only sense for `entry'-type 
templates"))
-  (let ((pos (point))
-       (base (buffer-base-buffer (current-buffer)))
-       (org-refile-for-capture t))
-    (save-window-excursion
-      (with-current-buffer (or base (current-buffer))
-       (save-excursion
-         (save-restriction
-           (widen)
-           (goto-char pos)
-           (call-interactively 'org-refile)))))
-    (org-capture-finalize)))
+    (user-error "Refiling from a capture buffer makes only sense \
+for `entry'-type templates"))
+  (let* ((base (or (buffer-base-buffer) (current-buffer)))
+        (pos (make-marker))
+        (org-capture-is-refiling t)
+        (kill-buffer (org-capture-get :kill-buffer 'local)))
+    ;; Since `org-capture-finalize' may alter buffer contents (e.g.,
+    ;; empty lines) around entry, use a marker to refer to the
+    ;; headline to be refiled.  Place the marker in the base buffer,
+    ;; as the current indirect one is going to be killed.
+    (set-marker pos (save-excursion (org-back-to-heading t) (point)) base)
+    (org-capture-put :kill-buffer nil)
+    (unwind-protect
+       (progn
+         (org-capture-finalize)
+         (save-window-excursion
+           (with-current-buffer base
+             (org-with-wide-buffer
+              (goto-char pos)
+              (call-interactively 'org-refile))))
+         (when kill-buffer (kill-buffer base)))
+      (set-marker pos nil))))
 
 (defun org-capture-kill ()
   "Abort the current capture process."
@@ -813,7 +846,8 @@ already gone.  Any prefix argument will be passed to the 
refile command."
   "Go to the location where the last capture note was stored."
   (interactive)
   (org-goto-marker-or-bmk org-capture-last-stored-marker
-                         "org-capture-last-stored")
+                         (plist-get org-bookmark-names-plist
+                                :last-capture))
   (message "This is the last note stored by a capture process"))
 
 ;;; Supporting functions for handling the process
@@ -823,7 +857,7 @@ already gone.  Any prefix argument will be passed to the 
refile command."
   (org-capture-put
    :initial-target-region
    ;; Check if the buffer is currently narrowed
-   (when (/= (buffer-size) (- (point-max) (point-min)))
+   (when (org-buffer-narrowed-p)
      (cons (point-min) (point-max))))
   ;; store the current point
   (org-capture-put :initial-target-position (point)))
@@ -853,14 +887,14 @@ Store them in the capture property list."
 
        ((eq (car target) 'file+headline)
        (set-buffer (org-capture-target-buffer (nth 1 target)))
+       (unless (derived-mode-p 'org-mode)
+         (error
+          "Target buffer \"%s\" for file+headline should be in Org mode"
+          (current-buffer)))
        (org-capture-put-target-region-and-position)
        (widen)
        (let ((hd (nth 2 target)))
          (goto-char (point-min))
-         (unless (derived-mode-p 'org-mode)
-           (error
-            "Target buffer \"%s\" for file+headline should be in Org mode"
-            (current-buffer)))
          (if (re-search-forward
               (format org-complex-heading-regexp-format (regexp-quote hd))
               nil t)
@@ -892,21 +926,29 @@ Store them in the capture property list."
              (setq target-entry-p (and (derived-mode-p 'org-mode) 
(org-at-heading-p))))
          (error "No match for target regexp in file %s" (nth 1 target))))
 
-       ((memq (car target) '(file+datetree file+datetree+prompt))
+       ((memq (car target) '(file+datetree file+datetree+prompt file+weektree 
file+weektree+prompt))
        (require 'org-datetree)
        (set-buffer (org-capture-target-buffer (nth 1 target)))
+       (unless (derived-mode-p 'org-mode)
+         (error "Target buffer \"%s\" for %s should be in Org mode"
+                (current-buffer)
+                (car target)))
        (org-capture-put-target-region-and-position)
        (widen)
-       ;; Make a date tree entry, with the current date (or yesterday,
-       ;; if we are extending dates for a couple of hours)
-       (org-datetree-find-date-create
+       ;; Make a date/week tree entry, with the current date (or
+       ;; yesterday, if we are extending dates for a couple of hours)
+       (funcall
+        (cond
+         ((memq (car target) '(file+weektree file+weektree+prompt))
+          #'org-datetree-find-iso-week-create)
+         (t #'org-datetree-find-date-create))
         (calendar-gregorian-from-absolute
          (cond
           (org-overriding-default-time
            ;; use the overriding default time
            (time-to-days org-overriding-default-time))
 
-          ((eq (car target) 'file+datetree+prompt)
+          ((memq (car target) '(file+datetree+prompt file+weektree+prompt))
            ;; prompt for date
            (let ((prompt-time (org-read-date
                                nil t nil "Date for tree entry:"
@@ -917,7 +959,9 @@ Store them in the capture property list."
                               (not org-time-was-given))
                           (not (= (time-to-days prompt-time) (org-today))))
                      ;; Use 00:00 when no time is given for another date than 
today?
-                     (apply 'encode-time (append '(0 0 0) (cdddr (decode-time 
prompt-time)))))
+                     (apply #'encode-time
+                            (append '(0 0 0)
+                                    (cl-cdddr (decode-time prompt-time)))))
                     ((string-match "\\([^ ]+\\)--?[^ ]+[ ]+\\(.*\\)" 
org-read-date-final-answer)
                      ;; Replace any time range by its start
                      (apply 'encode-time
@@ -964,31 +1008,31 @@ Store them in the capture property list."
                       :decrypted decrypted-hl-pos))))
 
 (defun org-capture-expand-file (file)
-  "Expand functions and symbols for FILE.
+  "Expand functions, symbols and file names for FILE.
 When FILE is a function, call it.  When it is a form, evaluate
-it.  When it is a variable, retrieve the value.  Return whatever we get."
+it.  When it is a variable, retrieve the value.  When it is
+a string, treat it as a file name, possibly expanding it
+according to `org-directory', and return it.  If it is the empty
+string, however, return `org-default-notes-file'.  In any other
+case, raise an error."
   (cond
-   ((org-string-nw-p file) file)
+   ((equal file "") org-default-notes-file)
+   ((stringp file) (expand-file-name file org-directory))
    ((functionp file) (funcall file))
    ((and (symbolp file) (boundp file)) (symbol-value file))
-   ((and file (consp file)) (eval file))
+   ((consp file) (eval file))
    (t file)))
 
 (defun org-capture-target-buffer (file)
-  "Get a buffer for FILE."
-  (setq file (org-capture-expand-file file))
-  (setq file (or (org-string-nw-p file)
-                org-default-notes-file
-                (error "No notes file specified, and no default available")))
-  (or (org-find-base-buffer-visiting file)
-      (progn (org-capture-put :new-buffer t)
-            (find-file-noselect (expand-file-name file org-directory)))))
-
-(defun org-capture-steal-local-variables (buffer)
-  "Install Org-mode local variables of BUFFER."
-  (mapc (lambda (v)
-         (ignore-errors (org-set-local (car v) (cdr v))))
-       (buffer-local-variables buffer)))
+  "Get a buffer for FILE.
+FILE is a generalized file location, as handled by
+`org-capture-expand-file'."
+  (let ((file (or (org-string-nw-p (org-capture-expand-file file))
+                 org-default-notes-file
+                 (error "No notes file specified, and no default available"))))
+    (or (org-find-base-buffer-visiting file)
+       (progn (org-capture-put :new-buffer t)
+              (find-file-noselect file)))))
 
 (defun org-capture-place-template (&optional inhibit-wconf-store)
   "Insert the template at the target location, and display the buffer.
@@ -1000,65 +1044,52 @@ may have been stored before."
   (org-switch-to-buffer-other-window
    (org-capture-get-indirect-buffer (org-capture-get :buffer) "CAPTURE"))
   (widen)
-  (show-all)
+  (outline-show-all)
   (goto-char (org-capture-get :pos))
-  (org-set-local 'org-capture-target-marker
-                (point-marker))
-  (org-set-local 'outline-level 'org-outline-level)
-  (let* ((template (org-capture-get :template))
-        (type (org-capture-get :type)))
-    (case type
-      ((nil entry) (org-capture-place-entry))
-      (table-line (org-capture-place-table-line))
-      (plain (org-capture-place-plain-text))
-      (item (org-capture-place-item))
-      (checkitem (org-capture-place-item))))
+  (setq-local outline-level 'org-outline-level)
+  (pcase (org-capture-get :type)
+    ((or `nil `entry) (org-capture-place-entry))
+    (`table-line (org-capture-place-table-line))
+    (`plain (org-capture-place-plain-text))
+    (`item (org-capture-place-item))
+    (`checkitem (org-capture-place-item)))
   (org-capture-mode 1)
-  (org-set-local 'org-capture-current-plist org-capture-plist))
+  (setq-local org-capture-current-plist org-capture-plist))
 
 (defun org-capture-place-entry ()
   "Place the template as a new Org entry."
-  (let* ((txt (org-capture-get :template))
-        (reversed (org-capture-get :prepend))
-        (target-entry-p (org-capture-get :target-entry-p))
-        level beg end file)
-
-    (cond
-     ((org-capture-get :exact-position)
+  (let ((reversed? (org-capture-get :prepend))
+       level)
+    (when (org-capture-get :exact-position)
       (goto-char (org-capture-get :exact-position)))
-     ((not target-entry-p)
-      ;; Insert as top-level entry, either at beginning or at end of file
-      (setq level 1)
-      (if reversed
-         (progn (goto-char (point-min))
-                (or (org-at-heading-p)
-                    (outline-next-heading)))
-       (goto-char (point-max))
-       (or (bolp) (insert "\n"))))
-     (t
-      ;; Insert as a child of the current entry
-      (and (looking-at "\\*+")
-          (setq level (- (match-end 0) (match-beginning 0))))
-      (setq level (org-get-valid-level (or level 1) 1))
-      (if reversed
-         (progn
-           (outline-next-heading)
-           (or (bolp) (insert "\n")))
-       (org-end-of-subtree t nil)
-       (or (bolp) (insert "\n")))))
+    (cond
+     ;; Insert as a child of the current entry.
+     ((org-capture-get :target-entry-p)
+      (setq level (org-get-valid-level
+                  (if (org-at-heading-p) (org-outline-level) 1)
+                  1))
+      (if reversed? (outline-next-heading) (org-end-of-subtree t)))
+     ;; Insert as a top-level entry at the beginning of the file.
+     (reversed?
+      (goto-char (point-min))
+      (unless (org-at-heading-p) (outline-next-heading)))
+     ;; Otherwise, insert as a top-level entry at the end of the file.
+     (t (goto-char (point-max))))
+    (unless (bolp) (insert "\n"))
     (org-capture-empty-lines-before)
-    (setq beg (point))
-    (org-capture-verify-tree txt)
-    (org-paste-subtree level txt 'for-yank)
-    (org-capture-empty-lines-after 1)
-    (org-capture-position-for-last-stored beg)
-    (outline-next-heading)
-    (setq end (point))
-    (org-capture-mark-kill-region beg (1- end))
-    (org-capture-narrow beg (1- end))
-    (if (or (re-search-backward "%\\?" beg t)
-           (re-search-forward "%\\?" end t))
-       (replace-match ""))))
+    (let ((beg (point))
+         (template (org-capture-get :template)))
+      (org-capture-verify-tree template)
+      (org-paste-subtree level template 'for-yank)
+      (org-capture-empty-lines-after)
+      (org-capture-position-for-last-stored beg)
+      (unless (org-at-heading-p) (outline-next-heading))
+      (let ((end (point)))
+       (org-capture-mark-kill-region beg end)
+       (org-capture-narrow beg end)
+       (when (or (re-search-backward "%\\?" beg t)
+                 (re-search-forward "%\\?" end t))
+         (replace-match ""))))))
 
 (defun org-capture-place-item ()
   "Place the template as a new plain list item."
@@ -1075,21 +1106,18 @@ may have been stored before."
        (t
        (setq beg (1+ (point-at-eol))
              end (save-excursion (outline-next-heading) (point)))))
+      (setq ind nil)
       (if (org-capture-get :prepend)
          (progn
            (goto-char beg)
-           (if (org-list-search-forward (org-item-beginning-re) end t)
-               (progn
-                 (goto-char (match-beginning 0))
-                 (setq ind (org-get-indentation)))
-             (goto-char end)
-             (setq ind 0)))
+           (when (org-list-search-forward (org-item-beginning-re) end t)
+             (goto-char (match-beginning 0))
+             (setq ind (org-get-indentation))))
        (goto-char end)
-       (if (org-list-search-backward (org-item-beginning-re) beg t)
-           (progn
-             (setq ind (org-get-indentation))
-             (org-end-of-item))
-         (setq ind 0))))
+       (when (org-list-search-backward (org-item-beginning-re) beg t)
+         (setq ind (org-get-indentation))
+         (org-end-of-item)))
+      (unless ind (goto-char end)))
     ;; Remove common indentation
     (setq txt (org-remove-indentation txt))
     ;; Make sure this is indeed an item
@@ -1097,18 +1125,23 @@ may have been stored before."
       (setq txt (concat "- "
                        (mapconcat 'identity (split-string txt "\n")
                                   "\n  "))))
+    ;; Prepare surrounding empty lines.
+    (org-capture-empty-lines-before)
+    (setq beg (point))
+    (unless (eolp) (save-excursion (insert "\n")))
+    (unless ind
+      (org-indent-line)
+      (setq ind (org-get-indentation))
+      (delete-region beg (point)))
     ;; Set the correct indentation, depending on context
     (setq ind (make-string ind ?\ ))
     (setq txt (concat ind
                      (mapconcat 'identity (split-string txt "\n")
                                 (concat "\n" ind))
                      "\n"))
-    ;; Insert, with surrounding empty lines
-    (org-capture-empty-lines-before)
-    (setq beg (point))
+    ;; Insert item.
     (insert txt)
-    (or (bolp) (insert "\n"))
-    (org-capture-empty-lines-after 1)
+    (org-capture-empty-lines-after)
     (org-capture-position-for-last-stored beg)
     (forward-char 1)
     (setq end (point))
@@ -1124,7 +1157,7 @@ may have been stored before."
   (let* ((txt (org-capture-get :template))
         (target-entry-p (org-capture-get :target-entry-p))
         (table-line-pos (org-capture-get :table-line-pos))
-        ind beg end)
+        beg end)
     (cond
      ((org-capture-get :exact-position)
       (goto-char (org-capture-get :exact-position)))
@@ -1149,21 +1182,24 @@ may have been stored before."
     ;; Check if the template is good
     (if (not (string-match org-table-dataline-regexp txt))
        (setq txt "| %?Bad template |\n"))
+    (if (functionp table-line-pos)
+       (setq table-line-pos (funcall table-line-pos))
+      (setq table-line-pos (eval table-line-pos)))
     (cond
      ((and table-line-pos
           (string-match "\\(I+\\)\\([-+][0-9]\\)" table-line-pos))
-      ;; we have a complex line specification
       (goto-char (point-min))
-      (let ((nh (- (match-end 1) (match-beginning 1)))
-           (delta (string-to-number (match-string 2 table-line-pos)))
-           ll)
+      ;; we have a complex line specification
+      (let ((ll (ignore-errors
+                 (save-match-data (org-table-analyze))
+                 (aref org-table-hlines
+                       (- (match-end 1) (match-beginning 1)))))
+           (delta (string-to-number (match-string 2 table-line-pos))))
        ;; The user wants a special position in the table
-       (org-table-get-specials)
-       (setq ll (ignore-errors (aref org-table-hlines nh)))
-       (unless ll (error "Invalid table line specification \"%s\""
-                         table-line-pos))
-       (setq ll (+ ll delta (if (< delta 0) 0 -1)))
-       (org-goto-line ll)
+       (unless ll
+         (error "Invalid table line specification \"%s\"" table-line-pos))
+       (goto-char org-table-current-begin-pos)
+       (forward-line (+ ll delta (if (< delta 0) 0 -1)))
        (org-table-insert-row 'below)
        (beginning-of-line 1)
        (delete-region (point) (1+ (point-at-eol)))
@@ -1216,7 +1252,7 @@ Of course, if exact position has been required, just put 
it there."
       ;; we should place the text into this entry
       (if (org-capture-get :prepend)
          ;; Skip meta data and drawers
-         (org-end-of-meta-data-and-drawers)
+         (org-end-of-meta-data t)
        ;; go to ent of the entry text, before the next headline
        (outline-next-heading)))
      (t
@@ -1226,7 +1262,7 @@ Of course, if exact position has been required, just put 
it there."
     (org-capture-empty-lines-before)
     (setq beg (point))
     (insert txt)
-    (org-capture-empty-lines-after 1)
+    (org-capture-empty-lines-after)
     (org-capture-position-for-last-stored beg)
     (setq end (point))
     (org-capture-mark-kill-region beg (1- end))
@@ -1256,8 +1292,8 @@ Of course, if exact position has been required, just put 
it there."
                           (org-table-current-dline))))
    (t (error "This should not happen"))))
 
-(defun org-capture-bookmark-last-stored-position ()
-  "Bookmark the last-captured position."
+(defun org-capture-store-last-position ()
+  "Store the last-captured position."
   (let* ((where (org-capture-get :position-for-last-stored 'local))
         (pos (cond
               ((markerp where)
@@ -1270,16 +1306,11 @@ Of course, if exact position has been required, just 
put it there."
                      (point-at-bol))
                  (point))))))
     (with-current-buffer (buffer-base-buffer (current-buffer))
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char pos)
-         (let ((bookmark-name (plist-get org-bookmark-names-plist
-                                         :last-capture)))
-           (when bookmark-name
-             (with-demoted-errors
-               (bookmark-set bookmark-name))))
-         (move-marker org-capture-last-stored-marker (point)))))))
+      (org-with-point-at pos
+       (when org-capture-bookmark
+         (let ((bookmark (plist-get org-bookmark-names-plist :last-capture)))
+           (when bookmark (with-demoted-errors (bookmark-set bookmark)))))
+       (move-marker org-capture-last-stored-marker (point))))))
 
 (defun org-capture-narrow (beg end)
   "Narrow, unless configuration says not to narrow."
@@ -1315,7 +1346,7 @@ Point will remain at the first line after the inserted 
text."
   (let* ((template (org-capture-get :template))
         (type  (org-capture-get :type))
         beg end pp)
-    (or (bolp) (newline))
+    (unless (bolp) (insert "\n"))
     (setq beg (point))
     (cond
      ((and (eq type 'entry) (derived-mode-p 'org-mode))
@@ -1337,13 +1368,16 @@ Point will remain at the first line after the inserted 
text."
       (org-capture-empty-lines-after)
       (goto-char beg)
       (org-list-repair)
-      (org-end-of-item)
-      (setq end (point)))
-     (t (insert template)))
+      (org-end-of-item))
+     (t
+      (insert template)
+      (org-capture-empty-lines-after)
+      (skip-chars-forward " \t\n")
+      (unless (eobp) (beginning-of-line))))
     (setq end (point))
     (goto-char beg)
-    (if (re-search-forward "%\\?" end t)
-       (replace-match ""))))
+    (when (re-search-forward "%\\?" end t)
+      (replace-match ""))))
 
 (defun org-capture-set-plist (entry)
   "Initialize the property list from the template definition."
@@ -1365,13 +1399,11 @@ Point will remain at the first line after the inserted 
text."
   "Go to the target location of a capture template.
 The user is queried for the template."
   (interactive)
-  (let* (org-select-template-temp-major-mode
-        (entry (org-capture-select-template template-key)))
-    (unless entry
-      (error "No capture template selected"))
+  (let ((entry (org-capture-select-template template-key)))
+    (unless entry (error "No capture template selected"))
     (org-capture-set-plist entry)
     (org-capture-set-target-location)
-    (org-pop-to-buffer-same-window (org-capture-get :buffer))
+    (pop-to-buffer-same-window (org-capture-get :buffer))
     (goto-char (org-capture-get :pos))))
 
 (defun org-capture-get-indirect-buffer (&optional buffer prefix)
@@ -1381,7 +1413,7 @@ Use PREFIX as a prefix for the name of the indirect 
buffer."
   (let ((n 1) (base (buffer-name buffer)) bname)
     (setq bname (concat prefix "-" base))
     (while (buffer-live-p (get-buffer bname))
-      (setq bname (concat prefix "-" (number-to-string (incf n)) "-" base)))
+      (setq bname (concat prefix "-" (number-to-string (cl-incf n)) "-" base)))
     (condition-case nil
         (make-indirect-buffer buffer bname 'clone)
       (error
@@ -1396,6 +1428,7 @@ Use PREFIX as a prefix for the name of the indirect 
buffer."
 
 (defun org-mks (table title &optional prompt specials)
   "Select a member of an alist with multiple keys.
+
 TABLE is the alist which should contain entries where the car is a string.
 There should be two types of entries.
 
@@ -1403,7 +1436,7 @@ There should be two types of entries.
    This indicates that `a' is a prefix key for multi-letter selection, and
    that there are entries following with keys like \"ab\", \"ax\"...
 
-2. Selectable members must have more than two elements, with the first
+2. Select-able members must have more than two elements, with the first
    being the string of keys that lead to selecting it, and the second a
    short description string of the item.
 
@@ -1414,84 +1447,72 @@ When you press a prefix key, the commands (and maybe 
further prefixes)
 under this key will be shown and offered for selection.
 
 TITLE will be placed over the selection in the temporary buffer,
-PROMPT will be used when prompting for a key.  SPECIAL is an alist with
-also (\"key\" \"description\") entries.  When one of these is selection,
-only the bare key is returned."
-  (setq prompt (or prompt "Select: "))
-  (let (tbl orig-table dkey ddesc des-keys allowed-keys
-           current prefix rtn re pressed buffer (inhibit-quit t))
-    (save-window-excursion
-      (setq buffer (org-switch-to-buffer-other-window "*Org Select*"))
-      (setq orig-table table)
-      (catch 'exit
-       (while t
-         (erase-buffer)
-         (insert title "\n\n")
-         (setq tbl table
-               des-keys nil
-               allowed-keys nil
-               cursor-type nil)
-         (setq prefix (if current (concat current " ") ""))
-         (while tbl
-           (cond
-            ((and (= 2 (length (car tbl))) (= (length (caar tbl)) 1))
-             ;; This is a description on this level
-             (setq dkey (caar tbl) ddesc (cadar tbl))
-             (pop tbl)
-             (push dkey des-keys)
-             (push dkey allowed-keys)
-             (insert prefix "[" dkey "]" "..." "  " ddesc "..." "\n")
-             ;; Skip keys which are below this prefix
-             (setq re (concat "\\`" (regexp-quote dkey)))
-             (let (case-fold-search)
-               (while (and tbl (string-match re (caar tbl))) (pop tbl))))
-            ((= 2 (length (car tbl)))
-             ;; Not yet a usable description, skip it
-             )
-            (t
-             ;; usable entry on this level
-             (insert prefix "[" (caar tbl) "]" "     " (nth 1 (car tbl)) "\n")
-             (push (caar tbl) allowed-keys)
-             (pop tbl))))
-         (when specials
-           (insert 
"-------------------------------------------------------------------------------\n")
-           (let ((sp specials))
-             (while sp
-               (insert (format "[%s]     %s\n"
-                               (caar sp) (nth 1 (car sp))))
-               (push (caar sp) allowed-keys)
-               (pop sp))))
-         (push "\C-g" allowed-keys)
-         (goto-char (point-min))
-         (if (not (pos-visible-in-window-p (point-max)))
-             (org-fit-window-to-buffer))
-         (message prompt)
-         (setq pressed (char-to-string (read-char-exclusive)))
-         (while (not (member pressed allowed-keys))
-           (message "Invalid key `%s'" pressed) (sit-for 1)
-           (message prompt)
-           (setq pressed (char-to-string (read-char-exclusive))))
-         (when (equal pressed "\C-g")
-           (kill-buffer buffer)
-           (error "Abort"))
-         (when (and (not (assoc pressed table))
-                    (not (member pressed des-keys))
-                    (assoc pressed specials))
-           (throw 'exit (setq rtn pressed)))
-         (unless (member pressed des-keys)
-           (throw 'exit (setq rtn (rassoc (cdr (assoc pressed table))
-                                          orig-table))))
-         (setq current (concat current pressed))
-         (setq table (mapcar
-                      (lambda (x)
-                        (if (and (> (length (car x)) 1)
-                                 (equal (substring (car x) 0 1) pressed))
-                            (cons (substring (car x) 1) (cdr x))
-                          nil))
-                      table))
-         (setq table (remove nil table)))))
-    (when buffer (kill-buffer buffer))
-    rtn))
+PROMPT will be used when prompting for a key.  SPECIAL is an
+alist with (\"key\" \"description\") entries.  When one of these
+is selected, only the bare key is returned."
+  (save-window-excursion
+    (let ((inhibit-quit t)
+         (buffer (org-switch-to-buffer-other-window "*Org Select*"))
+         (prompt (or prompt "Select: "))
+         current)
+      (unwind-protect
+         (catch 'exit
+           (while t
+             (erase-buffer)
+             (insert title "\n\n")
+             (let ((des-keys nil)
+                   (allowed-keys '("\C-g"))
+                   (cursor-type nil))
+               ;; Populate allowed keys and descriptions keys
+               ;; available with CURRENT selector.
+               (let ((re (format "\\`%s\\(.\\)\\'"
+                                 (if current (regexp-quote current) "")))
+                     (prefix (if current (concat current " ") "")))
+                 (dolist (entry table)
+                   (pcase entry
+                     ;; Description.
+                     (`(,(and key (pred (string-match re))) ,desc)
+                      (let ((k (match-string 1 key)))
+                        (push k des-keys)
+                        (push k allowed-keys)
+                        (insert prefix "[" k "]" "..." "  " desc "..." "\n")))
+                     ;; Usable entry.
+                     (`(,(and key (pred (string-match re))) ,desc . ,_)
+                      (let ((k (match-string 1 key)))
+                        (insert prefix "[" k "]" "     " desc "\n")
+                        (push k allowed-keys)))
+                     (_ nil))))
+               ;; Insert special entries, if any.
+               (when specials
+                 (insert "----------------------------------------------------\
+---------------------------\n")
+                 (pcase-dolist (`(,key ,description) specials)
+                   (insert (format "[%s]     %s\n" key description))
+                   (push key allowed-keys)))
+               ;; Display UI and let user select an entry or
+               ;; a sub-level prefix.
+               (goto-char (point-min))
+               (unless (pos-visible-in-window-p (point-max))
+                 (org-fit-window-to-buffer))
+               (message prompt)
+               (let ((pressed (char-to-string (read-char-exclusive))))
+                 (while (not (member pressed allowed-keys))
+                   (message "Invalid key `%s'" pressed) (sit-for 1)
+                   (message prompt)
+                   (setq pressed (char-to-string (read-char-exclusive))))
+                 (setq current (concat current pressed))
+                 (cond
+                  ((equal pressed "\C-g") (user-error "Abort"))
+                  ;; Selection is a prefix: open a new menu.
+                  ((member pressed des-keys))
+                  ;; Selection matches an association: return it.
+                  ((let ((entry (assoc current table)))
+                     (and entry (throw 'exit entry))))
+                  ;; Selection matches a special entry: return the
+                  ;; selection prefix.
+                  ((assoc current specials) (throw 'exit current))
+                  (t (error "No entry available")))))))
+       (when buffer (kill-buffer buffer))))))
 
 ;;; The template code
 (defun org-capture-select-template (&optional keys)
@@ -1511,46 +1532,41 @@ Lisp programs can force the template by setting KEYS to 
a string."
               '(("C" "Customize org-capture-templates")
                 ("q" "Abort"))))))
 
+(defvar org-capture--clipboards nil
+  "List various clipboards values.")
+
 (defun org-capture-fill-template (&optional template initial annotation)
   "Fill a template and return the filled template as a string.
 The template may still contain \"%?\" for cursor positioning."
-  (setq template (or template (org-capture-get :template)))
-  (when (stringp initial)
-    (setq initial (org-no-properties initial)))
-  (let* ((buffer (org-capture-get :buffer))
+  (let* ((template (or template (org-capture-get :template)))
+        (buffer (org-capture-get :buffer))
         (file (buffer-file-name (or (buffer-base-buffer buffer) buffer)))
-        (ct (org-capture-get :default-time))
-        (dct (decode-time ct))
-        (ct1
-         (if (< (nth 2 dct) org-extend-today-until)
-             (encode-time 0 59 23 (1- (nth 3 dct)) (nth 4 dct) (nth 5 dct))
-           ct))
-        (plist-p (if org-store-link-plist t nil))
-        (v-c (and (> (length kill-ring) 0) (current-kill 0)))
+        (time (let* ((c (or (org-capture-get :default-time) (current-time)))
+                     (d (decode-time c)))
+                (if (< (nth 2 d) org-extend-today-until)
+                    (encode-time 0 59 23 (1- (nth 3 d)) (nth 4 d) (nth 5 d))
+                  c)))
+        (v-t (format-time-string (org-time-stamp-format nil) time))
+        (v-T (format-time-string (org-time-stamp-format t) time))
+        (v-u (format-time-string (org-time-stamp-format nil t) time))
+        (v-U (format-time-string (org-time-stamp-format t t) time))
+        (v-c (and kill-ring (current-kill 0)))
         (v-x (or (org-get-x-clipboard 'PRIMARY)
                  (org-get-x-clipboard 'CLIPBOARD)
                  (org-get-x-clipboard 'SECONDARY)))
-        (v-t (format-time-string (car org-time-stamp-formats) ct1))
-        (v-T (format-time-string (cdr org-time-stamp-formats) ct1))
-        (v-u (concat "[" (substring v-t 1 -1) "]"))
-        (v-U (concat "[" (substring v-T 1 -1) "]"))
-        ;; `initial' and `annotation' might habe been passed.
-        ;; But if the property list has them, we prefer those values
+        ;; `initial' and `annotation' might have been passed.  But if
+        ;; the property list has them, we prefer those values.
         (v-i (or (plist-get org-store-link-plist :initial)
-                 initial
+                 (and (stringp initial) (org-no-properties initial))
                  (org-capture-get :initial)
                  ""))
-        (v-a (or (plist-get org-store-link-plist :annotation)
-                 annotation
-                 (org-capture-get :annotation)
-                 ""))
-        ;; Is the link empty?  Then we do not want it...
-        (v-a (if (equal v-a "[[]]") "" v-a))
-        (clipboards (remove nil (list v-i
-                                      (org-get-x-clipboard 'PRIMARY)
-                                      (org-get-x-clipboard 'CLIPBOARD)
-                                      (org-get-x-clipboard 'SECONDARY)
-                                      v-c)))
+        (v-a
+         (let ((a (or (plist-get org-store-link-plist :annotation)
+                      annotation
+                      (org-capture-get :annotation)
+                      "")))
+           ;; Is the link empty?  Then we do not want it...
+           (if (equal a "[[]]") "" a)))
         (l-re "\\[\\[\\(.*?\\)\\]\\(\\[.*?\\]\\)?\\]")
         (v-A (if (and v-a (string-match l-re v-a))
                  (replace-match "[[\\1][%^{Link description}]]" nil nil v-a)
@@ -1559,202 +1575,260 @@ The template may still contain \"%?\" for cursor 
positioning."
                  (replace-match "\\1" nil nil v-a)
                v-a))
         (v-n user-full-name)
-        (v-k (if (marker-buffer org-clock-marker)
-                 (org-no-properties org-clock-heading)))
+        (v-k (and (marker-buffer org-clock-marker)
+                  (org-no-properties org-clock-heading)))
         (v-K (if (marker-buffer org-clock-marker)
                  (org-make-link-string
                   (buffer-file-name (marker-buffer org-clock-marker))
                   org-clock-heading)))
         (v-f (or (org-capture-get :original-file-nondirectory) ""))
         (v-F (or (org-capture-get :original-file) ""))
-        v-I
-        (org-startup-folded nil)
-        (org-inhibit-startup t)
-        org-time-was-given org-end-time-was-given x
-        prompt completions char time pos default histvar strings)
-
-    (setq org-store-link-plist
-         (plist-put org-store-link-plist :annotation v-a)
-         org-store-link-plist
-         (plist-put org-store-link-plist :initial v-i))
-    (setq initial v-i)
-
-    (unless template (setq template "") (message "No template") (ding)
-           (sit-for 1))
+        (org-capture--clipboards
+         (delq nil
+               (list v-i
+                     (org-get-x-clipboard 'PRIMARY)
+                     (org-get-x-clipboard 'CLIPBOARD)
+                     (org-get-x-clipboard 'SECONDARY)
+                     v-c))))
+
+    (setq org-store-link-plist (plist-put org-store-link-plist :annotation 
v-a))
+    (setq org-store-link-plist (plist-put org-store-link-plist :initial v-i))
+
+    (unless template
+      (setq template "")
+      (message "no template") (ding)
+      (sit-for 1))
     (save-window-excursion
-      (delete-other-windows)
-      (org-pop-to-buffer-same-window (get-buffer-create "*Capture*"))
+      (org-switch-to-buffer-other-window (get-buffer-create "*Capture*"))
       (erase-buffer)
+      (setq buffer-file-name nil)
+      (setq mark-active nil)
       (insert template)
       (goto-char (point-min))
-      (org-capture-steal-local-variables buffer)
-      (setq buffer-file-name nil mark-active nil)
 
-      ;; %[] Insert contents of a file.
-      (goto-char (point-min))
-      (while (re-search-forward "%\\[\\(.+\\)\\]" nil t)
-       (unless (org-capture-escaped-%)
-         (let ((start (match-beginning 0))
-               (end (match-end 0))
-               (filename (expand-file-name (match-string 1))))
-           (goto-char start)
-           (delete-region start end)
-           (condition-case error
-               (insert-file-contents filename)
-             (error (insert (format "%%![Could not insert %s: %s]"
-                                    filename error)))))))
-      ;; %() embedded elisp
-      (org-capture-expand-embedded-elisp)
+      ;; %[] insert contents of a file.
+      (save-excursion
+       (while (re-search-forward "%\\[\\(.+\\)\\]" nil t)
+         (let ((filename (expand-file-name (match-string 1)))
+               (beg (copy-marker (match-beginning 0)))
+               (end (copy-marker (match-end 0))))
+           (unless (org-capture-escaped-%)
+             (delete-region beg end)
+             (set-marker beg nil)
+             (set-marker end nil)
+             (condition-case error
+                 (insert-file-contents filename)
+               (error
+                (insert (format "%%![couldn not insert %s: %s]"
+                                filename
+                                error))))))))
 
-      ;; The current time
-      (goto-char (point-min))
-      (while (re-search-forward "%<\\([^>\n]+\\)>" nil t)
-       (replace-match (format-time-string (match-string 1)) t t))
+      ;; Mark %() embedded elisp for later evaluation.
+      (org-capture-expand-embedded-elisp 'mark)
 
-      ;; Simple %-escapes
-      (goto-char (point-min))
-      (while (re-search-forward "%\\([tTuUaliAcxkKInfF]\\)" nil t)
-       (unless (org-capture-escaped-%)
-         (when (and initial (equal (match-string 0) "%i"))
-           (save-match-data
-             (let* ((lead (buffer-substring
-                           (point-at-bol) (match-beginning 0))))
-               (setq v-i (mapconcat 'identity
-                                    (org-split-string initial "\n")
-                                    (concat "\n" lead))))))
-         (replace-match (or (eval (intern (concat "v-" (match-string 1)))) "")
-                        t t)))
-
-      ;; From the property list
-      (when plist-p
-       (goto-char (point-min))
-       (while (re-search-forward "%\\(:[-a-zA-Z]+\\)" nil t)
-         (unless (org-capture-escaped-%)
-           (and (setq x (or (plist-get org-store-link-plist
-                                       (intern (match-string 1))) ""))
-                (replace-match x t t)))))
-
-      ;; Turn on org-mode in temp buffer, set local variables
-      ;; This is to support completion in interactive prompts
+      ;; Expand non-interactive templates.
+      (let ((regexp 
"%\\(:[-a-za-z]+\\|<\\([^>\n]+\\)>\\|[aAcfFikKlntTuUx]\\)"))
+       (save-excursion
+         (while (re-search-forward regexp nil t)
+           ;; `org-capture-escaped-%' may modify buffer and cripple
+           ;; match-data.  Use markers instead.  Ditto for other
+           ;; templates.
+           (let ((pos (copy-marker (match-beginning 0)))
+                 (end (copy-marker (match-end 0)))
+                 (value (match-string 1))
+                 (time-string (match-string 2)))
+             (unless (org-capture-escaped-%)
+               (delete-region pos end)
+               (set-marker pos nil)
+               (set-marker end nil)
+               (let* ((inside-sexp? (org-capture-inside-embedded-elisp-p))
+                      (replacement
+                       (pcase (string-to-char value)
+                         (?< (format-time-string time-string))
+                         (?:
+                          (or (plist-get org-store-link-plist (intern value))
+                              ""))
+                         (?i
+                          (if inside-sexp? v-i
+                            ;; Outside embedded Lisp, repeat leading
+                            ;; characters before initial place holder
+                            ;; every line.
+                            (let ((lead (buffer-substring-no-properties
+                                         (line-beginning-position) (point))))
+                              (replace-regexp-in-string "\n\\(.\\)"
+                                                        (concat lead "\\1")
+                                                        v-i nil nil 1))))
+                         (?a v-a)
+                         (?A v-A)
+                         (?c v-c)
+                         (?f v-f)
+                         (?F v-F)
+                         (?k v-k)
+                         (?K v-K)
+                         (?l v-l)
+                         (?n v-n)
+                         (?t v-t)
+                         (?T v-T)
+                         (?u v-u)
+                         (?U v-U)
+                         (?x v-x))))
+                 (insert
+                  (if inside-sexp?
+                      ;; Escape sensitive characters.
+                      (replace-regexp-in-string "[\\\"]" "\\\\\\&" replacement)
+                    replacement))))))))
+
+      ;; Expand %() embedded Elisp.  Limit to Sexp originally marked.
+      (org-capture-expand-embedded-elisp)
+
+      ;; Expand interactive templates.  This is the last step so that
+      ;; template is mostly expanded when prompting happens.  Turn on
+      ;; Org mode and set local variables.  This is to support
+      ;; completion in interactive prompts.
       (let ((org-inhibit-startup t)) (org-mode))
-      ;; Interactive template entries
-      (goto-char (point-min))
-      (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([gGtTuUCLp]\\)?" nil 
t)
-       (unless (org-capture-escaped-%)
-         (setq char (if (match-end 3) (match-string-no-properties 3))
-               prompt (if (match-end 2) (match-string-no-properties 2)))
-         (goto-char (match-beginning 0))
-         (replace-match "")
-         (setq completions nil default nil)
-         (when prompt
-           (setq completions (org-split-string prompt "|")
-                 prompt (pop completions)
-                 default (car completions)
-                 histvar (intern (concat
-                                  "org-capture-template-prompt-history::"
-                                  (or prompt "")))
-                 completions (mapcar 'list completions)))
-         (unless (boundp histvar) (set histvar nil))
-         (cond
-          ((member char '("G" "g"))
-           (let* ((org-last-tags-completion-table
-                   (org-global-tags-completion-table
-                    (if (equal char "G")
-                        (org-agenda-files)
-                      (and file (list file)))))
-                  (org-add-colon-after-tag-completion t)
-                  (ins (org-icompleting-read
-                        (if prompt (concat prompt ": ") "Tags: ")
-                        'org-tags-completion-function nil nil nil
-                        'org-tags-history)))
-             (setq ins (mapconcat 'identity
-                                  (org-split-string
-                                   ins (org-re "[^[:alnum:address@hidden"))
-                                  ":"))
-             (when (string-match "\\S-" ins)
-               (or (equal (char-before) ?:) (insert ":"))
-               (insert ins)
-               (or (equal (char-after) ?:) (insert ":"))
-               (and (org-at-heading-p)
-                    (let ((org-ignore-region t))
-                      (org-set-tags nil 'align))))))
-          ((equal char "C")
-           (cond ((= (length clipboards) 1) (insert (car clipboards)))
-                 ((> (length clipboards) 1)
-                  (insert (read-string "Clipboard/kill value: "
-                                       (car clipboards) '(clipboards . 1)
-                                       (car clipboards))))))
-          ((equal char "L")
-           (cond ((= (length clipboards) 1)
-                  (org-insert-link 0 (car clipboards)))
-                 ((> (length clipboards) 1)
-                  (org-insert-link 0 (read-string "Clipboard/kill value: "
-                                                  (car clipboards)
-                                                  '(clipboards . 1)
-                                                  (car clipboards))))))
-          ((equal char "p")
-           (org-set-property (org-no-properties prompt) nil))
-          (char
-           ;; These are the date/time related ones
-           (setq org-time-was-given (equal (upcase char) char))
-           (setq time (org-read-date (equal (upcase char) char) t nil
-                                     prompt))
-           (if (equal (upcase char) char) (setq org-time-was-given t))
-           (org-insert-time-stamp time org-time-was-given
-                                  (member char '("u" "U"))
-                                  nil nil (list org-end-time-was-given)))
-          (t
-           (let (org-completion-use-ido)
-             (push (org-completing-read-no-i
-                    (concat (if prompt prompt "Enter string")
-                            (if default (concat " [" default "]"))
-                            ": ")
-                    completions nil nil nil histvar default)
-                   strings)
-             (insert (car strings)))))))
-      ;; Replace %n escapes with nth %^{...} string
-      (setq strings (nreverse strings))
-      (goto-char (point-min))
-      (while (re-search-forward "%\\\\\\([1-9][0-9]*\\)" nil t)
-       (unless (org-capture-escaped-%)
-         (replace-match
-          (nth (1- (string-to-number (match-string 1))) strings)
-          nil t)))
+      (org-clone-local-variables buffer "\\`org-")
+      (let (strings)                   ; Stores interactive answers.
+       (save-excursion
+         (let ((regexp "%\\^\\(?:{\\([^}]*\\)}\\)?\\([CgGLptTuU]\\)?"))
+           (while (re-search-forward regexp nil t)
+             (let* ((items (and (match-end 1)
+                                (save-match-data
+                                  (split-string (match-string-no-properties 1)
+                                                "|"))))
+                    (key (match-string 2))
+                    (beg (copy-marker (match-beginning 0)))
+                    (end (copy-marker (match-end 0)))
+                    (prompt (nth 0 items))
+                    (default (nth 1 items))
+                    (completions (nthcdr 2 items)))
+               (unless (org-capture-escaped-%)
+                 (delete-region beg end)
+                 (set-marker beg nil)
+                 (set-marker end nil)
+                 (pcase key
+                   ((or "G" "g")
+                    (let* ((org-last-tags-completion-table
+                            (org-global-tags-completion-table
+                             (cond ((equal key "G") (org-agenda-files))
+                                   (file (list file))
+                                   (t nil))))
+                           (org-add-colon-after-tag-completion t)
+                           (ins (mapconcat
+                                 #'identity
+                                 (org-split-string
+                                  (completing-read
+                                   (if prompt (concat prompt ": ") "Tags: ")
+                                   'org-tags-completion-function nil nil nil
+                                   'org-tags-history)
+                                  "[^[:alnum:address@hidden")
+                                 ":")))
+                      (when (org-string-nw-p ins)
+                        (unless (eq (char-before) ?:) (insert ":"))
+                        (insert ins)
+                        (unless (eq (char-after) ?:) (insert ":"))
+                        (and (org-at-heading-p)
+                             (let ((org-ignore-region t))
+                               (org-set-tags nil 'align))))))
+                   ((or "C" "L")
+                    (let ((insert-fun (if (equal key "C") #'insert
+                                        (lambda (s) (org-insert-link 0 s)))))
+                      (pcase org-capture--clipboards
+                        (`nil nil)
+                        (`(,value) (funcall insert-fun value))
+                        (`(,first-value . ,_)
+                         (funcall insert-fun
+                                  (read-string "Clipboard/kill value: "
+                                               first-value
+                                               'org-capture--clipboards
+                                               first-value)))
+                        (_ (error "Invalid `org-capture--clipboards' value: %S"
+                                  org-capture--clipboards)))))
+                   ("p" (org-set-property prompt nil))
+                   ((guard key)
+                    ;; These are the date/time related ones.
+                    (let* ((upcase? (equal (upcase key) key))
+                           (org-time-was-given upcase?)
+                           (org-end-time-was-given)
+                           (time (org-read-date upcase? t nil prompt)))
+                      (org-insert-time-stamp
+                       time org-time-was-given
+                       (member key '("u" "U"))
+                       nil nil (list org-end-time-was-given))))
+                   (_
+                    (push (org-completing-read
+                           (concat (or prompt "Enter string")
+                                   (and default (format " [%s]" default))
+                                   ": ")
+                           completions nil nil nil nil default)
+                          strings)
+                    (insert (car strings)))))))))
+
+       ;; Replace %n escapes with nth %^{...} string.
+       (setq strings (nreverse strings))
+       (save-excursion
+         (while (re-search-forward "%\\\\\\([1-9][0-9]*\\)" nil t)
+           (unless (org-capture-escaped-%)
+             (replace-match
+              (nth (1- (string-to-number (match-string 1))) strings)
+              nil t)))))
+
       ;; Make sure there are no empty lines before the text, and that
-      ;; it ends with a newline character
-      (goto-char (point-min))
-      (while (looking-at "[ \t]*\n") (replace-match ""))
-      (if (re-search-forward "[ \t\n]*\\'" nil t) (replace-match "\n"))
-      ;; Return the expanded template and kill the temporary buffer
+      ;; it ends with a newline character.
+      (skip-chars-forward " \t\n")
+      (delete-region (point-min) (line-beginning-position))
+      (goto-char (point-max))
+      (skip-chars-backward " \t\n")
+      (delete-region (point) (point-max))
+      (insert "\n")
+
+      ;; Return the expanded template and kill the capture buffer.
       (untabify (point-min) (point-max))
       (set-buffer-modified-p nil)
-      (prog1 (buffer-string) (kill-buffer (current-buffer))))))
+      (prog1 (buffer-substring-no-properties (point-min) (point-max))
+       (kill-buffer (current-buffer))))))
 
 (defun org-capture-escaped-% ()
-  "Check if % was escaped - if yes, unescape it now."
-  (if (equal (char-before (match-beginning 0)) ?\\)
-      (progn
-       (delete-region (1- (match-beginning 0)) (match-beginning 0))
-       t)
-    nil))
-
-(defun org-capture-expand-embedded-elisp ()
-  "Evaluate embedded elisp %(sexp) and replace with the result."
-  (goto-char (point-min))
-  (while (re-search-forward "%(" nil t)
-    (unless (org-capture-escaped-%)
-      (goto-char (match-beginning 0))
-      (let ((template-start (point)))
-       (forward-char 1)
-       (let* ((sexp (read (current-buffer)))
-              (result (org-eval
-                       (org-capture--expand-keyword-in-embedded-elisp sexp))))
-         (delete-region template-start (point))
-         (when result
-           (if (stringp result)
-               (insert result)
-             (error "Capture template sexp `%s' must evaluate to string or nil"
-                    sexp))))))))
+  "Non-nil if % was escaped.
+If yes, unescape it now.  Assume match-data contains the
+placeholder to check."
+  (save-excursion
+    (goto-char (match-beginning 0))
+    (let ((n (abs (skip-chars-backward "\\\\"))))
+      (delete-char (/ (1+ n) 2))
+      (= (% n 2) 1))))
+
+(defun org-capture-expand-embedded-elisp (&optional mark)
+  "Evaluate embedded elisp %(sexp) and replace with the result.
+When optional MARK argument is non-nil, mark Sexp with a text
+property (`org-embedded-elisp') for later evaluation.  Only
+marked Sexp are evaluated when this argument is nil."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward "%(" nil t)
+      (cond
+       ((get-text-property (match-beginning 0) 'org-embedded-elisp)
+       (goto-char (match-beginning 0))
+       (let ((template-start (point)))
+         (forward-char 1)
+         (let* ((sexp (read (current-buffer)))
+                (result (org-eval
+                         (org-capture--expand-keyword-in-embedded-elisp
+                          sexp))))
+           (delete-region template-start (point))
+           (cond
+            ((not result) nil)
+            ((stringp result) (insert result))
+            (t (error
+                "Capture template sexp `%s' must evaluate to string or nil"
+                sexp))))))
+       ((not mark) nil)
+       ;; Only mark valid and non-escaped sexp.
+       ((org-capture-escaped-%) nil)
+       (t
+       (let ((end (with-syntax-table emacs-lisp-mode-syntax-table
+                    (ignore-errors (scan-sexps (1- (point)) 1)))))
+         (when end
+           (put-text-property (- (point) 2) end 'org-embedded-elisp t))))))))
 
 (defun org-capture--expand-keyword-in-embedded-elisp (attr)
   "Recursively replace capture link keywords in ATTR sexp.
@@ -1771,20 +1845,10 @@ Such keywords are prefixed with \"%:\".  See
        (t attr)))
 
 (defun org-capture-inside-embedded-elisp-p ()
-  "Return non-nil if point is inside of embedded elisp %(sexp)."
-  (let (beg end)
-    (with-syntax-table emacs-lisp-mode-syntax-table
-      (save-excursion
-       ;; `looking-at' and `search-backward' below do not match the "%(" if
-       ;; point is in its middle
-       (when (equal (char-before) ?%)
-         (backward-char))
-       (save-match-data
-         (when (or (looking-at "%(") (search-backward "%(" nil t))
-           (setq beg (point))
-           (setq end (progn (forward-char) (forward-sexp) (1- (point)))))))
-      (when (and beg end)
-       (and (<= (point) end) (>= (point) beg))))))
+  "Non-nil if point is inside of embedded elisp %(sexp).
+Assume sexps have been marked with
+`org-capture-expand-embedded-elisp' beforehand."
+  (get-text-property (point) 'org-embedded-elisp))
 
 ;;;###autoload
 (defun org-capture-import-remember-templates ()
@@ -1828,6 +1892,9 @@ Such keywords are prefixed with \"%:\".  See
                       (if jump-to-captured '(:jump-to-captured t)))))
 
           org-remember-templates))))
+;;; The function was made obsolete by commit 65399674d5 of
+;;; 2013-02-22.  This make-obsolete call was added 2016-09-01.
+(make-obsolete 'org-capture-import-remember-templates "use the 
`org-capture-templates' variable instead." "Org 9.0")
 
 (provide 'org-capture)
 
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 0bba925..cb6a6c9 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -1,4 +1,4 @@
-;;; org-clock.el --- The time clocking code for Org-mode
+;;; org-clock.el --- The time clocking code for Org mode -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,40 +24,49 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the time clocking code for Org-mode
+;; This file contains the time clocking code for Org mode
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'org)
 
 (declare-function calendar-iso-to-absolute "cal-iso" (date))
 (declare-function notifications-notify "notifications" (&rest params))
-(declare-function org-pop-to-buffer-same-window "org-compat" (&optional 
buffer-or-name norecord label))
-(declare-function org-refresh-properties "org" (dprop tprop))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-table-goto-line "org-table" (n))
+
+(defvar org-frame-title-format-backup frame-title-format)
 (defvar org-time-stamp-formats)
 (defvar org-ts-what)
-(defvar org-frame-title-format-backup frame-title-format)
+
 
 (defgroup org-clock nil
-  "Options concerning clocking working time in Org-mode."
+  "Options concerning clocking working time in Org mode."
   :tag "Org Clock"
   :group 'org-progress)
 
-(defcustom org-clock-into-drawer org-log-into-drawer
-  "Should clocking info be wrapped into a drawer?
-When t, clocking info will always be inserted into a :LOGBOOK: drawer.
-If necessary, the drawer will be created.
-When nil, the drawer will not be created, but used when present.
-When an integer and the number of clocking entries in an item
-reaches or exceeds this number, a drawer will be created.
-When a string, it names the drawer to be used.
-
-The default for this variable is the value of `org-log-into-drawer',
-which see."
+(defcustom org-clock-into-drawer t
+  "Non-nil when clocking info should be wrapped into a drawer.
+
+When non-nil, clocking info will be inserted into the same drawer
+as log notes (see variable `org-log-into-drawer'), if it exists,
+or \"LOGBOOK\" otherwise.  If necessary, the drawer will be
+created.
+
+When an integer, the drawer is created only when the number of
+clocking entries in an item reaches or exceeds this value.
+
+When a string, it becomes the name of the drawer, ignoring the
+log notes drawer altogether.
+
+Do not check directly this variable in a Lisp program.  Call
+function `org-clock-into-drawer' instead."
   :group 'org-todo
   :group 'org-clock
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(choice
          (const :tag "Always" t)
          (const :tag "Only when drawer exists" nil)
@@ -66,26 +75,29 @@ which see."
          (string :tag "Into Drawer named...")))
 
 (defun org-clock-into-drawer ()
-  "Return the value of `org-clock-into-drawer', but let properties overrule.
+  "Value of `org-clock-into-drawer'. but let properties overrule.
+
 If the current entry has or inherits a CLOCK_INTO_DRAWER
-property, it will be used instead of the default value; otherwise
-if the current entry has or inherits a LOG_INTO_DRAWER property,
-it will be used instead of the default value.
-The default is the value of the customizable variable `org-clock-into-drawer',
-which see."
-  (let ((p (org-entry-get nil "CLOCK_INTO_DRAWER" 'inherit))
-       (q (org-entry-get nil "LOG_INTO_DRAWER" 'inherit)))
-    (cond
-     ((or (not (or p q)) (equal p "nil") (equal q "nil")) 
org-clock-into-drawer)
-     ((or (equal p "t") (equal q "t")) "LOGBOOK")
-     ((not p) q)
-     (t p))))
+property, it will be used instead of the default value.
+
+Return value is either a string, an integer, or nil."
+  (let ((p (org-entry-get nil "CLOCK_INTO_DRAWER" 'inherit t)))
+    (cond ((equal p "nil") nil)
+         ((equal p "t") (or (org-log-into-drawer) "LOGBOOK"))
+          ((org-string-nw-p p)
+          (if (string-match-p "\\`[0-9]+\\'" p) (string-to-number p) p))
+         ((org-string-nw-p org-clock-into-drawer))
+         ((integerp org-clock-into-drawer) org-clock-into-drawer)
+         ((not org-clock-into-drawer) nil)
+         ((org-log-into-drawer))
+         (t "LOGBOOK"))))
 
 (defcustom org-clock-out-when-done t
   "When non-nil, clock will be stopped when the clocked entry is marked DONE.
+\\<org-mode-map>\
 DONE here means any DONE-like state.
 A nil value means clock will keep running until stopped explicitly with
-`C-c C-x C-o', or until the clock is started in a different item.
+`\\[org-clock-out]', or until the clock is started in a different item.
 Instead of t, this can also be a list of TODO states that should trigger
 clocking out."
   :group 'org-clock
@@ -223,9 +235,6 @@ file name  Play this sound file, fall back to beep"
          (const :tag "Standard beep" t)
          (file  :tag "Play sound file")))
 
-(define-obsolete-variable-alias 'org-clock-modeline-total
-  'org-clock-mode-line-total "24.3")
-
 (defcustom org-clock-mode-line-total 'auto
   "Default setting for the time included for the mode line clock.
 This can be overruled locally using the CLOCK_MODELINE_TOTAL property.
@@ -244,7 +253,7 @@ auto     Automatically, either `all', or `repeat' for 
repeating tasks"
          (const :tag "All task time" all)
          (const :tag "Automatically, `all' or since `repeat'" auto)))
 
-(org-defvaralias 'org-task-overrun-text 'org-clock-task-overrun-text)
+(defvaralias 'org-task-overrun-text 'org-clock-task-overrun-text)
 (defcustom org-clock-task-overrun-text nil
   "Extra mode line text to indicate that the clock is overrun.
 The can be nil to indicate that instead of adding text, the clock time
@@ -268,14 +277,14 @@ string as argument."
          (function :tag "Function")))
 
 (defgroup org-clocktable nil
-  "Options concerning the clock table in Org-mode."
+  "Options concerning the clock table in Org mode."
   :tag "Org Clock Table"
   :group 'org-clock)
 
 (defcustom org-clocktable-defaults
   (list
    :maxlevel 2
-   :lang (or (org-bound-and-true-p org-export-default-language) "en")
+   :lang (or (bound-and-true-p org-export-default-language) "en")
    :scope 'file
    :block nil
    :wstart 1
@@ -312,7 +321,9 @@ For more information, see `org-clocktable-write-default'."
   '(("en" "File"     "L"  "Timestamp"  "Headline" "Time"  "ALL"   "Total time" 
  "File time" "Clock summary at")
     ("es" "Archivo"  "N"  "Fecha y hora" "Tarea" "Tiempo" "TODO" "Tiempo 
total" "Tiempo archivo" "Clock summary at")
     ("fr" "Fichier"  "N"  "Horodatage" "En-tête"  "Durée" "TOUT"  "Durée 
totale" "Durée fichier" "Horodatage sommaire à")
-    ("nl" "Bestand"  "N"  "Tijdstip"   "Hoofding" "Duur"  "ALLES" "Totale 
duur"  "Bestandstijd" "Clock summary at"))
+    ("nl" "Bestand"  "N"  "Tijdstip"   "Hoofding" "Duur"  "ALLES" "Totale 
duur"  "Bestandstijd" "Clock summary at")
+    ("de" "Datei"    "E"  "Zeitstempel" "Kopfzeile" "Dauer" "GESAMT"
+     "Gesamtdauer"  "Dateizeit" "Erstellt am"))
   "Terms used in clocktable, translated to different languages."
   :group 'org-clocktable
   :version "24.1"
@@ -371,7 +382,7 @@ play with them."
   :type 'string)
 
 (defcustom org-clock-clocked-in-display 'mode-line
-  "When clocked in for a task, org-mode can display the current
+  "When clocked in for a task, Org can display the current
 task and accumulated time in the mode line and/or frame title.
 Allowed values are:
 
@@ -413,6 +424,26 @@ if you are using Debian."
   :package-version '(Org . "8.0")
   :type 'string)
 
+(defcustom org-clock-goto-before-context 2
+  "Number of lines of context to display before currently clocked-in entry.
+This applies when using `org-clock-goto'."
+  :group 'org-clock
+  :type 'integer)
+
+(defcustom org-clock-display-default-range 'thisyear
+  "Default range when displaying clocks with `org-clock-display'."
+  :group 'org-clock
+  :type '(choice (const today)
+                (const yesterday)
+                (const thisweek)
+                (const lastweek)
+                (const thismonth)
+                (const lastmonth)
+                (const thisyear)
+                (const lastyear)
+                (const untilnow)
+                (const :tag "Select range interactively" interactive)))
+
 (defvar org-clock-in-prepare-hook nil
   "Hook run when preparing the clock.
 This hook is run before anything happens to the task that
@@ -430,6 +461,33 @@ to add an effort property.")
 (defvar org-clock-has-been-used nil
   "Has the clock been used during the current Emacs session?")
 
+(defvar org-clock-stored-history nil
+  "Clock history, populated by `org-clock-load'")
+(defvar org-clock-stored-resume-clock nil
+  "Clock to resume, saved by `org-clock-load'")
+
+(defconst org-clock--oldest-date
+  (let* ((dichotomy
+         (lambda (min max pred)
+           (if (funcall pred min) min
+             (cl-incf min)
+             (while (> (- max min) 1)
+               (let ((mean (+ (ash min -1) (ash max -1) (logand min max 1))))
+                 (if (funcall pred mean) (setq max mean) (setq min mean)))))
+           max))
+        (high
+         (funcall dichotomy
+                  most-negative-fixnum
+                  0
+                  (lambda (m) (ignore-errors (decode-time (list m 0))))))
+        (low
+         (funcall dichotomy
+                  most-negative-fixnum
+                  0
+                  (lambda (m) (ignore-errors (decode-time (list high m)))))))
+    (list high low))
+  "Internal time for oldest date representable on the system.")
+
 ;;; The clock for measuring work time.
 
 (defvar org-mode-line-string "")
@@ -500,8 +558,17 @@ of a different task.")
   (org-check-and-save-marker org-clock-hd-marker beg end)
   (org-check-and-save-marker org-clock-default-task beg end)
   (org-check-and-save-marker org-clock-interrupted-task beg end)
-  (mapc (lambda (m) (org-check-and-save-marker m beg end))
-       org-clock-history))
+  (dolist (m org-clock-history)
+    (org-check-and-save-marker m beg end)))
+
+(defun org-clock-drawer-name ()
+  "Return clock drawer's name for current entry, or nil."
+  (let ((drawer (org-clock-into-drawer)))
+    (cond ((integerp drawer)
+          (let ((log-drawer (org-log-into-drawer)))
+            (if (stringp log-drawer) log-drawer "LOGBOOK")))
+         ((stringp drawer) drawer)
+         (t nil))))
 
 (defun org-clocking-buffer ()
   "Return the clocking buffer if we are currently clocking a task or nil."
@@ -519,8 +586,8 @@ of a different task.")
   (interactive)
   (let (och chl sel-list rpl (i 0) s)
     ;; Remove successive dups from the clock history to consider
-    (mapc (lambda (c) (if (not (equal c (car och))) (push c och)))
-         org-clock-history)
+    (dolist (c org-clock-history)
+      (unless (equal c (car och)) (push c och)))
     (setq och (reverse och) chl (length och))
     (if (zerop chl)
        (user-error "No recent clock")
@@ -541,17 +608,15 @@ of a different task.")
          (setq s (org-clock-insert-selection-line ?c org-clock-marker))
          (push s sel-list))
        (insert (org-add-props "Recent Tasks\n" nil 'face 'bold))
-       (mapc
-        (lambda (m)
-          (when (marker-buffer m)
-            (setq i (1+ i)
-                  s (org-clock-insert-selection-line
-                     (if (< i 10)
-                         (+ i ?0)
-                       (+ i (- ?A 10))) m))
-            (if (fboundp 'int-to-char) (setf (car s) (int-to-char (car s))))
-            (push s sel-list)))
-        och)
+       (dolist (m och)
+         (when (marker-buffer m)
+           (setq i (1+ i)
+                 s (org-clock-insert-selection-line
+                    (if (< i 10)
+                        (+ i ?0)
+                      (+ i (- ?A 10))) m))
+           (if (fboundp 'int-to-char) (setf (car s) (int-to-char (car s))))
+           (push s sel-list)))
        (run-hooks 'org-clock-before-select-task-hook)
        (goto-char (point-min))
        ;; Set min-height relatively to circumvent a possible but in
@@ -559,6 +624,7 @@ of a different task.")
        (fit-window-to-buffer nil nil (if (< chl 10) chl (+ 5 chl)))
        (message (or prompt "Select task for clocking:"))
        (setq cursor-type nil rpl (read-char-exclusive))
+       (kill-buffer)
        (cond
         ((eq rpl ?q) nil)
         ((eq rpl ?x) nil)
@@ -570,25 +636,22 @@ of a different task.")
 And return a cons cell with the selection character integer and the marker
 pointing to it."
   (when (marker-buffer marker)
-    (let (file cat task heading prefix)
+    (let (cat task heading prefix)
       (with-current-buffer (org-base-buffer (marker-buffer marker))
-       (save-excursion
-         (save-restriction
-           (widen)
-           (ignore-errors
-             (goto-char marker)
-             (setq file (buffer-file-name (marker-buffer marker))
-                   cat (org-get-category)
-                   heading (org-get-heading 'notags)
-                   prefix (save-excursion
-                            (org-back-to-heading t)
-                            (looking-at org-outline-regexp)
-                            (match-string 0))
-                   task (substring
-                         (org-fontify-like-in-org-mode
-                          (concat prefix heading)
-                          org-odd-levels-only)
-                         (length prefix)))))))
+       (org-with-wide-buffer
+         (ignore-errors
+           (goto-char marker)
+           (setq cat (org-get-category)
+                 heading (org-get-heading 'notags)
+                 prefix (save-excursion
+                          (org-back-to-heading t)
+                          (looking-at org-outline-regexp)
+                          (match-string 0))
+                 task (substring
+                       (org-fontify-like-in-org-mode
+                        (concat prefix heading)
+                        org-odd-levels-only)
+                       (length prefix))))))
       (when (and cat task)
        (insert (format "[%c] %-12s  %s\n" i cat task))
        (cons i marker)))))
@@ -608,19 +671,19 @@ If not, show simply the clocked time like 01:50."
        (let* ((effort-in-minutes
                (org-duration-string-to-minutes org-clock-effort))
               (work-done-str
-               (org-propertize
+               (propertize
                 (org-minutes-to-clocksum-string clocked-time)
                 'face (if (and org-clock-task-overrun (not 
org-clock-task-overrun-text))
                           'org-mode-line-clock-overrun 'org-mode-line-clock)))
               (effort-str (org-minutes-to-clocksum-string effort-in-minutes))
-              (clockstr (org-propertize
+              (clockstr (propertize
                          (concat  " [%s/" effort-str
                                   "] (" (replace-regexp-in-string "%" "%%" 
org-clock-heading) ")")
                          'face 'org-mode-line-clock)))
          (format clockstr work-done-str))
-      (org-propertize (concat "[" (org-minutes-to-clocksum-string clocked-time)
-                             (format " (%s)" org-clock-heading) "]")
-                     'face 'org-mode-line-clock))))
+      (propertize (concat " [" (org-minutes-to-clocksum-string clocked-time)
+                         "]" (format " (%s)" org-clock-heading))
+                 'face 'org-mode-line-clock))))
 
 (defun org-clock-get-last-clock-out-time ()
   "Get the last clock-out time for the current subtree."
@@ -635,20 +698,21 @@ If not, show simply the clocked time like 01:50."
       (org-clock-notify-once-if-expired)
     (setq org-clock-task-overrun nil))
   (setq org-mode-line-string
-       (org-propertize
+       (propertize
         (let ((clock-string (org-clock-get-clock-string))
-              (help-text "Org-mode clock is running.\nmouse-1 shows a 
menu\nmouse-2 will jump to task"))
+              (help-text "Org mode clock is running.\nmouse-1 shows a \
+menu\nmouse-2 will jump to task"))
           (if (and (> org-clock-string-limit 0)
                    (> (length clock-string) org-clock-string-limit))
-              (org-propertize
+              (propertize
                (substring clock-string 0 org-clock-string-limit)
                'help-echo (concat help-text ": " org-clock-heading))
-            (org-propertize clock-string 'help-echo help-text)))
+            (propertize clock-string 'help-echo help-text)))
         'local-map org-clock-mode-line-map
-        'mouse-face (if (featurep 'xemacs) 'highlight 'mode-line-highlight)))
+        'mouse-face 'mode-line-highlight))
   (if (and org-clock-task-overrun org-clock-task-overrun-text)
       (setq org-mode-line-string
-           (concat (org-propertize
+           (concat (propertize
                     org-clock-task-overrun-text
                     'face 'org-mode-line-clock-overrun) org-mode-line-string)))
   (force-mode-line-update))
@@ -739,7 +803,7 @@ use libnotify if available, or fall back on a message."
                        org-show-notification-handler notification))
        ((fboundp 'notifications-notify)
         (notifications-notify
-         :title "Org-mode message"
+         :title "Org mode message"
          :body notification
          ;; FIXME how to link to the Org icon?
          ;; :app-icon "~/.emacs.d/icons/mail.png"
@@ -776,11 +840,12 @@ If CLOCK-SOUND is non-nil, it overrides 
`org-clock-sound'."
   "Search through the given file and find all open clocks."
   (let ((buf (or (get-file-buffer file)
                 (find-file-noselect file)))
+       (org-clock-re (concat org-clock-string " \\(\\[.*?\\]\\)$"))
        clocks)
     (with-current-buffer buf
       (save-excursion
        (goto-char (point-min))
-       (while (re-search-forward "CLOCK: \\(\\[.*?\\]\\)$" nil t)
+       (while (re-search-forward org-clock-re nil t)
          (push (cons (copy-marker (match-end 1) t)
                      (org-time-string-to-time (match-string 1))) clocks))))
     clocks))
@@ -793,12 +858,10 @@ If CLOCK-SOUND is non-nil, it overrides 
`org-clock-sound'."
 (defmacro org-with-clock-position (clock &rest forms)
   "Evaluate FORMS with CLOCK as the current active clock."
   `(with-current-buffer (marker-buffer (car ,clock))
-     (save-excursion
-       (save-restriction
-        (widen)
-        (goto-char (car ,clock))
-        (beginning-of-line)
-        ,@forms))))
+     (org-with-wide-buffer
+      (goto-char (car ,clock))
+      (beginning-of-line)
+      ,@forms)))
 (def-edebug-spec org-with-clock-position (form body))
 (put 'org-with-clock-position 'lisp-indent-function 1)
 
@@ -812,7 +875,7 @@ This macro also protects the current active clock from 
being altered."
           (org-clock-effort)
           (org-clock-marker (car ,clock))
           (org-clock-hd-marker (save-excursion
-                                 (outline-back-to-heading t)
+                                 (org-back-to-heading t)
                                  (point-marker))))
        ,@forms)))
 (def-edebug-spec org-with-clock (form body))
@@ -885,7 +948,7 @@ If necessary, clock-out of the currently active clock."
 
 (defun org-clock-jump-to-current-clock (&optional effective-clock)
   (interactive)
-  (let ((org-clock-into-drawer (org-clock-into-drawer))
+  (let ((drawer (org-clock-into-drawer))
        (clock (or effective-clock (cons org-clock-marker
                                         org-clock-start-time))))
     (unless (marker-buffer (car clock))
@@ -893,26 +956,21 @@ If necessary, clock-out of the currently active clock."
     (org-with-clock clock (org-clock-goto))
     (with-current-buffer (marker-buffer (car clock))
       (goto-char (car clock))
-      (if org-clock-into-drawer
-         (let ((logbook
-                (if (stringp org-clock-into-drawer)
-                    (concat ":" org-clock-into-drawer ":")
-                  ":LOGBOOK:")))
-           (ignore-errors
-             (outline-flag-region
-              (save-excursion
-                (outline-back-to-heading t)
-                (search-forward logbook)
-                (goto-char (match-beginning 0)))
-              (save-excursion
-                (outline-back-to-heading t)
-                (search-forward logbook)
-                (search-forward ":END:")
-                (goto-char (match-end 0)))
-              nil)))))))
+      (when drawer
+       (org-with-wide-buffer
+        (let ((drawer-re (format "^[ \t]*:%s:[ \t]*$"
+                                 (regexp-quote (if (stringp drawer) drawer 
"LOGBOOK"))))
+              (beg (save-excursion (org-back-to-heading t) (point))))
+          (catch 'exit
+            (while (re-search-backward drawer-re beg t)
+              (let ((element (org-element-at-point)))
+                (when (eq (org-element-type element) 'drawer)
+                  (when (> (org-element-property :end element) (car clock))
+                    (org-flag-drawer nil element))
+                  (throw 'exit nil)))))))))))
 
 (defun org-clock-resolve (clock &optional prompt-fn last-valid fail-quietly)
-  "Resolve an open org-mode clock.
+  "Resolve an open Org clock.
 An open clock was found, with `dangling' possibly being non-nil.
 If this function was invoked with a prefix argument, non-dangling
 open clocks are ignored.  The given clock requires some sort of
@@ -930,7 +988,7 @@ The format of clock is (CONS MARKER START-TIME), where 
MARKER
 identifies the buffer and position the clock is open at (and
 thus, the heading it's under), and START-TIME is when the clock
 was started."
-  (assert clock)
+  (cl-assert clock)
   (let* ((ch
          (save-window-excursion
            (save-excursion
@@ -947,7 +1005,7 @@ k/K      Keep X minutes of the idle time (default is all). 
 If this
          that many minutes after the time that idling began, and then
          clocked back in at the present time.
 
-g/G      Indicate that you “got back” X minutes ago.  This is quite
+g/G      Indicate that you \"got back\" X minutes ago.  This is quite
          different from `k': it clocks you out from the beginning of
          the idle period and clock you back in X minutes ago.
 
@@ -963,10 +1021,6 @@ For all these options, using uppercase makes your final 
state
 to be CLOCKED OUT."))))
              (org-fit-window-to-buffer (get-buffer-window "*Org Clock*"))
              (let (char-pressed)
-               (when (featurep 'xemacs)
-                 (message (concat (funcall prompt-fn clock)
-                                  " [jkKgGsScCiq]? "))
-                 (setq char-pressed (read-char-exclusive)))
                (while (or (null char-pressed)
                           (and (not (memq char-pressed
                                           '(?k ?K ?g ?G ?s ?S ?C
@@ -1028,7 +1082,7 @@ to be CLOCKED OUT."))))
 
 ;;;###autoload
 (defun org-resolve-clocks (&optional only-dangling-p prompt-fn last-valid)
-  "Resolve all currently open org-mode clocks.
+  "Resolve all currently open Org clocks.
 If `only-dangling-p' is non-nil, only ask to resolve dangling
 \(i.e., not currently open and valid) clocks."
   (interactive "P")
@@ -1091,7 +1145,7 @@ This routine returns a floating point number."
 (defvar org-clock-user-idle-seconds)
 
 (defun org-resolve-clocks-if-idle ()
-  "Resolve all currently open org-mode clocks.
+  "Resolve all currently open Org clocks.
 This is performed after `org-clock-idle-time' minutes, to check
 if the user really wants to stay clocked in after being idle for
 so long."
@@ -1106,13 +1160,12 @@ so long."
          (org-clock-resolve
           (cons org-clock-marker
                 org-clock-start-time)
-          (function
-           (lambda (clock)
-             (format "Clocked in & idle for %.1f mins"
-                     (/ (float-time
-                         (time-subtract (current-time)
-                                        org-clock-user-idle-start))
-                        60.0))))
+          (lambda (_)
+            (format "Clocked in & idle for %.1f mins"
+                    (/ (float-time
+                        (time-subtract (current-time)
+                                       org-clock-user-idle-start))
+                       60.0)))
           org-clock-user-idle-start)))))
 
 (defvar org-clock-current-task nil "Task currently clocked in.")
@@ -1122,18 +1175,27 @@ so long."
 ;;;###autoload
 (defun org-clock-in (&optional select start-time)
   "Start the clock on the current item.
+
 If necessary, clock-out of the currently active clock.
-With a prefix argument SELECT (\\[universal-argument]), offer a list of 
recently clocked
-tasks to clock into.  When SELECT is \\[universal-argument] 
\\[universal-argument], clock into the current task
-and mark it as the default task, a special task that will always be offered
-in the clocking selection, associated with the letter `d'.
-When SELECT is \\[universal-argument] \\[universal-argument] 
\\[universal-argument], \
-clock in by using the last clock-out
-time as the start time \(see `org-clock-continuously' to
-make this the default behavior.)"
+
+With a `\\[universal-argument]' prefix argument SELECT, offer a list of \
+recently clocked
+tasks to clock into.
+
+When SELECT is `\\[universal-argument] \ \\[universal-argument]', \
+clock into the current task and mark it as
+the default task, a special task that will always be offered in the
+clocking selection, associated with the letter `d'.
+
+When SELECT is `\\[universal-argument] \\[universal-argument] \
+\\[universal-argument]', clock in by using the last clock-out
+time as the start time.  See `org-clock-continuously' to make this
+the default behavior."
   (interactive "P")
   (setq org-clock-notification-was-shown nil)
-  (org-refresh-properties org-effort-property 'org-effort)
+  (org-refresh-properties
+   org-effort-property '((effort . identity)
+                        (effort-minutes . org-duration-string-to-minutes)))
   (catch 'abort
     (let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness)
                             (org-clocking-p)))
@@ -1148,7 +1210,7 @@ make this the default behavior.)"
                 (not org-clock-resolving-clocks))
        (setq org-clock-leftover-time nil)
        (let ((org-clock-clocking-in t))
-         (org-resolve-clocks)))        ; check if any clocks are dangling
+         (org-resolve-clocks)))    ; check if any clocks are dangling
 
       (when (equal select '(64))
        ;; Set start-time to `org-clock-out-time'
@@ -1201,116 +1263,116 @@ make this the default behavior.)"
          (set-buffer (org-base-buffer (marker-buffer selected-task)))
          (setq target-pos (marker-position selected-task))
          (move-marker selected-task nil))
-       (save-excursion
-         (save-restriction
-           (widen)
-           (goto-char target-pos)
-           (org-back-to-heading t)
-           (or interrupting (move-marker org-clock-interrupted-task nil))
-           (run-hooks 'org-clock-in-prepare-hook)
-           (org-clock-history-push)
-           (setq org-clock-current-task (nth 4 (org-heading-components)))
-           (cond ((functionp org-clock-in-switch-to-state)
-                  (looking-at org-complex-heading-regexp)
-                  (let ((newstate (funcall org-clock-in-switch-to-state
-                                           (match-string 2))))
-                    (if newstate (org-todo newstate))))
-                 ((and org-clock-in-switch-to-state
-                       (not (looking-at (concat org-outline-regexp "[ \t]*"
-                                                org-clock-in-switch-to-state
-                                                "\\>"))))
-                  (org-todo org-clock-in-switch-to-state)))
-           (setq org-clock-heading
-                 (cond ((and org-clock-heading-function
-                             (functionp org-clock-heading-function))
-                        (funcall org-clock-heading-function))
-                       ((nth 4 (org-heading-components))
-                        (replace-regexp-in-string
-                         "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1"
-                         (match-string-no-properties 4)))
-                       (t "???")))
-           (org-clock-find-position org-clock-in-resume)
-           (cond
-            ((and org-clock-in-resume
-                  (looking-at
-                   (concat "^[ \t]*" org-clock-string
-                           " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
-                           " *\\sw+.? +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")))
-             (message "Matched %s" (match-string 1))
-             (setq ts (concat "[" (match-string 1) "]"))
-             (goto-char (match-end 1))
-             (setq org-clock-start-time
-                   (apply 'encode-time
-                          (org-parse-time-string (match-string 1))))
-             (setq org-clock-effort (org-entry-get (point) 
org-effort-property))
-             (setq org-clock-total-time (org-clock-sum-current-item
-                                         (org-clock-get-sum-start))))
-            ((eq org-clock-in-resume 'auto-restart)
-             ;; called from org-clock-load during startup,
-             ;; do not interrupt, but warn!
-             (message "Cannot restart clock because task does not contain 
unfinished clock")
-             (ding)
-             (sit-for 2)
-             (throw 'abort nil))
-            (t
-             (insert-before-markers "\n")
-             (backward-char 1)
-             (org-indent-line)
-             (when (and (save-excursion
-                          (end-of-line 0)
-                          (org-in-item-p)))
-               (beginning-of-line 1)
-               (org-indent-line-to (- (org-get-indentation) 2)))
-             (insert org-clock-string " ")
-             (setq org-clock-effort (org-entry-get (point) 
org-effort-property))
-             (setq org-clock-total-time (org-clock-sum-current-item
-                                         (org-clock-get-sum-start)))
-             (setq org-clock-start-time
-                   (or (and org-clock-continuously org-clock-out-time)
-                       (and leftover
-                            (y-or-n-p
-                             (format
-                              "You stopped another clock %d mins ago; start 
this one from then? "
-                              (/ (- (float-time
-                                     (org-current-time 
org-clock-rounding-minutes t))
-                                    (float-time leftover)) 60)))
-                            leftover)
-                       start-time
-                       (org-current-time org-clock-rounding-minutes t)))
-             (setq ts (org-insert-time-stamp org-clock-start-time
-                                             'with-hm 'inactive))))
-           (move-marker org-clock-marker (point) (buffer-base-buffer))
-           (move-marker org-clock-hd-marker
-                        (save-excursion (org-back-to-heading t) (point))
-                        (buffer-base-buffer))
-           (setq org-clock-has-been-used t)
-           ;; add to mode line
-           (when (or (eq org-clock-clocked-in-display 'mode-line)
-                     (eq org-clock-clocked-in-display 'both))
-             (or global-mode-string (setq global-mode-string '("")))
-             (or (memq 'org-mode-line-string global-mode-string)
-                 (setq global-mode-string
-                       (append global-mode-string '(org-mode-line-string)))))
-           ;; add to frame title
-           (when (or (eq org-clock-clocked-in-display 'frame-title)
-                     (eq org-clock-clocked-in-display 'both))
-             (setq frame-title-format org-clock-frame-title-format))
-           (org-clock-update-mode-line)
-           (when org-clock-mode-line-timer
-             (cancel-timer org-clock-mode-line-timer)
-             (setq org-clock-mode-line-timer nil))
-           (when org-clock-clocked-in-display
-             (setq org-clock-mode-line-timer
-                   (run-with-timer org-clock-update-period
-                                   org-clock-update-period
-                                   'org-clock-update-mode-line)))
-           (when org-clock-idle-timer
-             (cancel-timer org-clock-idle-timer)
-             (setq org-clock-idle-timer nil))
-           (setq org-clock-idle-timer
-                 (run-with-timer 60 60 'org-resolve-clocks-if-idle))
-           (message "Clock starts at %s - %s" ts org--msg-extra)
-           (run-hooks 'org-clock-in-hook)))))))
+       (org-with-wide-buffer
+        (goto-char target-pos)
+        (org-back-to-heading t)
+        (or interrupting (move-marker org-clock-interrupted-task nil))
+        (run-hooks 'org-clock-in-prepare-hook)
+        (org-clock-history-push)
+        (setq org-clock-current-task (nth 4 (org-heading-components)))
+        (cond ((functionp org-clock-in-switch-to-state)
+               (let ((case-fold-search nil))
+                 (looking-at org-complex-heading-regexp))
+               (let ((newstate (funcall org-clock-in-switch-to-state
+                                        (match-string 2))))
+                 (when newstate (org-todo newstate))))
+              ((and org-clock-in-switch-to-state
+                    (not (looking-at (concat org-outline-regexp "[ \t]*"
+                                             org-clock-in-switch-to-state
+                                             "\\>"))))
+               (org-todo org-clock-in-switch-to-state)))
+        (setq org-clock-heading
+              (cond ((and org-clock-heading-function
+                          (functionp org-clock-heading-function))
+                     (funcall org-clock-heading-function))
+                    ((nth 4 (org-heading-components))
+                     (replace-regexp-in-string
+                      "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1"
+                      (match-string-no-properties 4)))
+                    (t "???")))
+        (org-clock-find-position org-clock-in-resume)
+        (cond
+         ((and org-clock-in-resume
+               (looking-at
+                (concat "^[ \t]*" org-clock-string
+                        " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
+                        " *\\sw+.? +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")))
+          (message "Matched %s" (match-string 1))
+          (setq ts (concat "[" (match-string 1) "]"))
+          (goto-char (match-end 1))
+          (setq org-clock-start-time
+                (apply 'encode-time
+                       (org-parse-time-string (match-string 1))))
+          (setq org-clock-effort (org-entry-get (point) org-effort-property))
+          (setq org-clock-total-time (org-clock-sum-current-item
+                                      (org-clock-get-sum-start))))
+         ((eq org-clock-in-resume 'auto-restart)
+          ;; called from org-clock-load during startup,
+          ;; do not interrupt, but warn!
+          (message "Cannot restart clock because task does not contain 
unfinished clock")
+          (ding)
+          (sit-for 2)
+          (throw 'abort nil))
+         (t
+          (insert-before-markers "\n")
+          (backward-char 1)
+          (org-indent-line)
+          (when (and (save-excursion
+                       (end-of-line 0)
+                       (org-in-item-p)))
+            (beginning-of-line 1)
+            (indent-line-to (- (org-get-indentation) 2)))
+          (insert org-clock-string " ")
+          (setq org-clock-effort (org-entry-get (point) org-effort-property))
+          (setq org-clock-total-time (org-clock-sum-current-item
+                                      (org-clock-get-sum-start)))
+          (setq org-clock-start-time
+                (or (and org-clock-continuously org-clock-out-time)
+                    (and leftover
+                         (y-or-n-p
+                          (format
+                           "You stopped another clock %d mins ago; start this 
one from then? "
+                           (/ (- (float-time
+                                  (org-current-time org-clock-rounding-minutes 
t))
+                                 (float-time leftover))
+                              60)))
+                         leftover)
+                    start-time
+                    (org-current-time org-clock-rounding-minutes t)))
+          (setq ts (org-insert-time-stamp org-clock-start-time
+                                          'with-hm 'inactive))))
+        (move-marker org-clock-marker (point) (buffer-base-buffer))
+        (move-marker org-clock-hd-marker
+                     (save-excursion (org-back-to-heading t) (point))
+                     (buffer-base-buffer))
+        (setq org-clock-has-been-used t)
+        ;; add to mode line
+        (when (or (eq org-clock-clocked-in-display 'mode-line)
+                  (eq org-clock-clocked-in-display 'both))
+          (or global-mode-string (setq global-mode-string '("")))
+          (or (memq 'org-mode-line-string global-mode-string)
+              (setq global-mode-string
+                    (append global-mode-string '(org-mode-line-string)))))
+        ;; add to frame title
+        (when (or (eq org-clock-clocked-in-display 'frame-title)
+                  (eq org-clock-clocked-in-display 'both))
+          (setq frame-title-format org-clock-frame-title-format))
+        (org-clock-update-mode-line)
+        (when org-clock-mode-line-timer
+          (cancel-timer org-clock-mode-line-timer)
+          (setq org-clock-mode-line-timer nil))
+        (when org-clock-clocked-in-display
+          (setq org-clock-mode-line-timer
+                (run-with-timer org-clock-update-period
+                                org-clock-update-period
+                                'org-clock-update-mode-line)))
+        (when org-clock-idle-timer
+          (cancel-timer org-clock-idle-timer)
+          (setq org-clock-idle-timer nil))
+        (setq org-clock-idle-timer
+              (run-with-timer 60 60 'org-resolve-clocks-if-idle))
+        (message "Clock starts at %s - %s" ts org--msg-extra)
+        (run-hooks 'org-clock-in-hook))))))
 
 ;;;###autoload
 (defun org-clock-in-last (&optional arg)
@@ -1324,8 +1386,7 @@ With three universal prefix arguments, interactively 
prompt
 for a todo state to switch to, overriding the existing value
 `org-clock-in-switch-to-state'."
   (interactive "P")
-  (if (equal arg '(4))
-      (org-clock-in (org-clock-select-task))
+  (if (equal arg '(4)) (org-clock-in arg)
     (let ((start-time (if (or org-clock-continuously (equal arg '(16)))
                          (or org-clock-out-time
                              (org-current-time org-clock-rounding-minutes t))
@@ -1371,10 +1432,12 @@ decides which time to use."
       (current-time))
      ((equal cmt "today")
       (setq org--msg-extra "showing today's task time.")
-      (let* ((dt (decode-time)))
-       (setq dt (append (list 0 0 0) (nthcdr 3 dt)))
-       (if org-extend-today-until
-           (setf (nth 2 dt) org-extend-today-until))
+      (let* ((dt (decode-time))
+            (hour (nth 2 dt))
+            (day (nth 3 dt)))
+       (if (< hour org-extend-today-until) (setf (nth 3 dt) (1- day)))
+       (setf (nth 2 dt) org-extend-today-until)
+       (setq dt (append (list 0 0) (nthcdr 2 dt)))
        (apply 'encode-time dt)))
      ((or (equal cmt "all")
          (and (or (not cmt) (equal cmt "auto"))
@@ -1396,87 +1459,93 @@ When FIND-UNCLOSED is non-nil, first check if there is 
an unclosed clock
 line and position cursor in that line."
   (org-back-to-heading t)
   (catch 'exit
-    (let* ((org-clock-into-drawer (org-clock-into-drawer))
-          (beg (save-excursion
-                 (beginning-of-line 2)
-                 (or (bolp) (newline))
-                 (point)))
-          (end (progn (outline-next-heading) (point)))
-          (re (concat "^[ \t]*" org-clock-string))
-          (cnt 0)
-          (drawer (if (stringp org-clock-into-drawer)
-                      org-clock-into-drawer "LOGBOOK"))
-          first last ind-last)
-      (goto-char beg)
-      (when (and find-unclosed
-                (re-search-forward
-                 (concat "^[ \t]*" org-clock-string
-                         " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
-                         " *\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")
-                 end t))
-       (beginning-of-line 1)
-       (throw 'exit t))
-      (when (eobp) (newline) (setq end (max (point) end)))
-      (when (re-search-forward (concat "^[ \t]*:" drawer ":") end t)
-       ;; we seem to have a CLOCK drawer, so go there.
-       (beginning-of-line 2)
-       (or org-log-states-order-reversed
-           (and (re-search-forward org-property-end-re nil t)
-                (goto-char (match-beginning 0))))
-       (throw 'exit t))
-      ;; Lets count the CLOCK lines
+    (let* ((beg (line-beginning-position))
+          (end (save-excursion (outline-next-heading) (point)))
+          (org-clock-into-drawer (org-clock-into-drawer))
+          (drawer (org-clock-drawer-name)))
+      ;; Look for a running clock if FIND-UNCLOSED in non-nil.
+      (when find-unclosed
+       (let ((open-clock-re
+              (concat "^[ \t]*"
+                      org-clock-string
+                      " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
+                      " *\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")))
+         (while (re-search-forward open-clock-re end t)
+           (let ((element (org-element-at-point)))
+             (when (and (eq (org-element-type element) 'clock)
+                        (eq (org-element-property :status element) 'running))
+               (beginning-of-line)
+               (throw 'exit t))))))
+      ;; Look for an existing clock drawer.
+      (when drawer
+       (goto-char beg)
+       (let ((drawer-re (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$")))
+         (while (re-search-forward drawer-re end t)
+           (let ((element (org-element-at-point)))
+             (when (eq (org-element-type element) 'drawer)
+               (let ((cend (org-element-property :contents-end element)))
+                 (if (and (not org-log-states-order-reversed) cend)
+                     (goto-char cend)
+                   (forward-line))
+                 (throw 'exit t)))))))
       (goto-char beg)
-      (while (re-search-forward re end t)
-       (setq first (or first (match-beginning 0))
-             last (match-beginning 0)
-             cnt (1+ cnt)))
-      (when (and (integerp org-clock-into-drawer)
-                last
-                (>= (1+ cnt) org-clock-into-drawer))
-       ;; Wrap current entries into a new drawer
-       (goto-char last)
-       (setq ind-last (org-get-indentation))
-       (beginning-of-line 2)
-       (if (and (>= (org-get-indentation) ind-last)
-                (org-at-item-p))
-           (when (and (>= (org-get-indentation) ind-last)
-                      (org-at-item-p))
-             (let ((struct (org-list-struct)))
-               (goto-char (org-list-get-bottom-point struct)))))
-       (insert ":END:\n")
-       (beginning-of-line 0)
-       (org-indent-line-to ind-last)
-       (goto-char first)
-       (insert ":" drawer ":\n")
-       (beginning-of-line 0)
-       (org-indent-line)
-       (org-flag-drawer t)
-       (beginning-of-line 2)
-       (or org-log-states-order-reversed
-           (and (re-search-forward org-property-end-re nil t)
-                (goto-char (match-beginning 0))))
-       (throw 'exit nil))
-
-      (goto-char beg)
-      (while (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
-                 (not (equal (match-string 1) org-clock-string)))
-       ;; Planning info, skip to after it
-       (beginning-of-line 2)
-       (or (bolp) (newline)))
-      (when (or (eq org-clock-into-drawer t)
-               (stringp org-clock-into-drawer)
-               (and (integerp org-clock-into-drawer)
-                    (< org-clock-into-drawer 2)))
-       (insert ":" drawer ":\n:END:\n")
-       (beginning-of-line -1)
-       (org-indent-line)
-       (org-flag-drawer t)
-       (beginning-of-line 2)
-       (org-indent-line)
-       (beginning-of-line)
-       (or org-log-states-order-reversed
-           (and (re-search-forward org-property-end-re nil t)
-                (goto-char (match-beginning 0))))))))
+      (let ((clock-re (concat "^[ \t]*" org-clock-string))
+           (count 0)
+           positions)
+       ;; Count the CLOCK lines and store their positions.
+       (save-excursion
+         (while (re-search-forward clock-re end t)
+           (let ((element (org-element-at-point)))
+             (when (eq (org-element-type element) 'clock)
+               (setq positions (cons (line-beginning-position) positions)
+                     count (1+ count))))))
+       (cond
+        ((null positions)
+         ;; Skip planning line and property drawer, if any.
+         (org-end-of-meta-data)
+         (unless (bolp) (insert "\n"))
+         ;; Create a new drawer if necessary.
+         (when (and org-clock-into-drawer
+                    (or (not (wholenump org-clock-into-drawer))
+                        (< org-clock-into-drawer 2)))
+           (let ((beg (point)))
+             (insert ":" drawer ":\n:END:\n")
+             (org-indent-region beg (point))
+             (goto-char beg)
+             (org-flag-drawer t)
+             (forward-line))))
+        ;; When a clock drawer needs to be created because of the
+        ;; number of clock items or simply if it is missing, collect
+        ;; all clocks in the section and wrap them within the drawer.
+        ((if (wholenump org-clock-into-drawer)
+             (>= (1+ count) org-clock-into-drawer)
+           drawer)
+         ;; Skip planning line and property drawer, if any.
+         (org-end-of-meta-data)
+         (let ((beg (point)))
+           (insert
+            (mapconcat
+             (lambda (p)
+               (save-excursion
+                 (goto-char p)
+                 (org-trim (delete-and-extract-region
+                            (save-excursion (skip-chars-backward " \r\t\n")
+                                            (line-beginning-position 2))
+                            (line-beginning-position 2)))))
+             positions "\n")
+            "\n:END:\n")
+           (let ((end (point-marker)))
+             (goto-char beg)
+             (save-excursion (insert ":" drawer ":\n"))
+             (org-flag-drawer t)
+             (org-indent-region (point) end)
+             (forward-line)
+             (unless org-log-states-order-reversed
+               (goto-char end)
+               (beginning-of-line -1))
+             (set-marker end nil))))
+        (org-log-states-order-reversed (goto-char (car (last positions))))
+        (t (goto-char (car positions))))))))
 
 ;;;###autoload
 (defun org-clock-out (&optional switch-to-state fail-quietly at-time)
@@ -1504,7 +1573,7 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
          ts te s h m remove)
       (setq org-clock-out-time now)
       (save-excursion ; Do not replace this with `with-current-buffer'.
-       (org-no-warnings (set-buffer (org-clocking-buffer)))
+       (with-no-warnings (set-buffer (org-clocking-buffer)))
        (save-restriction
          (widen)
          (goto-char org-clock-marker)
@@ -1517,24 +1586,28 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
          (delete-region (point) (point-at-eol))
          (insert "--")
          (setq te (org-insert-time-stamp (or at-time now) 'with-hm 'inactive))
-         (setq s (- (float-time (apply 'encode-time (org-parse-time-string 
te)))
-                    (float-time (apply 'encode-time (org-parse-time-string 
ts))))
+         (setq s (- (float-time
+                     (apply #'encode-time (org-parse-time-string te nil t)))
+                    (float-time
+                     (apply #'encode-time (org-parse-time-string ts nil t))))
                h (floor (/ s 3600))
                s (- s (* 3600 h))
                m (floor (/ s 60))
                s (- s (* 60 s)))
          (insert " => " (format "%2d:%02d" h m))
-         (when (setq remove (and org-clock-out-remove-zero-time-clocks
-                                 (= (+ h m) 0)))
-           (beginning-of-line 1)
-           (delete-region (point) (point-at-eol))
-           (and (looking-at "\n") (> (point-max) (1+ (point)))
-                (delete-char 1)))
          (move-marker org-clock-marker nil)
          (move-marker org-clock-hd-marker nil)
-         (when org-log-note-clock-out
-           (org-add-log-setup 'clock-out nil nil nil nil
-                              (concat "# Task: " (org-get-heading t) "\n\n")))
+         ;; Possibly remove zero time clocks.  However, do not add
+         ;; a note associated to the CLOCK line in this case.
+         (cond ((and org-clock-out-remove-zero-time-clocks
+                     (= (+ h m) 0))
+                (setq remove t)
+                (delete-region (line-beginning-position)
+                               (line-beginning-position 2)))
+               (org-log-note-clock-out
+                (org-add-log-setup
+                 'clock-out nil nil nil
+                 (concat "# Task: " (org-get-heading t) "\n\n"))))
          (when org-clock-mode-line-timer
            (cancel-timer org-clock-mode-line-timer)
            (setq org-clock-mode-line-timer nil))
@@ -1551,10 +1624,11 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
                    (org-clock-out-when-done nil))
                (cond
                 ((functionp org-clock-out-switch-to-state)
-                 (looking-at org-complex-heading-regexp)
+                 (let ((case-fold-search nil))
+                   (looking-at org-complex-heading-regexp))
                  (let ((newstate (funcall org-clock-out-switch-to-state
                                           (match-string 2))))
-                   (if newstate (org-todo newstate))))
+                   (when newstate (org-todo newstate))))
                 ((and org-clock-out-switch-to-state
                       (not (looking-at (concat org-outline-regexp "[ \t]*"
                                                org-clock-out-switch-to-state
@@ -1564,34 +1638,25 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
          (message (concat "Clock stopped at %s after "
                           (org-minutes-to-clocksum-string (+ (* 60 h) m)) "%s")
                   te (if remove " => LINE REMOVED" ""))
-         (let ((h org-clock-out-hook))
-           ;; If a closing note needs to be stored in the drawer
-           ;; where clocks are stored, let's temporarily disable
-           ;; `org-clock-remove-empty-clock-drawer'
-           (if (and (equal org-clock-into-drawer org-log-into-drawer)
-                    (eq org-log-done 'note)
-                    org-clock-out-when-done)
-               (setq h (delq 'org-clock-remove-empty-clock-drawer h)))
-           (mapc (lambda (f) (funcall f)) h))
+         (run-hooks 'org-clock-out-hook)
          (unless (org-clocking-p)
            (setq org-clock-current-task nil)))))))
 
 (add-hook 'org-clock-out-hook 'org-clock-remove-empty-clock-drawer)
 
-(defun org-clock-remove-empty-clock-drawer nil
-  "Remove empty clock drawer in the current subtree."
-  (let* ((olid (or (org-entry-get (point) "LOG_INTO_DRAWER")
-                  org-log-into-drawer))
-        (clock-drawer (if (eq t olid) "LOGBOOK" olid))
-        (end (save-excursion (org-end-of-subtree t t))))
-    (when clock-drawer
-      (save-excursion
-       (org-back-to-heading t)
-       (while (and (< (point) end)
-                   (search-forward clock-drawer end t))
-         (goto-char (match-beginning 0))
-         (org-remove-empty-drawer-at clock-drawer (point))
-         (forward-line 1))))))
+(defun org-clock-remove-empty-clock-drawer ()
+  "Remove empty clock drawers in current subtree."
+  (save-excursion
+    (org-back-to-heading t)
+    (org-map-tree
+     (lambda ()
+       (let ((drawer (org-clock-drawer-name))
+            (case-fold-search t))
+        (when drawer
+          (let ((re (format "^[ \t]*:%s:[ \t]*$" (regexp-quote drawer)))
+                (end (save-excursion (outline-next-heading))))
+            (while (re-search-forward re end t)
+              (org-remove-empty-drawer-at (point))))))))))
 
 (defun org-clock-timestamps-up (&optional n)
   "Increase CLOCK timestamps at cursor.
@@ -1607,7 +1672,7 @@ Optional argument N tells to change by that many units."
 
 (defun org-clock-timestamps-change (updown &optional n)
   "Change CLOCK timestamps synchronously at cursor.
-UPDOWN tells whether to change 'up or 'down.
+UPDOWN tells whether to change `up' or `down'.
 Optional argument N tells to change by that many units."
   (setq org-ts-what nil)
   (when (org-at-timestamp-p t)
@@ -1654,13 +1719,13 @@ Optional argument N tells to change by that many units."
     (setq frame-title-format org-frame-title-format-backup)
     (force-mode-line-update)
     (error "No active clock"))
-  (save-excursion ; Do not replace this with `with-current-buffer'.
-    (org-no-warnings (set-buffer (org-clocking-buffer)))
+  (save-excursion    ; Do not replace this with `with-current-buffer'.
+    (with-no-warnings (set-buffer (org-clocking-buffer)))
     (goto-char org-clock-marker)
-    (if (org-looking-back (concat "^[ \t]*" org-clock-string ".*")
-                          (line-beginning-position))
+    (if (looking-back (concat "^[ \t]*" org-clock-string ".*")
+                     (line-beginning-position))
        (progn (delete-region (1- (point-at-bol)) (point-at-eol))
-              (org-remove-empty-drawer-at "LOGBOOK" (point)))
+              (org-remove-empty-drawer-at (point)))
       (message "Clock gone, cancel the timer anyway")
       (sit-for 2)))
   (move-marker org-clock-marker nil)
@@ -1672,12 +1737,6 @@ Optional argument N tells to change by that many units."
   (message "Clock canceled")
   (run-hooks 'org-clock-cancel-hook))
 
-(defcustom org-clock-goto-before-context 2
-  "Number of lines of context to display before currently clocked-in entry.
-This applies when using `org-clock-goto'."
-  :group 'org-clock
-  :type 'integer)
-
 ;;;###autoload
 (defun org-clock-goto (&optional select)
   "Go to the currently clocked-in entry, or to the most recently clocked one.
@@ -1695,7 +1754,7 @@ With prefix arg SELECT, offer recently clocked tasks for 
selection."
              (setq recent t)
              (car org-clock-history))
             (t (error "No active or recent clock task")))))
-    (org-pop-to-buffer-same-window (marker-buffer m))
+    (pop-to-buffer-same-window (marker-buffer m))
     (if (or (< m (point-min)) (> m (point-max))) (widen))
     (goto-char m)
     (org-show-entry)
@@ -1707,15 +1766,27 @@ With prefix arg SELECT, offer recently clocked tasks 
for selection."
        (message "No running clock, this is the most recently clocked task"))
     (run-hooks 'org-clock-goto-hook)))
 
-(defvar org-clock-file-total-minutes nil
+(defvar-local org-clock-file-total-minutes nil
   "Holds the file total time in minutes, after a call to `org-clock-sum'.")
-(make-variable-buffer-local 'org-clock-file-total-minutes)
 
 (defun org-clock-sum-today (&optional headline-filter)
   "Sum the times for each subtree for today."
-  (interactive)
   (let ((range (org-clock-special-range 'today)))
-    (org-clock-sum (car range) (cadr range) nil :org-clock-minutes-today)))
+    (org-clock-sum (car range) (cadr range)
+                  headline-filter :org-clock-minutes-today)))
+
+(defun org-clock-sum-custom (&optional headline-filter range propname)
+  "Sum the times for each subtree for today."
+  (let ((r (or (and (symbolp range) (org-clock-special-range range))
+              (org-clock-special-range
+               (intern (completing-read
+                        "Range: "
+                        '("today" "yesterday" "thisweek" "lastweek"
+                          "thismonth" "lastmonth" "thisyear" "lastyear"
+                          "interactive")
+                        nil t))))))
+    (org-clock-sum (car r) (cadr r)
+                  headline-filter (or propname :org-clock-minutes-custom))))
 
 ;;;###autoload
 (defun org-clock-sum (&optional tstart tend headline-filter propname)
@@ -1726,7 +1797,6 @@ HEADLINE-FILTER is a zero-arg function that, if 
specified, is called for
 each headline in the time range with point at the headline.  Headlines for
 which HEADLINE-FILTER returns nil are excluded from the clock summation.
 PROPNAME lets you set a custom text property instead of :org-clock-minutes."
-  (interactive)
   (org-with-silent-modifications
    (let* ((re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
                      org-clock-string
@@ -1753,9 +1823,9 @@ PROPNAME lets you set a custom text property instead of 
:org-clock-minutes."
           (setq ts (match-string 2)
                 te (match-string 3)
                 ts (float-time
-                    (apply 'encode-time (org-parse-time-string ts)))
+                    (apply #'encode-time (org-parse-time-string ts nil t)))
                 te (float-time
-                    (apply 'encode-time (org-parse-time-string te)))
+                    (apply #'encode-time (org-parse-time-string te nil t)))
                 ts (if tstart (max ts tstart) ts)
                 te (if tend (min te tend) te)
                 dt (- te ts)
@@ -1774,7 +1844,8 @@ PROPNAME lets you set a custom text property instead of 
:org-clock-minutes."
                      (>= (float-time org-clock-start-time) tstart)
                      (<= (float-time org-clock-start-time) tend))
             (let ((time (floor (- (float-time)
-                                  (float-time org-clock-start-time)) 60)))
+                                  (float-time org-clock-start-time))
+                               60)))
               (setq t1 (+ t1 time))))
           (let* ((headline-forced
                   (get-text-property (point)
@@ -1784,27 +1855,27 @@ PROPNAME lets you set a custom text property instead of 
:org-clock-minutes."
                       (save-excursion
                         (save-match-data (funcall headline-filter))))))
             (setq level (- (match-end 1) (match-beginning 1)))
+            (when (>= level lmax)
+              (setq ltimes (vconcat ltimes (make-vector lmax 0)) lmax (* 2 
lmax)))
             (when (or (> t1 0) (> (aref ltimes level) 0))
               (when (or headline-included headline-forced)
                 (if headline-included
-                    (loop for l from 0 to level do
-                          (aset ltimes l (+ (aref ltimes l) t1))))
+                    (cl-loop for l from 0 to level do
+                             (aset ltimes l (+ (aref ltimes l) t1))))
                 (setq time (aref ltimes level))
                 (goto-char (match-beginning 0))
                 (put-text-property (point) (point-at-eol)
                                    (or propname :org-clock-minutes) time)
-                (if headline-filter
-                    (save-excursion
-                      (save-match-data
-                        (while
-                            (> (funcall outline-level) 1)
-                          (outline-up-heading 1 t)
-                          (put-text-property
-                           (point) (point-at-eol)
-                           :org-clock-force-headline-inclusion t))))))
+                (when headline-filter
+                  (save-excursion
+                    (save-match-data
+                      (while (org-up-heading-safe)
+                        (put-text-property
+                         (point) (line-end-position)
+                         :org-clock-force-headline-inclusion t))))))
               (setq t1 0)
-              (loop for l from level to (1- lmax) do
-                    (aset ltimes l 0)))))))
+              (cl-loop for l from level to (1- lmax) do
+                       (aset ltimes l 0)))))))
        (setq org-clock-file-total-minutes (aref ltimes 0))))))
 
 (defun org-clock-sum-current-item (&optional tstart)
@@ -1816,74 +1887,99 @@ PROPNAME lets you set a custom text property instead of 
:org-clock-minutes."
       org-clock-file-total-minutes)))
 
 ;;;###autoload
-(defun org-clock-display (&optional total-only)
+(defun org-clock-display (&optional arg)
   "Show subtree times in the entire buffer.
-If TOTAL-ONLY is non-nil, only show the total time for the entire file
-in the echo area.
 
-Use \\[org-clock-remove-overlays] to remove the subtree times."
-  (interactive)
+By default, show the total time for the range defined in
+`org-clock-display-default-range'.  With `\\[universal-argument]' \
+prefix, show
+the total time for today instead.
+
+With `\\[universal-argument] \\[universal-argument]' prefix, \
+use a custom range, entered at prompt.
+
+With `\\[universal-argument] \ \\[universal-argument] \
+\\[universal-argument]' prefix, display the total time in the
+echo area.
+
+Use `\\[org-clock-remove-overlays]' to remove the subtree times."
+  (interactive "P")
   (org-clock-remove-overlays)
-  (let (time h m p)
-    (org-clock-sum)
-    (unless total-only
+  (let* ((todayp (equal arg '(4)))
+        (customp (member arg '((16) today yesterday
+                               thisweek lastweek thismonth
+                               lastmonth thisyear lastyear
+                               untilnow interactive)))
+        (prop (cond ((not arg) :org-clock-minutes-default)
+                    (todayp :org-clock-minutes-today)
+                    (customp :org-clock-minutes-custom)
+                    (t :org-clock-minutes)))
+        time h m p)
+    (cond ((not arg) (org-clock-sum-custom
+                     nil org-clock-display-default-range prop))
+         (todayp (org-clock-sum-today))
+         (customp (org-clock-sum-custom nil arg))
+         (t (org-clock-sum)))
+    (unless (eq arg '(64))
       (save-excursion
        (goto-char (point-min))
        (while (or (and (equal (setq p (point)) (point-min))
-                       (get-text-property p :org-clock-minutes))
+                       (get-text-property p prop))
                   (setq p (next-single-property-change
-                           (point) :org-clock-minutes)))
+                           (point) prop)))
          (goto-char p)
-         (when (setq time (get-text-property p :org-clock-minutes))
-           (org-clock-put-overlay time (funcall outline-level))))
+         (when (setq time (get-text-property p prop))
+           (org-clock-put-overlay time)))
        (setq h (/ org-clock-file-total-minutes 60)
              m (- org-clock-file-total-minutes (* 60 h)))
        ;; Arrange to remove the overlays upon next change.
        (when org-remove-highlights-with-change
-         (org-add-hook 'before-change-functions 'org-clock-remove-overlays
+         (add-hook 'before-change-functions 'org-clock-remove-overlays
                        nil 'local))))
-    (message (concat "Total file time: "
-                    (org-minutes-to-clocksum-string 
org-clock-file-total-minutes)
-                    " (%d hours and %d minutes)") h m)))
-
-(defvar org-clock-overlays nil)
-(make-variable-buffer-local 'org-clock-overlays)
-
-(defun org-clock-put-overlay (time &optional level)
+    (message (concat (format "Total file time%s: "
+                            (cond (todayp " for today")
+                                  (customp " (custom)")
+                                  (t "")))
+                    (org-minutes-to-clocksum-string
+                     org-clock-file-total-minutes)
+                    " (%d hours and %d minutes)")
+            h m)))
+
+(defvar-local org-clock-overlays nil)
+
+(defun org-clock-put-overlay (time)
   "Put an overlays on the current line, displaying TIME.
-If LEVEL is given, prefix time with a corresponding number of stars.
 This creates a new overlay and stores it in `org-clock-overlays', so that it
 will be easy to remove."
-  (let* ((l (if level (org-get-valid-level level 0) 0))
-        ov tx)
+  (let (ov tx)
     (beginning-of-line)
-    (when (looking-at org-complex-heading-regexp)
-      (goto-char (match-beginning 4)))
+    (let ((case-fold-search nil))
+      (when (looking-at org-complex-heading-regexp)
+       (goto-char (match-beginning 4))))
     (setq ov (make-overlay (point) (point-at-eol))
-         tx (concat (buffer-substring-no-properties (point) (match-end 4))
-                    (make-string
-                     (max 0 (- (- 60 (current-column))
-                               (- (match-end 4) (match-beginning 4))
-                               (length (org-get-at-bol 'line-prefix)))) ?.)
-                    (org-add-props (concat (make-string l ?*) " "
-                                           (org-minutes-to-clocksum-string 
time)
-                                           (make-string (- 16 l) ?\ ))
-                        (list 'face 'org-clock-overlay))
+         tx (concat (buffer-substring-no-properties (point) (match-end 4))
+                    (org-add-props
+                        (make-string
+                         (max 0 (- (- 60 (current-column))
+                                   (- (match-end 4) (match-beginning 4))
+                                   (length (org-get-at-bol 'line-prefix))))
+                         ?\·)
+                        '(face shadow))
+                    (org-add-props
+                        (format " %9s " (org-minutes-to-clocksum-string time))
+                        '(face org-clock-overlay))
                     ""))
-    (if (not (featurep 'xemacs))
-       (overlay-put ov 'display tx)
-      (overlay-put ov 'invisible t)
-      (overlay-put ov 'end-glyph (make-glyph tx)))
+    (overlay-put ov 'display tx)
     (push ov org-clock-overlays)))
 
 ;;;###autoload
-(defun org-clock-remove-overlays (&optional beg end noremove)
+(defun org-clock-remove-overlays (&optional _beg _end noremove)
   "Remove the occur highlights from the buffer.
-BEG and END are ignored.  If NOREMOVE is nil, remove this function
-from the `before-change-functions' in the current buffer."
+If NOREMOVE is nil, remove this function from the
+`before-change-functions' in the current buffer."
   (interactive)
   (unless org-inhibit-highlight-removal
-    (mapc 'delete-overlay org-clock-overlays)
+    (mapc #'delete-overlay org-clock-overlays)
     (setq org-clock-overlays nil)
     (unless noremove
       (remove-hook 'before-change-functions
@@ -2020,127 +2116,159 @@ buffer and update it."
 
 (defun org-clock-special-range (key &optional time as-strings wstart mstart)
   "Return two times bordering a special time range.
-Key is a symbol specifying the range and can be one of `today', `yesterday',
-`thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'.
-By default, a week starts Monday 0:00 and ends Sunday 24:00.
-The range is determined relative to TIME, which defaults to current time.
-The return value is a cons cell with two internal times like the ones
-returned by `current time' or `encode-time'.
-If AS-STRINGS is non-nil, the returned times will be formatted strings.
-If WSTART is non-nil, use this number to specify the starting day of a
-week (monday is 1).
-If MSTART is non-nil, use this number to specify the starting day of a
-month (1 is the first day of the month).
-If you can combine both, the month starting day will have priority."
-  (if (integerp key) (setq key (intern (number-to-string key))))
+
+KEY is a symbol specifying the range and can be one of `today',
+`yesterday', `thisweek', `lastweek', `thismonth', `lastmonth',
+`thisyear', `lastyear' or `untilnow'.  If set to `interactive',
+user is prompted for range boundaries.  It can be a string or an
+integer.
+
+By default, a week starts Monday 0:00 and ends Sunday 24:00.  The
+range is determined relative to TIME, which defaults to current
+time.
+
+The return value is a list containing two internal times, one for
+the beginning of the range and one for its end, like the ones
+returned by `current time' or `encode-time' and a string used to
+display information.  If AS-STRINGS is non-nil, the returned
+times will be formatted strings.
+
+If WSTART is non-nil, use this number to specify the starting day
+of a week (monday is 1).  If MSTART is non-nil, use this number
+to specify the starting day of a month (1 is the first day of the
+month).  If you can combine both, the month starting day will
+have priority."
   (let* ((tm (decode-time time))
-        (s 0) (m (nth 1 tm)) (h (nth 2 tm))
-        (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
+        (m (nth 1 tm))
+        (h (nth 2 tm))
+        (d (nth 3 tm))
+        (month (nth 4 tm))
+        (y (nth 5 tm))
         (dow (nth 6 tm))
-        (ws (or wstart 1))
-        (ms (or mstart 1))
-        (skey (symbol-name key))
+        (skey (format "%s" key))
         (shift 0)
-         (q (cond ((>= (nth 4 tm) 10) 4)
-                  ((>= (nth 4 tm) 7) 3)
-                  ((>= (nth 4 tm) 4) 2)
-                  ((>= (nth 4 tm) 1) 1)))
-        s1 m1 h1 d1 month1 y1 diff ts te fm txt w date
-        interval tmp shiftedy shiftedm shiftedq)
+        (q (cond ((>= month 10) 4)
+                 ((>= month 7) 3)
+                 ((>= month 4) 2)
+                 (t 1)))
+        m1 h1 d1 month1 y1 shiftedy shiftedm shiftedq)
     (cond
-     ((string-match "^[0-9]+$" skey)
-      (setq y (string-to-number skey) m 1 d 1 key 'year))
-     ((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)$" skey)
+     ((string-match "\\`[0-9]+\\'" skey)
+      (setq y (string-to-number skey) month 1 d 1 key 'year))
+     ((string-match "\\`\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)\\'" skey)
       (setq y (string-to-number (match-string 1 skey))
            month (string-to-number (match-string 2 skey))
-           d 1 key 'month))
-     ((string-match "^\\([0-9]+\\)-[wW]\\([0-9]\\{1,2\\}\\)$" skey)
+           d 1
+           key 'month))
+     ((string-match "\\`\\([0-9]+\\)-[wW]\\([0-9]\\{1,2\\}\\)\\'" skey)
       (require 'cal-iso)
-      (setq y (string-to-number (match-string 1 skey))
-           w (string-to-number (match-string 2 skey)))
-      (setq date (calendar-gregorian-from-absolute
-                 (calendar-absolute-from-iso (list w 1 y))))
-      (setq d (nth 1 date) month (car date) y (nth 2 date)
-           dow 1
-           key 'week))
-     ((string-match "^\\([0-9]+\\)-[qQ]\\([1-4]\\)$" skey)
+      (let ((date (calendar-gregorian-from-absolute
+                  (calendar-iso-to-absolute
+                   (list (string-to-number (match-string 2 skey))
+                         1
+                         (string-to-number (match-string 1 skey)))))))
+       (setq d (nth 1 date)
+             month (car date)
+             y (nth 2 date)
+             dow 1
+             key 'week)))
+     ((string-match "\\`\\([0-9]+\\)-[qQ]\\([1-4]\\)\\'" skey)
       (require 'cal-iso)
-      (setq y (string-to-number (match-string 1 skey)))
       (setq q (string-to-number (match-string 2 skey)))
-      (setq date (calendar-gregorian-from-absolute
-                 (calendar-absolute-from-iso (org-quarter-to-date q y))))
-      (setq d (nth 1 date) month (car date) y (nth 2 date)
-            dow 1
-            key 'quarter))
-     ((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)-\\([0-9]\\{1,2\\}\\)$" 
skey)
+      (let ((date (calendar-gregorian-from-absolute
+                  (calendar-iso-to-absolute
+                   (org-quarter-to-date
+                    q (string-to-number (match-string 1 skey)))))))
+       (setq d (nth 1 date)
+             month (car date)
+             y (nth 2 date)
+             dow 1
+             key 'quarter)))
+     ((string-match
+       "\\`\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)-\\([0-9]\\{1,2\\}\\)\\'"
+       skey)
       (setq y (string-to-number (match-string 1 skey))
            month (string-to-number (match-string 2 skey))
            d (string-to-number (match-string 3 skey))
            key 'day))
-     ((string-match "\\([-+][0-9]+\\)$" skey)
+     ((string-match "\\([-+][0-9]+\\)\\'" skey)
       (setq shift (string-to-number (match-string 1 skey))
-            key (intern (substring skey 0 (match-beginning 1))))
-      (if (and (memq key '(quarter thisq)) (> shift 0))
-         (error "Looking forward with quarters isn't implemented"))))
-
+           key (intern (substring skey 0 (match-beginning 1))))
+      (when (and (memq key '(quarter thisq)) (> shift 0))
+       (error "Looking forward with quarters isn't implemented"))))
     (when (= shift 0)
-      (cond ((eq key 'yesterday) (setq key 'today   shift -1))
-            ((eq key 'lastweek)  (setq key 'week    shift -1))
-            ((eq key 'lastmonth) (setq key 'month   shift -1))
-            ((eq key 'lastyear)  (setq key 'year    shift -1))
-            ((eq key 'lastq)     (setq key 'quarter shift -1))))
-    (cond
-     ((memq key '(day today))
-      (setq d (+ d shift) h 0 m 0 h1 24 m1 0))
-     ((memq key '(week thisweek))
-      (setq diff (+ (* -7 shift) (if (= dow 0) (- 7 ws) (- dow ws)))
-           m 0 h 0 d (- d diff) d1 (+ 7 d)))
-     ((memq key '(month thismonth))
-      (setq d (or ms 1) h 0 m 0 d1 (or ms 1)
-           month (+ month shift) month1 (1+ month) h1 0 m1 0))
-     ((memq key '(quarter thisq))
-      ;; Compute if this shift remains in this year.  If not, compute
-      ;; how many years and quarters we have to shift (via floor*) and
-      ;; compute the shifted years, months and quarters.
-      (cond
-       ((< (+ (- q 1) shift) 0) ; shift not in this year
-       (setq interval (* -1 (+ (- q 1) shift)))
-       ;; Set tmp to ((years to shift) (quarters to shift)).
-       (setq tmp (org-floor* interval 4))
-       ;; Due to the use of floor, 0 quarters actually means 4.
-       (if (= 0 (nth 1 tmp))
-           (setq shiftedy (- y (nth 0 tmp))
-                 shiftedm 1
-                 shiftedq 1)
-         (setq shiftedy (- y (+ 1 (nth 0 tmp)))
-               shiftedm (- 13 (* 3 (nth 1 tmp)))
-               shiftedq (- 5 (nth 1 tmp))))
-       (setq d 1 h 0 m 0 d1 1 month shiftedm month1 (+ 3 shiftedm) h1 0 m1 0 y 
shiftedy))
-       ((> (+ q shift) 0) ; shift is within this year
-       (setq shiftedq (+ q shift))
-       (setq shiftedy y)
-       (setq d 1 h 0 m 0 d1 1 month (+ 1 (* 3 (- (+ q shift) 1))) month1 (+ 4 
(* 3 (- (+ q shift) 1))) h1 0 m1 0))))
-     ((memq key '(year thisyear))
-      (setq m 0 h 0 d 1 month 1 y (+ y shift) y1 (1+ y)))
-     (t (error "No such time block %s" key)))
-    (setq ts (encode-time s m h d month y)
-         te (encode-time (or s1 s) (or m1 m) (or h1 h)
-                         (or d1 d) (or month1 month) (or y1 y)))
-    (setq fm (cdr org-time-stamp-formats))
-    (cond
-     ((memq key '(day today))
-      (setq txt (format-time-string "%A, %B %d, %Y" ts)))
-     ((memq key '(week thisweek))
-      (setq txt (format-time-string "week %G-W%V" ts)))
-     ((memq key '(month thismonth))
-      (setq txt (format-time-string "%B %Y" ts)))
-     ((memq key '(year thisyear))
-      (setq txt (format-time-string "the year %Y" ts)))
-     ((memq key '(quarter thisq))
-      (setq txt (concat (org-count-quarter shiftedq) " quarter of " 
(number-to-string shiftedy)))))
-    (if as-strings
-       (list (format-time-string fm ts) (format-time-string fm te) txt)
-      (list ts te txt))))
+      (pcase key
+       (`yesterday (setq key 'today   shift -1))
+       (`lastweek  (setq key 'week    shift -1))
+       (`lastmonth (setq key 'month   shift -1))
+       (`lastyear  (setq key 'year    shift -1))
+       (`lastq     (setq key 'quarter shift -1))))
+    ;; Prepare start and end times depending on KEY's type.
+    (pcase key
+      ((or `day `today) (setq m 0 h 0 h1 24 d (+ d shift)))
+      ((or `week `thisweek)
+       (let* ((ws (or wstart 1))
+             (diff (+ (* -7 shift) (if (= dow 0) (- 7 ws) (- dow ws)))))
+        (setq m 0 h 0 d (- d diff) d1 (+ 7 d))))
+      ((or `month `thismonth)
+       (setq h 0 m 0 d (or mstart 1) month (+ month shift) month1 (1+ month)))
+      ((or `quarter `thisq)
+       ;; Compute if this shift remains in this year.  If not, compute
+       ;; how many years and quarters we have to shift (via floor*) and
+       ;; compute the shifted years, months and quarters.
+       (cond
+       ((< (+ (- q 1) shift) 0)        ; Shift not in this year.
+        (let* ((interval (* -1 (+ (- q 1) shift)))
+               ;; Set tmp to ((years to shift) (quarters to shift)).
+               (tmp (cl-floor interval 4)))
+          ;; Due to the use of floor, 0 quarters actually means 4.
+          (if (= 0 (nth 1 tmp))
+              (setq shiftedy (- y (nth 0 tmp))
+                    shiftedm 1
+                    shiftedq 1)
+            (setq shiftedy (- y (+ 1 (nth 0 tmp)))
+                  shiftedm (- 13 (* 3 (nth 1 tmp)))
+                  shiftedq (- 5 (nth 1 tmp)))))
+        (setq m 0 h 0 d 1 month shiftedm month1 (+ 3 shiftedm) y shiftedy))
+       ((> (+ q shift) 0)              ; Shift is within this year.
+        (setq shiftedq (+ q shift))
+        (setq shiftedy y)
+        (let ((qshift (* 3 (1- (+ q shift)))))
+          (setq m 0 h 0 d 1 month (+ 1 qshift) month1 (+ 4 qshift))))))
+      ((or `year `thisyear)
+       (setq m 0 h 0 d 1 month 1 y (+ y shift) y1 (1+ y)))
+      ((or `interactive `untilnow))    ; Special cases, ignore them.
+      (_ (user-error "No such time block %s" key)))
+    ;; Format start and end times according to AS-STRINGS.
+    (let* ((start (pcase key
+                   (`interactive (org-read-date nil t nil "Range start? "))
+                   (`untilnow org-clock--oldest-date)
+                   (_ (encode-time 0 m h d month y))))
+          (end (pcase key
+                 (`interactive (org-read-date nil t nil "Range end? "))
+                 (`untilnow (current-time))
+                 (_ (encode-time 0
+                                 (or m1 m)
+                                 (or h1 h)
+                                 (or d1 d)
+                                 (or month1 month)
+                                 (or y1 y)))))
+          (text
+           (pcase key
+             ((or `day `today) (format-time-string "%A, %B %d, %Y" start))
+             ((or `week `thisweek) (format-time-string "week %G-W%V" start))
+             ((or `month `thismonth) (format-time-string "%B %Y" start))
+             ((or `year `thisyear) (format-time-string "the year %Y" start))
+             ((or `quarter `thisq)
+              (concat (org-count-quarter shiftedq)
+                      " quarter of " (number-to-string shiftedy)))
+             (`interactive "(Range interactively set)")
+             (`untilnow "now"))))
+      (if (not as-strings) (list start end text)
+       (let ((f (cdr org-time-stamp-formats)))
+         (list (format-time-string f start)
+               (format-time-string f end)
+               text))))))
 
 (defun org-count-quarter (n)
   (cond
@@ -2196,7 +2324,7 @@ the currently selected interval size."
           ((and wp (string-match "w\\|W" wp) mw (> (length wp) 0))
            (require 'cal-iso)
            (setq date (calendar-gregorian-from-absolute
-                       (calendar-absolute-from-iso (list (+ mw n) 1 y))))
+                       (calendar-iso-to-absolute (list (+ mw n) 1 y))))
            (setq ins (format-time-string
                       "%G-W%V"
                       (encode-time 0 0 0 (nth 1 date) (car date) (nth 2 
date)))))
@@ -2213,7 +2341,7 @@ the currently selected interval size."
                      y (- y 1))
              ())
            (setq date (calendar-gregorian-from-absolute
-                       (calendar-absolute-from-iso (org-quarter-to-date (+ mw 
n) y))))
+                       (calendar-iso-to-absolute (org-quarter-to-date (+ mw n) 
y))))
            (setq ins (format-time-string
                       (concat (number-to-string y) "-Q" (number-to-string (+ 
mw n)))
                       (encode-time 0 0 0 (nth 1 date) (car date) (nth 2 
date)))))
@@ -2238,25 +2366,32 @@ the currently selected interval size."
   (setq params (org-combine-plists org-clocktable-defaults params))
   (catch 'exit
     (let* ((scope (plist-get params :scope))
+          (files (pcase scope
+                   (`agenda
+                    (org-agenda-files t))
+                   (`agenda-with-archives
+                    (org-add-archive-files (org-agenda-files t)))
+                   (`file-with-archives
+                    (and buffer-file-name
+                         (org-add-archive-files (list buffer-file-name))))
+                   ((pred consp) scope)
+                   (_ (or (buffer-file-name) (current-buffer)))))
           (block (plist-get params :block))
           (ts (plist-get params :tstart))
           (te (plist-get params :tend))
-          (link (plist-get params :link))
-          (maxlevel (or (plist-get params :maxlevel) 3))
           (ws (plist-get params :wstart))
           (ms (plist-get params :mstart))
           (step (plist-get params :step))
-          (timestamp (plist-get params :timestamp))
           (formatter (or (plist-get params :formatter)
                          org-clock-clocktable-formatter
                          'org-clocktable-write-default))
-          cc range-text ipos pos one-file-with-archives
-          scope-is-list tbls level)
+          cc)
       ;; Check if we need to do steps
       (when block
        ;; Get the range text for the header
        (setq cc (org-clock-special-range block nil t ws ms)
-             ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
+             ts (car cc)
+             te (nth 1 cc)))
       (when step
        ;; Write many tables, in steps
        (unless (or block (and ts te))
@@ -2264,63 +2399,49 @@ the currently selected interval size."
        (org-clocktable-steps params)
        (throw 'exit nil))
 
-      (setq ipos (point)) ; remember the insertion position
-
-      ;; Get the right scope
-      (setq pos (point))
-      (cond
-       ((and scope (listp scope) (symbolp (car scope)))
-       (setq scope (eval scope)))
-       ((eq scope 'agenda)
-       (setq scope (org-agenda-files t)))
-       ((eq scope 'agenda-with-archives)
-       (setq scope (org-agenda-files t))
-       (setq scope (org-add-archive-files scope)))
-       ((eq scope 'file-with-archives)
-       (setq scope (org-add-archive-files (list (buffer-file-name)))
-             one-file-with-archives t)))
-      (setq scope-is-list (and scope (listp scope)))
-      (if scope-is-list
-         ;; we collect from several files
-         (let* ((files scope)
-                file)
-           (org-agenda-prepare-buffers files)
-           (while (setq file (pop files))
-             (with-current-buffer (find-buffer-visiting file)
-               (save-excursion
-                 (save-restriction
-                   (push (org-clock-get-table-data file params) tbls))))))
-       ;; Just from the current file
-       (save-restriction
-         ;; get the right range into the restriction
-         (org-agenda-prepare-buffers (list (buffer-file-name)))
-         (cond
-          ((not scope))  ; use the restriction as it is now
-          ((eq scope 'file) (widen))
-          ((eq scope 'subtree) (org-narrow-to-subtree))
-          ((eq scope 'tree)
-           (while (org-up-heading-safe))
-           (org-narrow-to-subtree))
-          ((and (symbolp scope) (string-match "^tree\\([0-9]+\\)$"
-                                              (symbol-name scope)))
-           (setq level (string-to-number (match-string 1 (symbol-name scope))))
-           (catch 'exit
-             (while (org-up-heading-safe)
-               (looking-at org-outline-regexp)
-               (if (<= (org-reduced-level (funcall outline-level)) level)
-                   (throw 'exit nil))))
-           (org-narrow-to-subtree)))
-         ;; do the table, with no file name.
-         (push (org-clock-get-table-data nil params) tbls)))
-
-      ;; OK, at this point we tbls as a list of tables, one per file
-      (setq tbls (nreverse tbls))
-
-      (setq params (plist-put params :multifile scope-is-list))
-      (setq params (plist-put params :one-file-with-archives
-                             one-file-with-archives))
-
-      (funcall formatter ipos tbls params))))
+      (org-agenda-prepare-buffers (if (consp files) files (list files)))
+
+      (let ((origin (point))
+           (tables
+            (if (consp files)
+                (mapcar (lambda (file)
+                          (with-current-buffer (find-buffer-visiting file)
+                            (save-excursion
+                              (save-restriction
+                                (org-clock-get-table-data file params)))))
+                        files)
+              ;; Get the right restriction for the scope.
+              (save-restriction
+                (cond
+                 ((not scope))      ;use the restriction as it is now
+                 ((eq scope 'file) (widen))
+                 ((eq scope 'subtree) (org-narrow-to-subtree))
+                 ((eq scope 'tree)
+                  (while (org-up-heading-safe))
+                  (org-narrow-to-subtree))
+                 ((and (symbolp scope)
+                       (string-match "\\`tree\\([0-9]+\\)\\'"
+                                     (symbol-name scope)))
+                  (let ((level (string-to-number
+                                (match-string 1 (symbol-name scope)))))
+                    (catch 'exit
+                      (while (org-up-heading-safe)
+                        (looking-at org-outline-regexp)
+                        (when (<= (org-reduced-level (funcall outline-level))
+                                  level)
+                          (throw 'exit nil))))
+                    (org-narrow-to-subtree))))
+                (list (org-clock-get-table-data nil params)))))
+           (multifile
+            ;; Even though `file-with-archives' can consist of
+            ;; multiple files, we consider this is one extended file
+            ;; instead.
+            (and (consp files) (not (eq scope 'file-with-archives)))))
+
+       (funcall formatter
+                origin
+                tables
+                (org-combine-plists params `(:multifile ,multifile)))))))
 
 (defun org-clocktable-write-default (ipos tables params)
   "Write out a clock table at position IPOS in the current buffer.
@@ -2335,43 +2456,46 @@ from the dynamic block definition."
   ;; well-defined number of columns...
   (let* ((hlchars '((1 . "*") (2 . "/")))
         (lwords (assoc (or (plist-get params :lang)
-                           (org-bound-and-true-p org-export-default-language)
+                           (bound-and-true-p org-export-default-language)
                            "en")
                        org-clock-clocktable-language-setup))
         (multifile (plist-get params :multifile))
         (block (plist-get params :block))
-        (ts (plist-get params :tstart))
-        (te (plist-get params :tend))
-        (header (plist-get  params :header))
-        (narrow (plist-get params :narrow))
+        (sort (plist-get params :sort))
+        (header (plist-get params :header))
         (ws (or (plist-get params :wstart) 1))
         (ms (or (plist-get params :mstart) 1))
         (link (plist-get params :link))
-        (maxlevel (or (plist-get params :maxlevel) 3))
-        (emph (plist-get params :emphasize))
-        (level-p (plist-get params :level))
         (org-time-clocksum-use-effort-durations
          (plist-get params :effort-durations))
+        (maxlevel (or (plist-get params :maxlevel) 3))
+        (emph (plist-get params :emphasize))
+        (compact? (plist-get params :compact))
+        (narrow (or (plist-get params :narrow) (and compact? '40!)))
+        (level? (and (not compact?) (plist-get params :level)))
         (timestamp (plist-get params :timestamp))
         (properties (plist-get params :properties))
-        (ntcol (max 1 (or (plist-get params :tcolumns) 100)))
-        (rm-file-column (plist-get params :one-file-with-archives))
-        (indent (plist-get params :indent))
+        (time-columns
+         (if (or compact? (< maxlevel 2)) 1
+           ;; Deepest headline level is a hard limit for the number
+           ;; of time columns.
+           (let ((levels
+                  (cl-mapcan
+                   (lambda (table)
+                     (pcase table
+                       (`(,_ ,(and (pred wholenump) (pred (/= 0))) ,entries)
+                        (mapcar #'car entries))))
+                   tables)))
+             (min maxlevel
+                  (or (plist-get params :tcolumns) 100)
+                  (if (null levels) 1 (apply #'max levels))))))
+        (indent (or compact? (plist-get params :indent)))
+        (formula (plist-get params :formula))
         (case-fold-search t)
-        range-text total-time tbl level hlc formula pcol
-        file-time entries entry headline
-        recalc content narrow-cut-p tcol)
-
-    ;; Implement abbreviations
-    (when (plist-get params :compact)
-      (setq level nil indent t narrow (or narrow '40!) ntcol 1))
-
-    ;; Some consistency test for parameters
-    (unless (integerp ntcol)
-      (setq params (plist-put params :tcolumns (setq ntcol 100))))
+        range-text total-time recalc narrow-cut-p)
 
     (when (and narrow (integerp narrow) link)
-      ;; We cannot have both integer narrow and link
+      ;; We cannot have both integer narrow and link.
       (message
        "Using hard narrowing in clocktable to allow for links")
       (setq narrow (intern (format "%d!" narrow))))
@@ -2389,19 +2513,19 @@ from the dynamic block definition."
               narrow))))
 
     (when block
-      ;; Get the range text for the header
+      ;; Get the range text for the header.
       (setq range-text (nth 2 (org-clock-special-range block nil t ws ms))))
 
-    ;; Compute the total time
-    (setq total-time (apply '+ (mapcar 'cadr tables)))
+    ;; Compute the total time.
+    (setq total-time (apply #'+ (mapcar #'cadr tables)))
 
-    ;; Now we need to output this tsuff
+    ;; Now we need to output this tsuff.
     (goto-char ipos)
 
-    ;; Insert the text *before* the actual table
+    ;; Insert the text *before* the actual table.
     (insert-before-markers
      (or header
-        ;; Format the standard header
+        ;; Format the standard header.
         (concat
          "#+CAPTION: "
          (nth 9 lwords) " ["
@@ -2415,155 +2539,144 @@ from the dynamic block definition."
     ;; Insert the narrowing line
     (when (and narrow (integerp narrow) (not narrow-cut-p))
       (insert-before-markers
-       "|"                            ; table line starter
-       (if multifile "|" "")          ; file column, maybe
-       (if level-p   "|" "")          ; level column, maybe
-       (if timestamp "|" "")          ; timestamp column, maybe
-       (if properties (make-string (length properties) ?|) "")  ;properties 
columns, maybe
-       (format "<%d>| |\n" narrow)))  ; headline and time columns
+       "|"                             ;table line starter
+       (if multifile "|" "")           ;file column, maybe
+       (if level? "|" "")              ;level column, maybe
+       (if timestamp "|" "")           ;timestamp column, maybe
+       (if properties (make-string (length properties) ?|) "") ;properties 
columns, maybe
+       (format "<%d>| |\n" narrow)))   ; headline and time columns
 
     ;; Insert the table header line
     (insert-before-markers
-     "|"                              ; table line starter
-     (if multifile (concat (nth 1 lwords) "|") "")  ; file column, maybe
-     (if level-p   (concat (nth 2 lwords) "|") "")  ; level column, maybe
-     (if timestamp (concat (nth 3 lwords) "|") "")  ; timestamp column, maybe
-     (if properties (concat (mapconcat 'identity properties "|") "|") "") 
;properties columns, maybe
-     (concat (nth 4 lwords) "|"
-            (nth 5 lwords) "|\n"))                 ; headline and time columns
+     "|"                                          ;table line starter
+     (if multifile (concat (nth 1 lwords) "|") "") ;file column, maybe
+     (if level? (concat (nth 2 lwords) "|") "") ;level column, maybe
+     (if timestamp (concat (nth 3 lwords) "|") "") ;timestamp column, maybe
+     (if properties                    ;properties columns, maybe
+        (concat (mapconcat #'identity properties "|") "|")
+       "")
+     (concat (nth 4 lwords) "|")               ;headline
+     (concat (nth 5 lwords) "|")               ;time column
+     (make-string (max 0 (1- time-columns)) ?|)        ;other time columns
+     (if (eq formula '%) "%|\n" "\n"))
 
     ;; Insert the total time in the table
     (insert-before-markers
-     "|-\n"                            ; a hline
-     "|"                               ; table line starter
+     "|-\n"                            ;a hline
+     "|"                               ;table line starter
      (if multifile (concat "| " (nth 6 lwords) " ") "")
-                                       ; file column, maybe
-     (if level-p   "|"      "")        ; level column, maybe
-     (if timestamp "|"      "")        ; timestamp column, maybe
-     (if properties (make-string (length properties) ?|) "")  ; properties 
columns, maybe
-     (concat (format org-clock-total-time-cell-format (nth 7 lwords))  "| ") ; 
instead of a headline
+                                       ;file column, maybe
+     (if level?   "|"      "")         ;level column, maybe
+     (if timestamp "|"      "")                ;timestamp column, maybe
+     (make-string (length properties) ?|) ;properties columns, maybe
+     (concat (format org-clock-total-time-cell-format (nth 7 lwords))
+            "| ")
      (format org-clock-total-time-cell-format
-            (org-minutes-to-clocksum-string (or total-time 0))) ; the time
-     "|\n")                          ; close line
-
-    ;; Now iterate over the tables and insert the data
-    ;; but only if any time has been collected
+            (org-minutes-to-clocksum-string (or total-time 0))) ;time
+     "|"
+     (make-string (max 0 (1- time-columns)) ?|)
+     (cond ((not (eq formula '%)) "")
+          ((or (not total-time) (= total-time 0)) "0.0|")
+          (t  "100.0|"))
+     "\n")
+
+    ;; Now iterate over the tables and insert the data but only if any
+    ;; time has been collected.
     (when (and total-time (> total-time 0))
-
-      (while (setq tbl (pop tables))
-       ;; now tbl is the table resulting from one file.
-       (setq file-time (nth 1 tbl))
+      (pcase-dolist (`(,file-name ,file-time ,entries) tables)
        (when (or (and file-time (> file-time 0))
                  (not (plist-get params :fileskip0)))
-         (insert-before-markers "|-\n")  ; a hline because a new file starts
-         ;; First the file time, if we have multiple files
+         (insert-before-markers "|-\n") ;hline at new file
+         ;; First the file time, if we have multiple files.
          (when multifile
-           ;; Summarize the time collected from this file
+           ;; Summarize the time collected from this file.
            (insert-before-markers
             (format (concat "| %s %s | %s%s"
-                            (format org-clock-file-time-cell-format (nth 8 
lwords))
+                            (format org-clock-file-time-cell-format
+                                    (nth 8 lwords))
                             " | *%s*|\n")
-                    (file-name-nondirectory (car tbl))
-                    (if level-p   "| " "") ; level column, maybe
-                    (if timestamp "| " "") ; timestamp column, maybe
-                    (if properties (make-string (length properties) ?|) "")  
;properties columns, maybe
-                    (org-minutes-to-clocksum-string (nth 1 tbl))))) ; the time
+                    (file-name-nondirectory file-name)
+                    (if level?   "| " "")  ;level column, maybe
+                    (if timestamp "| " "") ;timestamp column, maybe
+                    (if properties         ;properties columns, maybe
+                        (make-string (length properties) ?|)
+                      "")
+                    (org-minutes-to-clocksum-string file-time)))) ;time
 
          ;; Get the list of node entries and iterate over it
-         (setq entries (nth 2 tbl))
-         (while (setq entry (pop entries))
-           (setq level (car entry)
-                 headline (nth 1 entry)
-                 hlc (if emph (or (cdr (assoc level hlchars)) "") ""))
-           (when narrow-cut-p
-             (if (and (string-match (concat "\\`" org-bracket-link-regexp
-                                            "\\'")
-                                    headline)
-                      (match-end 3))
-                 (setq headline
-                       (format "[[%s][%s]]"
-                               (match-string 1 headline)
-                               (org-shorten-string (match-string 3 headline)
-                                                   narrow)))
-               (setq headline (org-shorten-string headline narrow))))
-           (insert-before-markers
-            "|"                      ; start the table line
-            (if multifile "|" "")    ; free space for file name column?
-            (if level-p (format "%d|" (car entry)) "")   ; level, maybe
-            (if timestamp (concat (nth 2 entry) "|") "") ; timestamp, maybe
-            (if properties
-                (concat
-                 (mapconcat
-                  (lambda (p) (or (cdr (assoc p (nth 4 entry))) ""))
-                  properties "|") "|") "")  ;properties columns, maybe
-            (if indent (org-clocktable-indent-string level) "") ; indentation
-            hlc headline hlc "|"                                ; headline
-            (make-string (min (1- ntcol) (or (- level 1))) ?|)
-                                       ; empty fields for higher levels
-            hlc (org-minutes-to-clocksum-string (nth 3 entry)) hlc ; time
-            "|\n"                                               ; close line
-            )))))
-    ;; When exporting subtrees or regions the region might be
-    ;; activated, so let's disable ̀delete-active-region'
-    (let ((delete-active-region nil)) (backward-delete-char 1))
-    (if (setq formula (plist-get params :formula))
-       (cond
-        ((eq formula '%)
-         ;; compute the column where the % numbers need to go
-         (setq pcol (+ 2
-                       (if multifile 1 0)
-                       (if level-p 1 0)
-                       (if timestamp 1 0)
-                       (min maxlevel (or ntcol 100))))
-         ;; compute the column where the total time is
-         (setq tcol (+ 2
-                       (if multifile 1 0)
-                       (if level-p 1 0)
-                       (if timestamp 1 0)))
-         (insert
-          (format
-           "\n#+TBLFM: $%d='(org-clock-time%% @%d$%d $%d..$%d);%%.1f"
-           pcol            ; the column where the % numbers should go
-           (if (and narrow (not narrow-cut-p)) 3 2) ; row of the total time
-           tcol            ; column of the total time
-           tcol (1- pcol)  ; range of columns where times can be found
-           ))
-         (setq recalc t))
-        ((stringp formula)
-         (insert "\n#+TBLFM: " formula)
-         (setq recalc t))
-        (t (error "Invalid formula in clocktable")))
-      ;; Should we rescue an old formula?
-      (when (stringp (setq content (plist-get params :content)))
-       (when (string-match "^\\([ \t]*#\\+tblfm:.*\\)" content)
+         (when (> maxlevel 0)
+           (pcase-dolist (`(,level ,headline ,ts ,time ,props) entries)
+             (when narrow-cut-p
+               (setq headline
+                     (if (and (string-match
+                               (format "\\`%s\\'" org-bracket-link-regexp)
+                               headline)
+                              (match-end 3))
+                         (format "[[%s][%s]]"
+                                 (match-string 1 headline)
+                                 (org-shorten-string (match-string 3 headline)
+                                                     narrow))
+                       (org-shorten-string headline narrow))))
+             (let ((hlc (if emph (or (cdr (assoc level hlchars)) "") "")))
+               (insert-before-markers
+                "|"                   ;start the table line
+                (if multifile "|" "") ;free space for file name column?
+                (if level? (format "%d|" level) "") ;level, maybe
+                (if timestamp (concat ts "|") "")   ;timestamp, maybe
+                (if properties         ;properties columns, maybe
+                    (concat (mapconcat (lambda (p)
+                                         (or (cdr (assoc p props)) ""))
+                                       properties
+                                       "|")
+                            "|")
+                  "")
+                (if indent             ;indentation
+                    (org-clocktable-indent-string level)
+                  "")
+                hlc headline hlc "|"   ;headline
+                ;; Empty fields for higher levels.
+                (make-string (max 0 (1- (min time-columns level))) ?|)
+                hlc (org-minutes-to-clocksum-string time) hlc "|" ; time
+                (make-string (max 0 (- time-columns level)) ?|)
+                (if (eq formula '%)
+                    (format "%.1f |" (* 100 (/ time (float total-time))))
+                  "")
+                "\n")))))))
+    (delete-char -1)
+    (cond
+     ;; Possibly rescue old formula?
+     ((or (not formula) (eq formula '%))
+      (let ((contents (org-string-nw-p (plist-get params :content))))
+       (when (and contents (string-match "^\\([ \t]*#\\+tblfm:.*\\)" contents))
          (setq recalc t)
-         (insert "\n" (match-string 1 (plist-get params :content)))
+         (insert "\n" (match-string 1 contents))
          (beginning-of-line 0))))
-    ;; Back to beginning, align the table, recalculate if necessary
+     ;; Insert specified formula line.
+     ((stringp formula)
+      (insert "\n#+TBLFM: " formula)
+      (setq recalc t))
+     (t
+      (user-error "Invalid :formula parameter in clocktable")))
+    ;; Back to beginning, align the table, recalculate if necessary.
     (goto-char ipos)
     (skip-chars-forward "^|")
     (org-table-align)
     (when org-hide-emphasis-markers
-      ;; we need to align a second time
+      ;; We need to align a second time.
       (org-table-align))
-    (when recalc
-      (if (eq formula '%)
-         (save-excursion
-           (if (and narrow (not narrow-cut-p)) (beginning-of-line 2))
-           (org-table-goto-column pcol nil 'force)
-           (insert "%")))
-      (org-table-recalculate 'all))
-    (when rm-file-column
-      ;; The file column is actually not wanted
-      (forward-char 1)
-      (org-table-delete-column))
+    (when sort
+      (save-excursion
+       (org-table-goto-line 3)
+       (org-table-goto-column (car sort))
+       (org-table-sort-lines nil (cdr sort))))
+    (when recalc (org-table-recalculate 'all))
     total-time))
 
 (defun org-clocktable-indent-string (level)
+  "Return indentation string according to LEVEL.
+LEVEL is an integer.  Indent by two spaces per level above 1."
   (if (= level 1) ""
-    (let ((str " "))
-      (dotimes (k (1- level) str)
-       (setq str (concat "\\emsp" str))))))
+    (concat "\\_" (make-string (* 2 (1- level)) ?\s))))
 
 (defun org-clocktable-steps (params)
   "Step through the range to make a number of clock tables."
@@ -2576,26 +2689,28 @@ from the dynamic block definition."
         (step (cdr (assoc step0 '((day . 86400) (week . 604800)))))
         (stepskip0 (plist-get p1 :stepskip0))
         (block (plist-get p1 :block))
-        cc range-text step-time tsb)
+        cc step-time tsb)
     (when block
       (setq cc (org-clock-special-range block nil t ws ms)
-           ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
+           ts (car cc)
+           te (nth 1 cc)))
     (cond
      ((numberp ts)
-      ;; If ts is a number, it's an absolute day number from org-agenda.
-      (destructuring-bind (month day year) (calendar-gregorian-from-absolute 
ts)
+      ;; If ts is a number, it's an absolute day number from
+      ;; org-agenda.
+      (pcase-let ((`(,month ,day ,year) (calendar-gregorian-from-absolute ts)))
        (setq ts (float-time (encode-time 0 0 0 day month year)))))
      (ts
       (setq ts (float-time
-               (apply 'encode-time (org-parse-time-string ts))))))
+               (apply #'encode-time (org-parse-time-string ts nil t))))))
     (cond
      ((numberp te)
       ;; Likewise for te.
-      (destructuring-bind (month day year) (calendar-gregorian-from-absolute 
te)
+      (pcase-let ((`(,month ,day ,year) (calendar-gregorian-from-absolute te)))
        (setq te (float-time (encode-time 0 0 0 day month year)))))
      (te
       (setq te (float-time
-               (apply 'encode-time (org-parse-time-string te))))))
+               (apply #'encode-time (org-parse-time-string te nil t))))))
     (setq tsb
          (if (eq step0 'week)
              (- ts (* 86400 (- (nth 6 (decode-time (seconds-to-time ts))) ws)))
@@ -2635,19 +2750,22 @@ file time (in minutes) as 1st and 2nd elements.  The 
third element
 of this list will be a list of headline entries.  Each entry has the
 following structure:
 
-  (LEVEL HEADLINE TIMESTAMP TIME)
-
-LEVEL:     The level of the headline, as an integer.  This will be
-           the reduced leve, so 1,2,3,... even if only odd levels
-           are being used.
-HEADLINE:  The text of the headline.  Depending on PARAMS, this may
-           already be formatted like a link.
-TIMESTAMP: If PARAMS require it, this will be a time stamp found in the
-           entry, any of SCHEDULED, DEADLINE, NORMAL, or first inactive,
-           in this sequence.
-TIME:      The sum of all time spend in this tree, in minutes.  This time
-           will of cause be restricted to the time block and tags match
-           specified in PARAMS."
+  (LEVEL HEADLINE TIMESTAMP TIME PROPERTIES)
+
+LEVEL:      The level of the headline, as an integer.  This will be
+            the reduced level, so 1,2,3,... even if only odd levels
+            are being used.
+HEADLINE:   The text of the headline.  Depending on PARAMS, this may
+            already be formatted like a link.
+TIMESTAMP:  If PARAMS require it, this will be a time stamp found in the
+            entry, any of SCHEDULED, DEADLINE, NORMAL, or first inactive,
+            in this sequence.
+TIME:       The sum of all time spend in this tree, in minutes.  This time
+            will of cause be restricted to the time block and tags match
+            specified in PARAMS.
+PROPERTIES: The list properties specified in the `:properties' parameter
+            along with their value, as an alist following the pattern
+            (NAME . VALUE)."
   (let* ((maxlevel (or (plist-get params :maxlevel) 3))
         (timestamp (plist-get params :timestamp))
         (ts (plist-get params :tstart))
@@ -2659,14 +2777,14 @@ TIME:      The sum of all time spend in this tree, in 
minutes.  This time
         (tags (plist-get params :tags))
         (properties (plist-get params :properties))
         (inherit-property-p (plist-get params :inherit-props))
-        todo-only
-        (matcher (if tags (cdr (org-make-tags-matcher tags))))
-        cc range-text st p time level hdl props tsp tbl)
+        (matcher (and tags (cdr (org-make-tags-matcher tags))))
+        cc st p tbl)
 
     (setq org-clock-file-total-minutes nil)
     (when block
       (setq cc (org-clock-special-range block nil t ws ms)
-           ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
+           ts (car cc)
+           te (nth 1 cc)))
     (when (integerp ts) (setq ts (calendar-gregorian-from-absolute ts)))
     (when (integerp te) (setq te (calendar-gregorian-from-absolute te)))
     (when (and ts (listp ts))
@@ -2678,12 +2796,12 @@ TIME:      The sum of all time spend in this tree, in 
minutes.  This time
     (if te (setq te (org-matcher-time te)))
     (save-excursion
       (org-clock-sum ts te
-                    (unless (null matcher)
-                      (lambda ()
-                        (let* ((tags-list (org-get-tags-at))
-                               (org-scanner-tags tags-list)
-                               (org-trust-scanner-tags t))
-                          (eval matcher)))))
+                    (when matcher
+                      `(lambda ()
+                         (let* ((tags-list (org-get-tags-at))
+                                (org-scanner-tags tags-list)
+                                (org-trust-scanner-tags t))
+                           (funcall ,matcher nil tags-list nil)))))
       (goto-char (point-min))
       (setq st t)
       (while (or (and (bobp) (prog1 st (setq st nil))
@@ -2692,66 +2810,46 @@ TIME:      The sum of all time spend in this tree, in 
minutes.  This time
                 (setq p (next-single-property-change
                          (point) :org-clock-minutes)))
        (goto-char p)
-       (when (setq time (get-text-property p :org-clock-minutes))
-         (save-excursion
-           (beginning-of-line 1)
-           (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ 
\t]+:[[:alnum:address@hidden:]+:\\)?[ \t]*$"))
-                      (setq level (org-reduced-level
-                                   (- (match-end 1) (match-beginning 1))))
-                      (<= level maxlevel))
-             (setq hdl (if (not link)
-                           (match-string 2)
-                         (org-make-link-string
-                          (format "file:%s::%s"
-                                  (buffer-file-name)
-                                  (save-match-data
-                                    (match-string 2)))
-                          (org-make-org-heading-search-string
-                           (replace-regexp-in-string
-                            org-bracket-link-regexp
-                            (lambda (m) (or (match-string 3 m)
-                                            (match-string 1 m)))
-                            (match-string 2)))))
-                   tsp (when timestamp
-                         (setq props (org-entry-properties (point)))
-                         (or (cdr (assoc "SCHEDULED" props))
-                             (cdr (assoc "DEADLINE" props))
-                             (cdr (assoc "TIMESTAMP" props))
-                             (cdr (assoc "TIMESTAMP_IA" props))))
-                   props (when properties
-                           (remove nil
-                                   (mapcar
-                                    (lambda (p)
-                                      (when (org-entry-get (point) p 
inherit-property-p)
-                                        (cons p (org-entry-get (point) p 
inherit-property-p))))
-                                    properties))))
-             (when (> time 0) (push (list level hdl tsp time props) tbl))))))
-      (setq tbl (nreverse tbl))
-      (list file org-clock-file-total-minutes tbl))))
-
-(defun org-clock-time% (total &rest strings)
-  "Compute a time fraction in percent.
-TOTAL s a time string like 10:21 specifying the total times.
-STRINGS is a list of strings that should be checked for a time.
-The first string that does have a time will be used.
-This function is made for clock tables."
-  (let ((re "\\([0-9]+\\):\\([0-9]+\\)")
-       tot s)
-    (save-match-data
-      (catch 'exit
-       (if (not (string-match re total))
-           (throw 'exit 0.)
-         (setq tot (+ (string-to-number (match-string 2 total))
-                      (* 60 (string-to-number (match-string 1 total)))))
-         (if (= tot 0.) (throw 'exit 0.)))
-       (while (setq s (pop strings))
-         (if (string-match "\\([0-9]+\\):\\([0-9]+\\)" s)
-             (throw 'exit
-                    (/ (* 100.0 (+ (string-to-number (match-string 2 s))
-                                   (* 60 (string-to-number
-                                          (match-string 1 s)))))
-                       tot))))
-       0))))
+       (let ((time (get-text-property p :org-clock-minutes)))
+         (when (and time (> time 0) (org-at-heading-p))
+           (let ((level (org-reduced-level (org-current-level))))
+             (when (<= level maxlevel)
+               (let* ((headline (replace-regexp-in-string
+                                 (format "\\`%s[ \t]+" org-comment-string) ""
+                                 (nth 4 (org-heading-components))))
+                      (hdl
+                       (if (not link) headline
+                         (let ((search
+                                (org-make-org-heading-search-string headline)))
+                           (org-make-link-string
+                            (if (not (buffer-file-name)) search
+                              (format "file:%s::%s" (buffer-file-name) search))
+                            ;; Prune statistics cookies.  Replace
+                            ;; links with their description, or
+                            ;; a plain link if there is none.
+                            (org-trim
+                             (org-link-display-format
+                              (replace-regexp-in-string
+                               "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
+                               headline)))))))
+                      (tsp
+                       (and timestamp
+                            (let ((p (org-entry-properties (point) 'special)))
+                              (or (cdr (assoc "SCHEDULED" p))
+                                  (cdr (assoc "DEADLINE" p))
+                                  (cdr (assoc "TIMESTAMP" p))
+                                  (cdr (assoc "TIMESTAMP_IA" p))))))
+                      (props
+                       (and properties
+                            (delq nil
+                                  (mapcar
+                                   (lambda (p)
+                                     (let ((v (org-entry-get
+                                               (point) p inherit-property-p)))
+                                       (and v (cons p v))))
+                                   properties)))))
+                 (push (list level hdl tsp time props) tbl)))))))
+      (list file org-clock-file-total-minutes (nreverse tbl)))))
 
 ;; Saving and loading the clock
 
@@ -2789,9 +2887,9 @@ Otherwise, return nil."
          (setq ts (match-string 1)
                te (match-string 3))
          (setq s (- (float-time
-                     (apply 'encode-time (org-parse-time-string te)))
+                     (apply #'encode-time (org-parse-time-string te nil t)))
                     (float-time
-                     (apply 'encode-time (org-parse-time-string ts))))
+                     (apply #'encode-time (org-parse-time-string ts nil t))))
                neg (< s 0)
                s (abs s)
                h (floor (/ s 3600))
@@ -2809,86 +2907,67 @@ The details of what will be saved are regulated by the 
variable
              (or org-clock-loaded
                 org-clock-has-been-used
                 (not (file-exists-p org-clock-persist-file))))
-    (let (b)
-      (with-current-buffer (find-file (expand-file-name 
org-clock-persist-file))
-       (progn
-         (delete-region (point-min) (point-max))
-         ;;Store clock
-         (insert (format ";; org-persist.el - %s at %s\n"
-                         (system-name) (format-time-string
-                                        (cdr org-time-stamp-formats))))
-         (if (and (memq org-clock-persist '(t clock))
-                  (setq b (org-clocking-buffer))
-                  (setq b (or (buffer-base-buffer b) b))
-                  (buffer-live-p b)
-                  (buffer-file-name b)
-                  (or (not org-clock-persist-query-save)
-                      (y-or-n-p (concat "Save current clock ("
-                                        org-clock-heading ") "))))
-             (insert "(setq resume-clock '(\""
-                     (buffer-file-name (org-clocking-buffer))
-                     "\" . " (int-to-string (marker-position org-clock-marker))
-                     "))\n"))
-         ;; Store clocked task history.  Tasks are stored reversed to make
-         ;; reading simpler
-         (when (and (memq org-clock-persist '(t history))
-                    org-clock-history)
-           (insert
-            "(setq stored-clock-history '("
-            (mapconcat
-             (lambda (m)
-               (when (and (setq b (marker-buffer m))
-                          (setq b (or (buffer-base-buffer b) b))
-                          (buffer-live-p b)
-                          (buffer-file-name b))
-                 (concat "(\"" (buffer-file-name b)
-                         "\" . " (int-to-string (marker-position m))
-                         ")")))
-             (reverse org-clock-history) " ") "))\n"))
-         (save-buffer)
-         (kill-buffer (current-buffer)))))))
+    (with-temp-file org-clock-persist-file
+      (insert (format ";; %s - %s at %s\n"
+                     (file-name-nondirectory org-clock-persist-file)
+                     (system-name)
+                     (format-time-string (org-time-stamp-format t))))
+      ;; Store clock to be resumed.
+      (when (and (memq org-clock-persist '(t clock))
+                (let ((b (org-base-buffer (org-clocking-buffer))))
+                  (and (buffer-live-p b)
+                       (buffer-file-name b)
+                       (or (not org-clock-persist-query-save)
+                           (y-or-n-p (format "Save current clock (%s) "
+                                             org-clock-heading))))))
+       (insert
+        (format "(setq org-clock-stored-resume-clock '(%S . %d))\n"
+                (buffer-file-name (org-base-buffer (org-clocking-buffer)))
+                (marker-position org-clock-marker))))
+      ;; Store clocked task history.  Tasks are stored reversed to
+      ;; make reading simpler.
+      (when (and (memq org-clock-persist '(t history))
+                org-clock-history)
+       (insert
+        (format "(setq org-clock-stored-history '(%s))\n"
+                (mapconcat
+                 (lambda (m)
+                   (let ((b (org-base-buffer (marker-buffer m))))
+                     (when (and (buffer-live-p b)
+                                (buffer-file-name b))
+                       (format "(%S . %d)"
+                               (buffer-file-name b)
+                               (marker-position m)))))
+                 (reverse org-clock-history)
+                 " ")))))))
 
 (defun org-clock-load ()
   "Load clock-related data from disk, maybe resuming a stored clock."
   (when (and org-clock-persist (not org-clock-loaded))
-    (let ((filename (expand-file-name org-clock-persist-file))
-         (org-clock-in-resume 'auto-restart)
-         resume-clock stored-clock-history)
-      (if (not (file-readable-p filename))
-         (message "Not restoring clock data; %s not found"
-                  org-clock-persist-file)
-       (message "%s" "Restoring clock data")
-       (setq org-clock-loaded t)
-       (load-file filename)
-       ;; load history
-       (when stored-clock-history
-         (save-window-excursion
-           (mapc (lambda (task)
-                   (if (file-exists-p (car task))
-                       (org-clock-history-push (cdr task)
-                                               (find-file (car task)))))
-                 stored-clock-history)))
-       ;; resume clock
-       (when (and resume-clock org-clock-persist
-                  (file-exists-p (car resume-clock))
-                  (or (not org-clock-persist-query-resume)
-                      (y-or-n-p
-                       (concat
-                        "Resume clock ("
-                        (with-current-buffer (find-file (car resume-clock))
-                          (save-excursion
-                            (goto-char (cdr resume-clock))
-                            (org-back-to-heading t)
-                            (and (looking-at org-complex-heading-regexp)
-                                 (match-string 4))))
-                        ") "))))
-         (when (file-exists-p (car resume-clock))
-           (with-current-buffer (find-file (car resume-clock))
-             (goto-char (cdr resume-clock))
-             (let ((org-clock-auto-clock-resolution nil))
-               (org-clock-in)
-               (if (outline-invisible-p)
-                   (org-show-context))))))))))
+    (if (not (file-readable-p org-clock-persist-file))
+       (message "Not restoring clock data; %S not found" 
org-clock-persist-file)
+      (message "Restoring clock data")
+      ;; Load history.
+      (load-file org-clock-persist-file)
+      (setq org-clock-loaded t)
+      (pcase-dolist (`(,(and file (pred file-exists-p)) . ,position)
+                    org-clock-stored-history)
+       (org-clock-history-push position (find-file-noselect file)))
+      ;; Resume clock.
+      (pcase org-clock-stored-resume-clock
+       (`(,(and file (pred file-exists-p)) . ,position)
+        (with-current-buffer (find-file-noselect file)
+          (when (or (not org-clock-persist-query-resume)
+                    (y-or-n-p (format "Resume clock (%s) "
+                                      (save-excursion
+                                        (goto-char position)
+                                        (org-get-heading t t)))))
+            (goto-char position)
+            (let ((org-clock-in-resume 'auto-restart)
+                  (org-clock-auto-clock-resolution nil))
+              (org-clock-in)
+              (when (org-invisible-p) (org-show-context))))))
+       (_ nil)))))
 
 ;; Suggested bindings
 (org-defkey org-mode-map "\C-c\C-x\C-e" 'org-clock-modify-effort-estimate)
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index a2046af..ac8f36a 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -1,4 +1,4 @@
-;;; org-colview.el --- Column View in Org-mode
+;;; org-colview.el --- Column View in Org            -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -28,42 +28,117 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'org)
 
 (declare-function org-agenda-redo "org-agenda" (&optional all))
 (declare-function org-agenda-do-context-action "org-agenda" ())
 (declare-function org-clock-sum-today "org-clock" (&optional headline-filter))
-
-(when (featurep 'xemacs)
-  (error "Do not load this file into XEmacs, use `org-colview-xemacs.el' from 
the contrib/ directory"))
-
+(declare-function org-element-extract-element "org-element" (element))
+(declare-function org-element-interpret-data "org-element" (data))
+(declare-function org-element-map "org-element" (data types fun &optional info 
first-match no-recursion with-affiliated))
+(declare-function org-element-parse-secondary-string "org-element" (string 
restriction &optional parent))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-restriction "org-element" (element))
+(declare-function org-element-type "org-element" (element))
+
+(defvar org-agenda-columns-add-appointments-to-effort-sum)
+(defvar org-agenda-columns-compute-summary-properties)
+(defvar org-agenda-columns-show-summaries)
+(defvar org-agenda-view-columns-initially)
+(defvar org-inlinetask-min-level)
+
+
+;;; Configuration
+
+(defcustom org-columns-modify-value-for-display-function nil
+  "Function that modifies values for display in column view.
+For example, it can be used to cut out a certain part from a time stamp.
+The function must take 2 arguments:
+
+column-title    The title of the column (*not* the property name)
+value           The value that should be modified.
+
+The function should return the value that should be displayed,
+or nil if the normal value should be used."
+  :group 'org-properties
+  :type '(choice (const nil) (function)))
+
+(defcustom org-columns-summary-types nil
+  "Alist between operators and summarize functions.
+
+Each association follows the pattern (LABEL . SUMMARIZE) where
+
+  LABEL is a string used in #+COLUMNS definition describing the
+  summary type.  It can contain any character but \"}\".  It is
+  case-sensitive.
+
+  SUMMARIZE is a function called with two arguments.  The first
+  argument is a non-empty list of values, as non-empty strings.
+  The second one is a format string or nil.  It has to return
+  a string summarizing the list of values.
+
+Note that the return value can become one value for an higher
+order summary, so the function is expected to handle its own
+output.
+
+Types defined in this variable take precedence over those defined
+in `org-columns-summary-types-default', which see."
+  :group 'org-properties
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type '(alist :key-type (string :tag "       Label")
+               :value-type (function :tag "Summarize")))
+
+
+
 ;;; Column View
 
 (defvar org-columns-overlays nil
   "Holds the list of current column overlays.")
 
-(defvar org-columns-current-fmt nil
+(defvar org-columns--time 0.0
+  "Number of seconds since the epoch, as a floating point number.")
+
+(defvar-local org-columns-current-fmt nil
   "Local variable, holds the currently active column format.")
-(make-variable-buffer-local 'org-columns-current-fmt)
-(defvar org-columns-current-fmt-compiled nil
+
+(defvar-local org-columns-current-fmt-compiled nil
   "Local variable, holds the currently active column format.
 This is the compiled version of the format.")
-(make-variable-buffer-local 'org-columns-current-fmt-compiled)
-(defvar org-columns-current-widths nil
-  "Loval variable, holds the currently widths of fields.")
-(make-variable-buffer-local 'org-columns-current-widths)
-(defvar org-columns-current-maxwidths nil
-  "Loval variable, holds the currently active maximum column widths.")
-(make-variable-buffer-local 'org-columns-current-maxwidths)
+
+(defvar-local org-columns-current-maxwidths nil
+  "Currently active maximum column widths, as a vector.")
+
 (defvar org-columns-begin-marker (make-marker)
   "Points to the position where last a column creation command was called.")
+
 (defvar org-columns-top-level-marker (make-marker)
   "Points to the position where current columns region starts.")
 
 (defvar org-columns-map (make-sparse-keymap)
   "The keymap valid in column display.")
 
+(defconst org-columns-summary-types-default
+  '(("+"     . org-columns--summary-sum)
+    ("$"     . org-columns--summary-currencies)
+    ("X"     . org-columns--summary-checkbox)
+    ("X/"    . org-columns--summary-checkbox-count)
+    ("X%"    . org-columns--summary-checkbox-percent)
+    ("max"   . org-columns--summary-max)
+    ("mean"  . org-columns--summary-mean)
+    ("min"   . org-columns--summary-min)
+    (":"     . org-columns--summary-sum-times)
+    (":max"  . org-columns--summary-max-time)
+    (":mean" . org-columns--summary-mean-time)
+    (":min"  . org-columns--summary-min-time)
+    ("@max"  . org-columns--summary-max-age)
+    ("@mean" . org-columns--summary-mean-age)
+    ("@min"  . org-columns--summary-min-age)
+    ("est+"  . org-columns--summary-estimate))
+  "Map operators to summarize functions.
+See `org-columns-summary-types' for details.")
+
 (defun org-columns-content ()
   "Switch to contents view while in columns view."
   (interactive)
@@ -146,121 +221,181 @@ This is the compiled version of the format.")
     "--"
     ["Quit" org-columns-quit t]))
 
-(defun org-columns-new-overlay (beg end &optional string face)
+(defun org-columns--displayed-value (spec value)
+  "Return displayed value for specification SPEC in current entry.
+SPEC is a column format specification as stored in
+`org-columns-current-fmt-compiled'.  VALUE is the real value to
+display, as a string."
+  (or (and (functionp org-columns-modify-value-for-display-function)
+          (funcall org-columns-modify-value-for-display-function
+                   (nth 1 spec)        ;column name
+                   value))
+      (pcase spec
+       (`("ITEM" . ,_)
+        (concat (make-string (1- (org-current-level))
+                             (if org-hide-leading-stars ?\s ?*))
+                "* "
+                (org-columns-compact-links value)))
+       (`(,_ ,_ ,_ ,_ nil) value)
+       ;; If PRINTF is set, assume we are displaying a number and
+       ;; obey to the format string.
+       (`(,_ ,_ ,_ ,_ ,printf) (format printf (string-to-number value)))
+       (_ (error "Invalid column specification format: %S" spec)))))
+
+(defun org-columns--collect-values (&optional compiled-fmt)
+  "Collect values for columns on the current line.
+
+Return a list of triplets (SPEC VALUE DISPLAYED) suitable for
+`org-columns--display-here'.
+
+This function assumes `org-columns-current-fmt-compiled' is
+initialized is set in the current buffer.  However, it is
+possible to override it with optional argument COMPILED-FMT."
+  (let ((summaries (get-text-property (point) 'org-summaries)))
+    (mapcar
+     (lambda (spec)
+       (pcase spec
+        (`(,p . ,_)
+         (let* ((v (or (cdr (assoc spec summaries))
+                       (org-entry-get (point) p 'selective t)
+                       (and compiled-fmt ;assume `org-agenda-columns'
+                            ;; Effort property is not defined.  Try
+                            ;; to use appointment duration.
+                            org-agenda-columns-add-appointments-to-effort-sum
+                            (string= p (upcase org-effort-property))
+                            (get-text-property (point) 'duration)
+                            (propertize (org-minutes-to-clocksum-string
+                                         (get-text-property (point) 'duration))
+                                        'face 'org-warning))
+                       "")))
+           (list spec v (org-columns--displayed-value spec v))))))
+     (or compiled-fmt org-columns-current-fmt-compiled))))
+
+(defun org-columns--set-widths (cache)
+  "Compute the maximum column widths from the format and CACHE.
+This function sets `org-columns-current-maxwidths' as a vector of
+integers greater than 0."
+  (setq org-columns-current-maxwidths
+       (apply #'vector
+              (mapcar
+               (lambda (spec)
+                 (pcase spec
+                   (`(,_ ,_ ,(and width (pred wholenump)) . ,_) width)
+                   (`(,_ ,name . ,_)
+                    ;; No width is specified in the columns format.
+                    ;; Compute it by checking all possible values for
+                    ;; PROPERTY.
+                    (let ((width (length name)))
+                      (dolist (entry cache width)
+                        (let ((value (nth 2 (assoc spec (cdr entry)))))
+                          (setq width (max (length value) width))))))))
+               org-columns-current-fmt-compiled))))
+
+(defun org-columns--new-overlay (beg end &optional string face)
   "Create a new column overlay and add it to the list."
   (let ((ov (make-overlay beg end)))
     (overlay-put ov 'face (or face 'secondary-selection))
-    (remove-text-properties 0 (length string) '(face nil) string)
     (org-overlay-display ov string face)
     (push ov org-columns-overlays)
     ov))
 
-(defun org-columns-display-here (&optional props dateline)
-  "Overlay the current line with column display."
-  (interactive)
-  (let* ((fmt org-columns-current-fmt-compiled)
-        (beg (point-at-bol))
-        (level-face (save-excursion
-                      (beginning-of-line 1)
-                      (and (looking-at "\\(\\**\\)\\(\\* \\)")
-                           (org-get-level-face 2))))
-        (ref-face (or level-face
-                      (and (eq major-mode 'org-agenda-mode)
-                           (get-text-property (point-at-bol) 'face))
-                      'default))
-        (color (list :foreground (face-attribute ref-face :foreground)))
-        (font (list :height (face-attribute 'default :height)
-                    :family (face-attribute 'default :family)))
-        (face (list color font 'org-column ref-face))
-        (face1 (list color font 'org-agenda-column-dateline ref-face))
-        (cphr (get-text-property (point-at-bol) 'org-complex-heading-regexp))
-        pom property ass width f fc string fm ov column val modval s2 title 
calc)
-    ;; Check if the entry is in another buffer.
-    (unless props
-      (if (eq major-mode 'org-agenda-mode)
-         (setq pom (or (org-get-at-bol 'org-hd-marker)
-                       (org-get-at-bol 'org-marker))
-               props (if pom (org-entry-properties pom) nil))
-       (setq props (org-entry-properties nil))))
-    ;; Walk the format
-    (while (setq column (pop fmt))
-      (setq property (car column)
-           title (nth 1 column)
-           ass (if (equal property "ITEM")
-                   (cons "ITEM"
-                         ;; When in a buffer, get the whole line,
-                         ;; we'll clean it later…
-                         (if (derived-mode-p 'org-mode)
-                             (save-match-data
-                               (org-remove-tabs
-                                (buffer-substring-no-properties
-                                 (point-at-bol) (point-at-eol))))
-                           ;; In agenda, just get the `txt' property
-                           (or (org-get-at-bol 'txt)
-                               (buffer-substring-no-properties
-                                (point) (progn (end-of-line) (point))))))
-                 (assoc property props))
-           width (or (cdr (assoc property org-columns-current-maxwidths))
-                     (nth 2 column)
-                     (length property))
-           f (format "%%-%d.%ds | " width width)
-           fm (nth 4 column)
-           fc (nth 5 column)
-           calc (nth 7 column)
-           val (or (cdr ass) "")
-           modval (cond ((and org-columns-modify-value-for-display-function
-                              (functionp
-                               org-columns-modify-value-for-display-function))
-                         (funcall org-columns-modify-value-for-display-function
-                                  title val))
-                        ((equal property "ITEM")
-                         (org-columns-cleanup-item
-                          val org-columns-current-fmt-compiled
-                          (or org-complex-heading-regexp cphr)))
-                        (fc (org-columns-number-to-string
-                             (org-columns-string-to-number val fm) fm fc))
-                        ((and calc (functionp calc)
-                              (not (string= val ""))
-                              (not (get-text-property 0 'org-computed val)))
-                         (org-columns-number-to-string
-                          (funcall calc (org-columns-string-to-number
-                                         val fm)) fm))))
-      (setq s2 (org-columns-add-ellipses (or modval val) width))
-      (setq string (format f s2))
-      ;; Create the overlay
+(defun org-columns--summarize (operator)
+  "Return summary function associated to string OPERATOR."
+  (if (not operator) nil
+    (cdr (or (assoc operator org-columns-summary-types)
+            (assoc operator org-columns-summary-types-default)
+            (error "Unknown %S operator" operator)))))
+
+(defun org-columns--overlay-text (value fmt width property original)
+  "Return text "
+  (format fmt
+          (let ((v (org-columns-add-ellipses value width)))
+            (pcase property
+              ("PRIORITY"
+               (propertize v 'face (org-get-priority-face original)))
+              ("TAGS"
+               (if (not org-tags-special-faces-re)
+                   (propertize v 'face 'org-tag)
+                 (replace-regexp-in-string
+                  org-tags-special-faces-re
+                  (lambda (m) (propertize m 'face (org-get-tag-face m)))
+                  v nil nil 1)))
+              ("TODO" (propertize v 'face (org-get-todo-face original)))
+              (_ v)))))
+
+(defun org-columns--display-here (columns &optional dateline)
+  "Overlay the current line with column display.
+COLUMNS is an alist (SPEC VALUE DISPLAYED).  Optional argument
+DATELINE is non-nil when the face used should be
+`org-agenda-column-dateline'."
+  (save-excursion
+    (beginning-of-line)
+    (let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)")
+                           (org-get-level-face 2)))
+          (ref-face (or level-face
+                        (and (eq major-mode 'org-agenda-mode)
+                             (org-get-at-bol 'face))
+                        'default))
+          (color (list :foreground (face-attribute ref-face :foreground)))
+          (font (list :height (face-attribute 'default :height)
+                      :family (face-attribute 'default :family)))
+          (face (list color font 'org-column ref-face))
+          (face1 (list color font 'org-agenda-column-dateline ref-face)))
+      ;; Each column is an overlay on top of a character.  So there has
+      ;; to be at least as many characters available on the line as
+      ;; columns to display.
+      (let ((columns (length org-columns-current-fmt-compiled))
+           (chars (- (line-end-position) (line-beginning-position))))
+       (when (> columns chars)
+         (save-excursion
+           (end-of-line)
+           (let ((inhibit-read-only t))
+             (insert (make-string (- columns chars) ?\s))))))
+      ;; Display columns.  Create and install the overlay for the
+      ;; current column on the next character.
+      (let ((i 0)
+           (last (1- (length columns))))
+       (dolist (column columns)
+         (pcase column
+           (`(,spec ,original ,value)
+            (let* ((property (car spec))
+                   (width (aref org-columns-current-maxwidths i))
+                   (fmt (format (if (= i last) "%%-%d.%ds |"
+                                  "%%-%d.%ds | ")
+                                width width))
+                   (ov (org-columns--new-overlay
+                        (point) (1+ (point))
+                        (org-columns--overlay-text
+                         value fmt width property original)
+                        (if dateline face1 face))))
+              (overlay-put ov 'keymap org-columns-map)
+              (overlay-put ov 'org-columns-key property)
+              (overlay-put ov 'org-columns-value original)
+              (overlay-put ov 'org-columns-value-modified value)
+              (overlay-put ov 'org-columns-format fmt)
+              (overlay-put ov 'line-prefix "")
+              (overlay-put ov 'wrap-prefix "")
+              (forward-char))))
+         (cl-incf i)))
+      ;; Make the rest of the line disappear.
+      (let ((ov (org-columns--new-overlay (point) (line-end-position))))
+       (overlay-put ov 'invisible t)
+       (overlay-put ov 'keymap org-columns-map)
+       (overlay-put ov 'line-prefix "")
+       (overlay-put ov 'wrap-prefix ""))
+      (let ((ov (make-overlay (1- (line-end-position))
+                             (line-beginning-position 2))))
+       (overlay-put ov 'keymap org-columns-map)
+       (push ov org-columns-overlays))
       (org-with-silent-modifications
-       (setq ov (org-columns-new-overlay
-                beg (setq beg (1+ beg)) string (if dateline face1 face)))
-       (overlay-put ov 'keymap org-columns-map)
-       (overlay-put ov 'org-columns-key property)
-       (overlay-put ov 'org-columns-value (cdr ass))
-       (overlay-put ov 'org-columns-value-modified modval)
-       (overlay-put ov 'org-columns-pom pom)
-       (overlay-put ov 'org-columns-format f)
-       (overlay-put ov 'line-prefix "")
-       (overlay-put ov 'wrap-prefix ""))
-      (if (or (not (char-after beg))
-             (equal (char-after beg) ?\n))
-         (let ((inhibit-read-only t))
-           (save-excursion
-             (goto-char beg)
-             (org-unmodified (insert " ")))))) ;; FIXME: add props and remove 
later?
-    ;; Make the rest of the line disappear.
-    (org-unmodified
-     (setq ov (org-columns-new-overlay beg (point-at-eol)))
-     (overlay-put ov 'invisible t)
-     (overlay-put ov 'keymap org-columns-map)
-     (overlay-put ov 'intangible t)
-     (overlay-put ov 'line-prefix "")
-     (overlay-put ov 'wrap-prefix "")
-     (push ov org-columns-overlays)
-     (setq ov (make-overlay (1- (point-at-eol)) (1+ (point-at-eol))))
-     (overlay-put ov 'keymap org-columns-map)
-     (push ov org-columns-overlays)
-     (let ((inhibit-read-only t))
-       (put-text-property (max (point-min) (1- (point-at-bol)))
-                         (min (point-max) (1+ (point-at-eol)))
-                         'read-only "Type `e' to edit property")))))
+       (let ((inhibit-read-only t))
+        (put-text-property
+         (line-end-position 0)
+         (line-beginning-position 2)
+         'read-only
+         (substitute-command-keys
+          "Type \\<org-columns-map>`\\[org-columns-edit-value]' \
+to edit property")))))))
 
 (defun org-columns-add-ellipses (string width)
   "Truncate STRING with WIDTH characters, with ellipses."
@@ -285,34 +420,27 @@ for the duration of the command.")
 (defvar header-line-format)
 (defvar org-columns-previous-hscroll 0)
 
-(defun org-columns-display-here-title ()
+(defun org-columns--display-here-title ()
   "Overlay the newline before the current line with the table title."
   (interactive)
-  (let ((fmt org-columns-current-fmt-compiled)
-       string (title "")
-       property width f column str widths)
-    (while (setq column (pop fmt))
-      (setq property (car column)
-           str (or (nth 1 column) property)
-           width (or (cdr (assoc property org-columns-current-maxwidths))
-                     (nth 2 column)
-                     (length str))
-           widths (push width widths)
-           f (format "%%-%d.%ds | " width width)
-           string (format f str)
-           title (concat title string)))
-    (setq title (concat
-                (org-add-props " " nil 'display '(space :align-to 0))
-                ;;(org-add-props title nil 'face '(:weight bold :underline t 
:inherit default))))
-                (org-add-props title nil 'face 'org-column-title)))
-    (org-set-local 'org-previous-header-line-format header-line-format)
-    (org-set-local 'org-columns-current-widths (nreverse widths))
-    (setq org-columns-full-header-line-format title)
+  (let ((title "")
+       (i 0))
+    (dolist (column org-columns-current-fmt-compiled)
+      (pcase column
+       (`(,property ,name . ,_)
+        (let* ((width (aref org-columns-current-maxwidths i))
+               (fmt (format "%%-%d.%ds | " width width)))
+          (setq title (concat title (format fmt (or name property)))))))
+      (cl-incf i))
+    (setq-local org-previous-header-line-format header-line-format)
+    (setq org-columns-full-header-line-format
+         (concat
+          (org-add-props " " nil 'display '(space :align-to 0))
+          (org-add-props (substring title 0 -1) nil 'face 'org-column-title)))
     (setq org-columns-previous-hscroll -1)
-                                       ;    (org-columns-hscoll-title)
-    (org-add-hook 'post-command-hook 'org-columns-hscoll-title nil 'local)))
+    (add-hook 'post-command-hook 'org-columns-hscroll-title nil 'local)))
 
-(defun org-columns-hscoll-title ()
+(defun org-columns-hscroll-title ()
   "Set the `header-line-format' so that it scrolls along with the table."
   (sit-for .0001) ; need to force a redisplay to update window-hscroll
   (when (not (= (window-hscroll) org-columns-previous-hscroll))
@@ -335,7 +463,7 @@ for the duration of the command.")
       (when (local-variable-p 'org-previous-header-line-format)
        (setq header-line-format org-previous-header-line-format)
        (kill-local-variable 'org-previous-header-line-format)
-       (remove-hook 'post-command-hook 'org-columns-hscoll-title 'local))
+       (remove-hook 'post-command-hook 'org-columns-hscroll-title 'local))
       (move-marker org-columns-begin-marker nil)
       (move-marker org-columns-top-level-marker nil)
       (org-with-silent-modifications
@@ -348,29 +476,6 @@ for the duration of the command.")
       (when (local-variable-p 'org-colview-initial-truncate-line-value)
        (setq truncate-lines org-colview-initial-truncate-line-value)))))
 
-(defun org-columns-cleanup-item (item fmt cphr)
-  "Remove from ITEM what is a column in the format FMT.
-CPHR is the complex heading regexp to use for parsing ITEM."
-  (let (fixitem)
-    (if (not cphr)
-       item
-      (unless (string-match "^\\*+ " item)
-       (setq item (concat "* " item) fixitem t))
-      (if (string-match cphr item)
-         (setq item
-               (concat
-                (org-add-props (match-string 1 item) nil
-                  'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) 
(match-beginning 1))))))
-                (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " 
(match-string 2 item)))
-                (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " 
(match-string 3 item)))
-                " " (save-match-data (org-columns-compact-links (or 
(match-string 4 item) "")))
-                (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " 
(match-string 5 item)))))
-       (add-text-properties
-        0 (1+ (match-end 1))
-        (list 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) 
(match-beginning 1))))))
-        item))
-      (if fixitem (replace-regexp-in-string "^\\*+ " "" item) item))))
-
 (defun org-columns-compact-links (s)
   "Replace [[link][desc]] with [desc] or [link]."
   (while (string-match org-bracket-link-regexp s)
@@ -394,25 +499,26 @@ CPHR is the complex heading regexp to use for parsing 
ITEM."
    (org-columns-remove-overlays)
    (let ((inhibit-read-only t))
      (remove-text-properties (point-min) (point-max) '(read-only t))))
-  (when (eq major-mode 'org-agenda-mode)
+  (if (not (eq major-mode 'org-agenda-mode))
+      (setq org-columns-current-fmt nil)
     (setq org-agenda-columns-active nil)
     (message
      "Modification not yet reflected in Agenda buffer, use `r' to refresh")))
 
 (defun org-columns-check-computed ()
-  "Check if this column value is computed.
-If yes, throw an error indicating that changing it does not make sense."
-  (let ((val (get-char-property (point) 'org-columns-value)))
-    (when (and (stringp val)
-              (get-char-property 0 'org-computed val))
-      (error "This value is computed from the entry's children"))))
-
-(defun org-columns-todo (&optional arg)
+  "Throw an error if current column value is computed."
+  (let ((spec (nth (current-column) org-columns-current-fmt-compiled)))
+    (and
+     (nth 3 spec)
+     (assoc spec (get-text-property (line-beginning-position) 'org-summaries))
+     (error "This value is computed from the entry's children"))))
+
+(defun org-columns-todo (&optional _arg)
   "Change the TODO state during column view."
   (interactive "P")
   (org-columns-edit-value "TODO"))
 
-(defun org-columns-set-tags-or-toggle (&optional arg)
+(defun org-columns-set-tags-or-toggle (&optional _arg)
   "Toggle checkbox at point, or set tags for current headline."
   (interactive "P")
   (if (string-match "\\`\\[[ xX-]\\]\\'"
@@ -430,107 +536,76 @@ Where possible, use the standard interface for changing 
this line."
   (interactive)
   (org-columns-check-computed)
   (let* ((col (current-column))
+        (bol (line-beginning-position))
+        (eol (line-end-position))
+        (pom (or (get-text-property bol 'org-hd-marker) (point)))
         (key (or key (get-char-property (point) 'org-columns-key)))
-        (value (get-char-property (point) 'org-columns-value))
-        (bol (point-at-bol)) (eol (point-at-eol))
-        (pom (or (get-text-property bol 'org-hd-marker)
-                 (point))) ; keep despite of compiler waring
-        (line-overlays
-         (delq nil (mapcar (lambda (x)
-                             (and (eq (overlay-buffer x) (current-buffer))
-                                  (>= (overlay-start x) bol)
-                                  (<= (overlay-start x) eol)
-                                  x))
-                           org-columns-overlays)))
-        (org-columns-time (time-to-number-of-days (current-time)))
-        nval eval allowed)
+        (org-columns--time (float-time (current-time)))
+        (action
+         (pcase key
+           ("CLOCKSUM"
+            (error "This special column cannot be edited"))
+           ("ITEM"
+            (lambda () (org-with-point-at pom (org-edit-headline))))
+           ("TODO"
+            (lambda ()
+              (org-with-point-at pom (call-interactively #'org-todo))))
+           ("PRIORITY"
+            (lambda ()
+              (org-with-point-at pom
+                (call-interactively #'org-priority))))
+           ("TAGS"
+            (lambda ()
+              (org-with-point-at pom
+                (let ((org-fast-tag-selection-single-key
+                       (if (eq org-fast-tag-selection-single-key 'expert)
+                           t
+                         org-fast-tag-selection-single-key)))
+                  (call-interactively #'org-set-tags)))))
+           ("DEADLINE"
+            (lambda ()
+              (org-with-point-at pom (call-interactively #'org-deadline))))
+           ("SCHEDULED"
+            (lambda ()
+              (org-with-point-at pom (call-interactively #'org-schedule))))
+           ("BEAMER_ENV"
+            (lambda ()
+              (org-with-point-at pom
+                (call-interactively #'org-beamer-select-environment))))
+           (_
+            (let* ((allowed (org-property-get-allowed-values pom key 'table))
+                   (value (get-char-property (point) 'org-columns-value))
+                   (nval (org-trim
+                          (if (null allowed) (read-string "Edit: " value)
+                            (completing-read
+                             "Value: " allowed nil
+                             (not (get-text-property
+                                   0 'org-unrestricted (caar allowed))))))))
+              (and (not (equal nval value))
+                   (lambda () (org-entry-put pom key nval))))))))
     (cond
-     ((equal key "CLOCKSUM")
-      (error "This special column cannot be edited"))
-     ((equal key "ITEM")
-      (setq eval '(org-with-point-at pom
-                   (org-edit-headline))))
-     ((equal key "TODO")
-      (setq eval '(org-with-point-at
-                     pom
-                   (call-interactively 'org-todo))))
-     ((equal key "PRIORITY")
-      (setq eval '(org-with-point-at pom
-                   (call-interactively 'org-priority))))
-     ((equal key "TAGS")
-      (setq eval '(org-with-point-at pom
-                   (let ((org-fast-tag-selection-single-key
-                          (if (eq org-fast-tag-selection-single-key 'expert)
-                              t org-fast-tag-selection-single-key)))
-                     (call-interactively 'org-set-tags)))))
-     ((equal key "DEADLINE")
-      (setq eval '(org-with-point-at pom
-                   (call-interactively 'org-deadline))))
-     ((equal key "SCHEDULED")
-      (setq eval '(org-with-point-at pom
-                   (call-interactively 'org-schedule))))
-     ((equal key "BEAMER_env")
-      (setq eval '(org-with-point-at pom
-                   (call-interactively 'org-beamer-select-environment))))
+     ((null action))
+     ((eq major-mode 'org-agenda-mode)
+      (org-columns--call action)
+      ;; The following let preserves the current format, and makes
+      ;; sure that in only a single file things need to be updated.
+      (let* ((org-agenda-overriding-columns-format org-columns-current-fmt)
+            (buffer (marker-buffer pom))
+            (org-agenda-contributing-files
+             (list (with-current-buffer buffer
+                     (buffer-file-name (buffer-base-buffer))))))
+       (org-agenda-columns)))
      (t
-      (setq allowed (org-property-get-allowed-values pom key 'table))
-      (if allowed
-         (setq nval (org-icompleting-read
-                     "Value: " allowed nil
-                     (not (get-text-property 0 'org-unrestricted
-                                             (caar allowed)))))
-       (setq nval (read-string "Edit: " value)))
-      (setq nval (org-trim nval))
-      (when (not (equal nval value))
-       (setq eval '(org-entry-put pom key nval)))))
-    (when eval
-
-      (cond
-       ((equal major-mode 'org-agenda-mode)
-       (org-columns-eval eval)
-       ;; The following let preserves the current format, and makes sure
-       ;; that in only a single file things need to be updated.
-       (let* ((org-agenda-overriding-columns-format org-columns-current-fmt)
-              (buffer (marker-buffer pom))
-              (org-agenda-contributing-files
-               (list (with-current-buffer buffer
-                       (buffer-file-name (buffer-base-buffer))))))
-         (org-agenda-columns)))
-       (t
-       (let ((inhibit-read-only t))
-         (org-with-silent-modifications
-          (remove-text-properties
-           (max (point-min) (1- bol)) eol '(read-only t)))
-         (unwind-protect
-             (progn
-               (setq org-columns-overlays
-                     (org-delete-all line-overlays org-columns-overlays))
-               (mapc 'delete-overlay line-overlays)
-               (org-columns-eval eval))
-           (org-columns-display-here)))
-       (org-move-to-column col)
-       (if (and (derived-mode-p 'org-mode)
-                (nth 3 (assoc key org-columns-current-fmt-compiled)))
-           (org-columns-update key)))))))
-
-(defun org-edit-headline () ; FIXME: this is not columns specific.  Make 
interactive?????  Use from agenda????
-  "Edit the current headline, the part without TODO keyword, TAGS."
-  (org-back-to-heading)
-  (when (looking-at org-todo-line-regexp)
-    (let ((pos (point))
-         (pre (buffer-substring (match-beginning 0) (match-beginning 3)))
-         (txt (match-string 3))
-         (post "")
-         txt2)
-      (if (string-match (org-re "[ \t]+:[[:alnum:]:address@hidden:[ \t]*$") 
txt)
-         (setq post (match-string 0 txt)
-               txt (substring txt 0 (match-beginning 0))))
-      (setq txt2 (read-string "Edit: " txt))
-      (when (not (equal txt txt2))
-       (goto-char pos)
-       (insert pre txt2 post)
-       (delete-region (point) (point-at-eol))
-       (org-set-tags nil t)))))
+      (let ((inhibit-read-only t))
+       (org-with-silent-modifications
+        (remove-text-properties (max (point-min) (1- bol)) eol '(read-only t)))
+       (org-columns--call action))
+      ;; Some properties can modify headline (e.g., "TODO"), and
+      ;; possible shuffle overlays.  Make sure they are still all at
+      ;; the right place on the current line.
+      (let ((org-columns-inhibit-recalculation)) (org-columns-redo))
+      (org-columns-update key)
+      (org-move-to-column col)))))
 
 (defun org-columns-edit-allowed ()
   "Edit the list of allowed values for the current property."
@@ -553,15 +628,15 @@ Where possible, use the standard interface for changing 
this line."
           (t pom))
      key1 nval)))
 
-(defun org-columns-eval (form)
-  (let (hidep)
-    (save-excursion
-      (beginning-of-line 1)
-      ;; `next-line' is needed here, because it skips invisible line.
-      (condition-case nil (org-no-warnings (next-line 1)) (error nil))
-      (setq hidep (org-at-heading-p 1)))
-    (eval form)
-    (and hidep (hide-entry))))
+(defun org-columns--call (fun)
+  "Call function FUN while preserving heading visibility.
+FUN is a function called with no argument."
+  (let ((hide-body (and (/= (line-end-position) (point-max))
+                       (save-excursion
+                         (move-beginning-of-line 2)
+                         (org-at-heading-p t)))))
+    (unwind-protect (funcall fun)
+      (when hide-body (outline-hide-entry)))))
 
 (defun org-columns-previous-allowed-value ()
   "Switch to the previous allowed value for this column."
@@ -574,72 +649,57 @@ When PREVIOUS is set, go to the previous value.  When NTH 
is
 an integer, select that value."
   (interactive)
   (org-columns-check-computed)
-  (let* ((col (current-column))
+  (let* ((column (current-column))
         (key (get-char-property (point) 'org-columns-key))
         (value (get-char-property (point) 'org-columns-value))
-        (bol (point-at-bol)) (eol (point-at-eol))
-        (pom (or (get-text-property bol 'org-hd-marker)
-                 (point))) ; keep despite of compiler waring
-        (line-overlays
-         (delq nil (mapcar (lambda (x)
-                             (and (eq (overlay-buffer x) (current-buffer))
-                                  (>= (overlay-start x) bol)
-                                  (<= (overlay-start x) eol)
-                                  x))
-                           org-columns-overlays)))
-        (allowed (or (org-property-get-allowed-values pom key)
-                     (and (memq
-                           (nth 4 (assoc key org-columns-current-fmt-compiled))
-                           '(checkbox checkbox-n-of-m checkbox-percent))
-                          '("[ ]" "[X]"))
-                     (org-colview-construct-allowed-dates value)))
-        nval)
-    (when (integerp nth)
-      (setq nth (1- nth))
-      (if (= nth -1) (setq nth 9)))
-    (when (equal key "ITEM")
-      (error "Cannot edit item headline from here"))
+        (pom (or (get-text-property (line-beginning-position) 'org-hd-marker)
+                 (point)))
+        (allowed
+         (let ((all
+                (or (org-property-get-allowed-values pom key)
+                    (pcase (nth column org-columns-current-fmt-compiled)
+                      (`(,_ ,_ ,_ ,(or "X" "X/" "X%") ,_) '("[ ]" "[X]")))
+                    (org-colview-construct-allowed-dates value))))
+           (if previous (reverse all) all))))
+    (when (equal key "ITEM") (error "Cannot edit item headline from here"))
     (unless (or allowed (member key '("SCHEDULED" "DEADLINE" "CLOCKSUM")))
       (error "Allowed values for this property have not been defined"))
-    (if (member key '("SCHEDULED" "DEADLINE" "CLOCKSUM"))
-       (setq nval (if previous 'earlier 'later))
-      (if previous (setq allowed (reverse allowed)))
+    (let* ((l (length allowed))
+          (new
+           (cond
+            ((member key '("SCHEDULED" "DEADLINE" "CLOCKSUM"))
+             (if previous 'earlier 'later))
+            ((integerp nth)
+             (when (> (abs nth) l)
+               (user-error "Only %d allowed values for property `%s'" l key))
+             (nth (mod (1- nth) l) allowed))
+            ((member value allowed)
+             (when (= l 1) (error "Only one allowed value for this property"))
+             (or (nth 1 (member value allowed)) (car allowed)))
+            (t (car allowed))))
+          (action (lambda () (org-entry-put pom key new))))
       (cond
-       (nth
-       (setq nval (nth nth allowed))
-       (if (not nval)
-           (error "There are only %d allowed values for property `%s'"
-                  (length allowed) key)))
-       ((member value allowed)
-       (setq nval (or (car (cdr (member value allowed)))
-                      (car allowed)))
-       (if (equal nval value)
-           (error "Only one allowed value for this property")))
-       (t (setq nval (car allowed)))))
-    (cond
-     ((equal major-mode 'org-agenda-mode)
-      (org-columns-eval '(org-entry-put pom key nval))
-      ;; The following let preserves the current format, and makes sure
-      ;; that in only a single file things need to be updated.
-      (let* ((org-agenda-overriding-columns-format org-columns-current-fmt)
-            (buffer (marker-buffer pom))
-            (org-agenda-contributing-files
-             (list (with-current-buffer buffer
-                     (buffer-file-name (buffer-base-buffer))))))
-       (org-agenda-columns)))
-     (t
-      (let ((inhibit-read-only t))
-       (remove-text-properties (1- bol) eol '(read-only t))
-       (unwind-protect
-           (progn
-             (setq org-columns-overlays
-                   (org-delete-all line-overlays org-columns-overlays))
-             (mapc 'delete-overlay line-overlays)
-             (org-columns-eval '(org-entry-put pom key nval)))
-         (org-columns-display-here)))
-      (org-move-to-column col)
-      (and (nth 3 (assoc key org-columns-current-fmt-compiled))
-          (org-columns-update key))))))
+       ((eq major-mode 'org-agenda-mode)
+       (org-columns--call action)
+       ;; The following let preserves the current format, and makes
+       ;; sure that in only a single file things need to be updated.
+       (let* ((org-agenda-overriding-columns-format org-columns-current-fmt)
+              (buffer (marker-buffer pom))
+              (org-agenda-contributing-files
+               (list (with-current-buffer buffer
+                       (buffer-file-name (buffer-base-buffer))))))
+         (org-agenda-columns)))
+       (t
+       (let ((inhibit-read-only t))
+         (remove-text-properties (line-end-position 0) (line-end-position)
+                                 '(read-only t))
+         (org-columns--call action))
+       ;; Some properties can modify headline (e.g., "TODO"), and
+       ;; possible shuffle overlays.  Make sure they are still all at
+       ;; the right place on the current line.
+       (let ((org-columns-inhibit-recalculation)) (org-columns-redo))
+       (org-columns-update key)
+       (org-move-to-column column))))))
 
 (defun org-colview-construct-allowed-dates (s)
   "Construct a list of three dates around the date in S.
@@ -662,13 +722,6 @@ around it."
       (mapcar (lambda (x) (format-time-string fmt (apply 'encode-time x)))
              (list time-before time time-after)))))
 
-(defun org-verify-version (task)
-  (cond
-   ((eq task 'columns)
-    (if (or (featurep 'xemacs)
-           (< emacs-major-version 22))
-       (error "Emacs 22 is required for the columns feature")))))
-
 (defun org-columns-open-link (&optional arg)
   (interactive "P")
   (let ((value (get-char-property (point) 'org-columns-value)))
@@ -681,179 +734,165 @@ around it."
     fmt))
 
 (defun org-columns-get-format (&optional fmt-string)
+  "Return columns format specifications.
+When optional argument FMT-STRING is non-nil, use it as the
+current specifications.  This function also sets
+`org-columns-current-fmt-compiled' and
+`org-columns-current-fmt'."
   (interactive)
-  (let (fmt-as-property fmt)
-    (when (condition-case nil (org-back-to-heading) (error nil))
-      (setq fmt-as-property (org-entry-get nil "COLUMNS" t)))
-    (setq fmt (or fmt-string fmt-as-property org-columns-default-format))
-    (org-set-local 'org-columns-current-fmt fmt)
-    (org-columns-compile-format fmt)
-    fmt))
+  (let ((format
+        (or fmt-string
+            (org-entry-get nil "COLUMNS" t)
+            (org-with-wide-buffer
+             (goto-char (point-min))
+             (catch :found
+               (let ((case-fold-search t))
+                 (while (re-search-forward "^[ \t]*#\\+COLUMNS: .+$" nil t)
+                   (let ((element (org-element-at-point)))
+                     (when (eq (org-element-type element) 'keyword)
+                       (throw :found (org-element-property :value element)))))
+                 nil)))
+            org-columns-default-format)))
+    (setq org-columns-current-fmt format)
+    (org-columns-compile-format format)
+    format))
 
 (defun org-columns-goto-top-level ()
-  (when (condition-case nil (org-back-to-heading) (error nil))
-    (org-entry-get nil "COLUMNS" t))
-  (if (marker-position org-entry-property-inherited-from)
-      (move-marker org-columns-top-level-marker 
org-entry-property-inherited-from)
-    (move-marker org-columns-top-level-marker (point))))
+  "Move to the beginning of the column view area.
+Also sets `org-columns-top-level-marker' to the new position."
+  (goto-char
+   (move-marker
+    org-columns-top-level-marker
+    (cond ((org-before-first-heading-p) (point-min))
+         ((org-entry-get nil "COLUMNS" t) org-entry-property-inherited-from)
+         (t (org-back-to-heading) (point))))))
 
 ;;;###autoload
-(defun org-columns (&optional columns-fmt-string)
-  "Turn on column view on an org-mode file.
+(defun org-columns (&optional global columns-fmt-string)
+  "Turn on column view on an Org mode file.
+
+Column view applies to the whole buffer if point is before the
+first headline.  Otherwise, it applies to the first ancestor
+setting \"COLUMNS\" property.  If there is none, it defaults to
+the current headline.  With a `\\[universal-argument]' prefix \
+argument, turn on column
+view for the whole buffer unconditionally.
+
 When COLUMNS-FMT-STRING is non-nil, use it as the column format."
-  (interactive)
-  (org-verify-version 'columns)
+  (interactive "P")
   (org-columns-remove-overlays)
+  (when global (goto-char (point-min)))
   (move-marker org-columns-begin-marker (point))
-  (let ((org-columns-time (time-to-number-of-days (current-time)))
-       beg end fmt cache maxwidths)
-    (org-columns-goto-top-level)
-    (setq fmt (org-columns-get-format columns-fmt-string))
+  (org-columns-goto-top-level)
+  ;; Initialize `org-columns-current-fmt' and
+  ;; `org-columns-current-fmt-compiled'.
+  (let ((org-columns--time (float-time (current-time))))
+    (org-columns-get-format columns-fmt-string)
+    (unless org-columns-inhibit-recalculation (org-columns-compute-all))
     (save-excursion
-      (goto-char org-columns-top-level-marker)
-      (setq beg (point))
-      (unless org-columns-inhibit-recalculation
-       (org-columns-compute-all))
-      (setq end (or (condition-case nil (org-end-of-subtree t t) (error nil))
-                   (point-max)))
-      ;; Get and cache the properties
-      (goto-char beg)
-      (when (assoc "CLOCKSUM" org-columns-current-fmt-compiled)
-       (save-excursion
-         (save-restriction
-           (narrow-to-region beg end)
-           (org-clock-sum))))
-      (when (assoc "CLOCKSUM_T" org-columns-current-fmt-compiled)
-       (save-excursion
-         (save-restriction
-           (narrow-to-region beg end)
-           (org-clock-sum-today))))
-      (while (re-search-forward org-outline-regexp-bol end t)
-       (if (and org-columns-skip-archived-trees
-                (looking-at (concat ".*:" org-archive-tag ":")))
-           (org-end-of-subtree t)
-         (push (cons (org-current-line) (org-entry-properties)) cache)))
-      (when cache
-       (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
-       (org-set-local 'org-columns-current-maxwidths maxwidths)
-       (org-columns-display-here-title)
-       (when (org-set-local 'org-columns-flyspell-was-active
-                            (org-bound-and-true-p flyspell-mode))
-         (flyspell-mode 0))
-       (unless (local-variable-p 'org-colview-initial-truncate-line-value)
-         (org-set-local 'org-colview-initial-truncate-line-value
-                        truncate-lines))
-       (setq truncate-lines t)
-       (mapc (lambda (x)
-               (org-goto-line (car x))
-               (org-columns-display-here (cdr x)))
-             cache)))))
-
-(eval-when-compile (defvar org-columns-time))
-
-(defvar org-columns-compile-map
-  '(("none" none +)
-    (":" add_times +)
-    ("+" add_numbers +)
-    ("$" currency +)
-    ("X" checkbox +)
-    ("X/" checkbox-n-of-m +)
-    ("X%" checkbox-percent +)
-    ("max" max_numbers max)
-    ("min" min_numbers min)
-    ("mean" mean_numbers
-     (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
-    (":max" max_times max)
-    (":min" min_times min)
-    (":mean" mean_times
-     (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
-    ("@min" min_age min (lambda (x) (- org-columns-time x)))
-    ("@max" max_age max (lambda (x) (- org-columns-time x)))
-    ("@mean" mean_age
-     (lambda (&rest x) (/ (apply '+ x) (float (length x))))
-     (lambda (x) (- org-columns-time x)))
-    ("est+" estimate org-estimate-combine))
-  "Operator <-> format,function,calc  map.
-Used to compile/uncompile columns format and completing read in
-interactive function `org-columns-new'.
-
-operator    string used in #+COLUMNS definition describing the
-           summary type
-format      symbol describing summary type selected interactively in
-           `org-columns-new' and internally in
-           `org-columns-number-to-string' and
-           `org-columns-string-to-number'
-function    called with a list of values as argument to calculate
-           the summary value
-calc        function called on every element before summarizing.  This is
-           optional and should only be specified if needed")
-
-(defun org-columns-new (&optional prop title width op fmt fun &rest rest)
-  "Insert a new column, to the left of the current column."
+      (save-restriction
+       (when (and (not global) (org-at-heading-p))
+         (narrow-to-region (point) (org-end-of-subtree t t)))
+       (when (assoc "CLOCKSUM" org-columns-current-fmt-compiled)
+         (org-clock-sum))
+       (when (assoc "CLOCKSUM_T" org-columns-current-fmt-compiled)
+         (org-clock-sum-today))
+       (let ((cache
+              ;; Collect contents of columns ahead of time so as to
+              ;; compute their maximum width.
+              (org-map-entries
+               (lambda () (cons (point) (org-columns--collect-values)))
+               nil nil (and org-columns-skip-archived-trees 'archive))))
+         (when cache
+           (org-columns--set-widths cache)
+           (org-columns--display-here-title)
+           (when (setq-local org-columns-flyspell-was-active
+                             (bound-and-true-p flyspell-mode))
+             (flyspell-mode 0))
+           (unless (local-variable-p 'org-colview-initial-truncate-line-value)
+             (setq-local org-colview-initial-truncate-line-value
+                         truncate-lines))
+           (setq truncate-lines t)
+           (dolist (entry cache)
+             (goto-char (car entry))
+             (org-columns--display-here (cdr entry)))))))))
+
+(defun org-columns-new (&optional spec &rest attributes)
+  "Insert a new column, to the left of the current column.
+Interactively fill attributes for new column.  When column format
+specification SPEC is provided, edit it instead.
+
+When optional argument attributes can be a list of columns
+specifications attributes to create the new column
+non-interactively.  See `org-columns-compile-format' for
+details."
   (interactive)
-  (let ((editp (and prop (assoc prop org-columns-current-fmt-compiled)))
-       cell)
-    (setq prop (org-icompleting-read
-               "Property: " (mapcar 'list (org-buffer-property-keys t nil t))
-               nil nil prop))
-    (setq title (read-string (concat "Column title [" prop "]: ") (or title 
prop)))
-    (setq width (read-string "Column width: " (if width (number-to-string 
width))))
-    (if (string-match "\\S-" width)
-       (setq width (string-to-number width))
-      (setq width nil))
-    (setq fmt (org-icompleting-read
-              "Summary [none]: "
-              (mapcar (lambda (x) (list (symbol-name (cadr x))))
-                      org-columns-compile-map)
-              nil t))
-    (setq fmt (intern fmt)
-         fun (cdr (assoc fmt (mapcar 'cdr org-columns-compile-map))))
-    (if (eq fmt 'none) (setq fmt nil))
-    (if editp
-       (progn
-         (setcar editp prop)
-         (setcdr editp (list title width nil fmt nil fun)))
-      (setq cell (nthcdr (1- (current-column))
-                        org-columns-current-fmt-compiled))
-      (setcdr cell (cons (list prop title width nil fmt nil
-                              (car fun) (cadr fun))
-                        (cdr cell))))
+  (let ((new (or attributes
+                (let ((prop
+                       (completing-read
+                        "Property: "
+                        (mapcar #'list (org-buffer-property-keys t nil t))
+                        nil nil (nth 0 spec))))
+                  (list prop
+                        (read-string (format "Column title [%s]: " prop)
+                                     (nth 1 spec))
+                        ;; Use `read-string' instead of `read-number'
+                        ;; to allow empty width.
+                        (let ((w (read-string
+                                  "Column width: "
+                                  (and (nth 2 spec)
+                                       (number-to-string (nth 2 spec))))))
+                          (and (org-string-nw-p w) (string-to-number w)))
+                        (org-string-nw-p
+                         (completing-read
+                          "Summary: "
+                          (delete-dups
+                           (cons '("") ;Allow empty operator.
+                                 (mapcar (lambda (x) (list (car x)))
+                                         (append
+                                          org-columns-summary-types
+                                          org-columns-summary-types-default))))
+                          nil t (nth 3 spec)))
+                        (org-string-nw-p
+                         (read-string "Format: " (nth 4 spec))))))))
+    (if spec
+       (progn (setcar spec (car new))
+              (setcdr spec (cdr new)))
+      (push new (nthcdr (current-column) org-columns-current-fmt-compiled)))
     (org-columns-store-format)
     (org-columns-redo)))
 
 (defun org-columns-delete ()
   "Delete the column at point from columns view."
   (interactive)
-  (let* ((n (current-column))
-        (title (nth 1 (nth n org-columns-current-fmt-compiled))))
-    (when (y-or-n-p
-          (format "Are you sure you want to remove column \"%s\"? " title))
+  (let ((spec (nth (current-column) org-columns-current-fmt-compiled)))
+    (when (y-or-n-p (format "Are you sure you want to remove column %S? "
+                           (nth 1 spec)))
       (setq org-columns-current-fmt-compiled
-           (delq (nth n org-columns-current-fmt-compiled)
-                 org-columns-current-fmt-compiled))
+           (delq spec org-columns-current-fmt-compiled))
       (org-columns-store-format)
-      (org-columns-redo)
-      (if (>= (current-column) (length org-columns-current-fmt-compiled))
-         (backward-char 1)))))
+      ;; This may leave a now wrong value in a node property.  However
+      ;; updating it may prove counter-intuitive.  See comments in
+      ;; `org-columns-move-right' for details.
+      (let ((org-columns-inhibit-recalculation t)) (org-columns-redo))
+      (when (>= (current-column) (length org-columns-current-fmt-compiled))
+       (backward-char)))))
 
 (defun org-columns-edit-attributes ()
   "Edit the attributes of the current column."
   (interactive)
-  (let* ((n (current-column))
-        (info (nth n org-columns-current-fmt-compiled)))
-    (apply 'org-columns-new info)))
+  (org-columns-new (nth (current-column) org-columns-current-fmt-compiled)))
 
 (defun org-columns-widen (arg)
   "Make the column wider by ARG characters."
   (interactive "p")
   (let* ((n (current-column))
         (entry (nth n org-columns-current-fmt-compiled))
-        (width (or (nth 2 entry)
-                   (cdr (assoc (car entry) org-columns-current-maxwidths)))))
+        (width (aref org-columns-current-maxwidths n)))
     (setq width (max 1 (+ width arg)))
     (setcar (nthcdr 2 entry) width)
     (org-columns-store-format)
-    (org-columns-redo)))
+    (let ((org-columns-inhibit-recalculation t)) (org-columns-redo))))
 
 (defun org-columns-narrow (arg)
   "Make the column narrower by ARG characters."
@@ -872,7 +911,16 @@ calc        function called on every element before 
summarizing.  This is
     (setcar cell (car (cdr cell)))
     (setcdr cell (cons e (cdr (cdr cell))))
     (org-columns-store-format)
-    (org-columns-redo)
+    ;; Do not compute again properties, since we're just moving
+    ;; columns around.  It can put a property value a bit off when
+    ;; switching between an non-computed and a computed value for the
+    ;; same property, e.g. from "%A %A{+}" to "%A{+} %A".
+    ;;
+    ;; In this case, the value needs to be updated since the first
+    ;; column related to a property determines how its value is
+    ;; computed.  However, (correctly) updating the value could be
+    ;; surprising, so we leave it as-is nonetheless.
+    (let ((org-columns-inhibit-recalculation t)) (org-columns-redo))
     (forward-char 1)))
 
 (defun org-columns-move-left ()
@@ -886,358 +934,455 @@ calc        function called on every element before 
summarizing.  This is
     (backward-char 1)))
 
 (defun org-columns-store-format ()
-  "Store the text version of the current columns format in appropriate place.
-This is either in the COLUMNS property of the node starting the current column
-display, or in the #+COLUMNS line of the current buffer."
-  (let (fmt (cnt 0))
-    (setq fmt (org-columns-uncompile-format org-columns-current-fmt-compiled))
-    (org-set-local 'org-columns-current-fmt fmt)
-    (if (marker-position org-columns-top-level-marker)
-       (save-excursion
-         (goto-char org-columns-top-level-marker)
-         (if (and (org-at-heading-p)
-                  (org-entry-get nil "COLUMNS"))
-             (org-entry-put nil "COLUMNS" fmt)
-           (goto-char (point-min))
-           ;; Overwrite all #+COLUMNS lines....
-           (while (re-search-forward "^#\\+COLUMNS:.*" nil t)
-             (setq cnt (1+ cnt))
-             (replace-match (concat "#+COLUMNS: " fmt) t t))
-           (unless (> cnt 0)
-             (goto-char (point-min))
-             (or (org-at-heading-p t) (outline-next-heading))
-             (let ((inhibit-read-only t))
-               (insert-before-markers "#+COLUMNS: " fmt "\n")))
-           (org-set-local 'org-columns-default-format fmt))))))
-
-(defun org-columns-get-autowidth-alist (s cache)
-  "Derive the maximum column widths from the format and the cache."
-  (let ((start 0) rtn)
-    (while (string-match (org-re "%\\([[:alpha:]][[:alnum:]_-]*\\)") s start)
-      (push (cons (match-string 1 s) 1) rtn)
-      (setq start (match-end 0)))
-    (mapc (lambda (x)
-           (setcdr x (apply 'max
-                            (mapcar
-                             (lambda (y)
-                               (length (or (cdr (assoc (car x) (cdr y))) " ")))
-                             cache))))
-         rtn)
-    rtn))
-
-(defun org-columns-compute-all ()
-  "Compute all columns that have operators defined."
-  (org-with-silent-modifications
-   (remove-text-properties (point-min) (point-max) '(org-summaries t)))
-  (let ((columns org-columns-current-fmt-compiled)
-       (org-columns-time (time-to-number-of-days (current-time)))
-       col)
-    (while (setq col (pop columns))
-      (when (nth 3 col)
-       (save-excursion
-         (org-columns-compute (car col)))))))
+  "Store the text version of the current columns format.
+The format is stored either in the COLUMNS property of the node
+starting the current column display, or in a #+COLUMNS line of
+the current buffer."
+  (let ((fmt (org-columns-uncompile-format org-columns-current-fmt-compiled)))
+    (setq-local org-columns-current-fmt fmt)
+    (when (marker-position org-columns-top-level-marker)
+      (org-with-wide-buffer
+       (goto-char org-columns-top-level-marker)
+       (if (and (org-at-heading-p) (org-entry-get nil "COLUMNS"))
+          (org-entry-put nil "COLUMNS" fmt)
+        (goto-char (point-min))
+        (let ((case-fold-search t))
+          ;; Try to replace the first COLUMNS keyword available.
+          (catch :found
+            (while (re-search-forward "^[ \t]*#\\+COLUMNS:\\(.*\\)" nil t)
+              (let ((element (save-match-data (org-element-at-point))))
+                (when (and (eq (org-element-type element) 'keyword)
+                           (equal (org-element-property :key element)
+                                  "COLUMNS"))
+                  (replace-match (concat " " fmt) t t nil 1)
+                  (throw :found nil))))
+            ;; No COLUMNS keyword in the buffer.  Insert one at the
+            ;; beginning, right before the first heading, if any.
+            (goto-char (point-min))
+            (unless (org-at-heading-p t) (outline-next-heading))
+            (let ((inhibit-read-only t))
+              (insert-before-markers "#+COLUMNS: " fmt "\n"))))
+        (setq-local org-columns-default-format fmt))))))
 
 (defun org-columns-update (property)
   "Recompute PROPERTY, and update the columns display for it."
   (org-columns-compute property)
-  (let (fmt val pos)
-    (save-excursion
-      (mapc (lambda (ov)
-             (when (equal (overlay-get ov 'org-columns-key) property)
-               (setq pos (overlay-start ov))
-               (goto-char pos)
-               (when (setq val (cdr (assoc property
-                                           (get-text-property
-                                            (point-at-bol) 'org-summaries))))
-                 (setq fmt (overlay-get ov 'org-columns-format))
-                 (overlay-put ov 'org-columns-value val)
-                 (overlay-put ov 'display (format fmt val)))))
-           org-columns-overlays))))
-
-(defvar org-inlinetask-min-level
-  (if (featurep 'org-inlinetask) org-inlinetask-min-level 15))
-
-;;;###autoload
-(defun org-columns-compute (property)
-  "Sum the values of property PROPERTY hierarchically, for the entire buffer."
-  (interactive)
-  (let* ((re org-outline-regexp-bol)
-        (lmax 30) ; Does anyone use deeper levels???
-        (lvals (make-vector lmax nil))
-        (lflag (make-vector lmax nil))
-        (level 0)
-        (ass (assoc property org-columns-current-fmt-compiled))
-        (format (nth 4 ass))
-        (printf (nth 5 ass))
-        (fun (nth 6 ass))
-        (calc (or (nth 7 ass) 'identity))
-        (beg org-columns-top-level-marker)
-        (inminlevel org-inlinetask-min-level)
-        (last-level org-inlinetask-min-level)
-        val valflag flag end sumpos sum-alist sum str str1 useval)
-    (save-excursion
-      ;; Find the region to compute
-      (goto-char beg)
-      (setq end (condition-case nil (org-end-of-subtree t) (error 
(point-max))))
-      (goto-char end)
-      ;; Walk the tree from the back and do the computations
-      (while (re-search-backward re beg t)
-       (setq sumpos (match-beginning 0)
-             last-level (if (not (or (zerop level) (eq level inminlevel)))
-                            level last-level)
-             level (org-outline-level)
-             val (org-entry-get nil property)
-             valflag (and val (string-match "\\S-" val)))
-       (cond
-        ((< level last-level)
-         ;; put the sum of lower levels here as a property
-         (setq sum (+ (if (and (/= last-level inminlevel)
-                               (aref lvals last-level))
-                          (apply fun (aref lvals last-level)) 0)
-                      (if (aref lvals inminlevel)
-                          (apply fun (aref lvals inminlevel)) 0))
-               flag (or (aref lflag last-level) ; any valid entries from 
children?
-                        (aref lflag inminlevel)) ; or inline tasks?
-               str (org-columns-number-to-string sum format printf)
-               str1 (org-add-props (copy-sequence str) nil 'org-computed t 
'face 'bold)
-               useval (if flag str1 (if valflag val ""))
-               sum-alist (get-text-property sumpos 'org-summaries))
-         (if (assoc property sum-alist)
-             (setcdr (assoc property sum-alist) useval)
-           (push (cons property useval) sum-alist)
-           (org-with-silent-modifications
-            (add-text-properties sumpos (1+ sumpos)
-                                 (list 'org-summaries sum-alist))))
-         (when (and val (not (equal val (if flag str val))))
-           (org-entry-put nil property (if flag str val)))
-         ;; add current to current level accumulator
-         (when (or flag valflag)
-           (push (if flag
-                     sum
-                   (funcall calc (org-columns-string-to-number
-                                  (if flag str val) format)))
-                 (aref lvals level))
-           (aset lflag level t))
-         ;; clear accumulators for deeper levels
-         (loop for l from (1+ level) to (1- lmax) do
-               (aset lvals l nil)
-               (aset lflag l nil)))
-        ((>= level last-level)
-         ;; add what we have here to the accumulator for this level
-         (when valflag
-           (push (funcall calc (org-columns-string-to-number val format))
-                 (aref lvals level))
-           (aset lflag level t)))
-        (t (error "This should not happen")))))))
+  (org-with-wide-buffer
+   (let ((p (upcase property)))
+     (dolist (ov org-columns-overlays)
+       (let ((key (overlay-get ov 'org-columns-key)))
+        (when (and key (equal key p) (overlay-start ov))
+          (goto-char (overlay-start ov))
+          (let* ((spec (nth (current-column) org-columns-current-fmt-compiled))
+                 (value
+                  (or (cdr (assoc spec
+                                  (get-text-property (line-beginning-position)
+                                                     'org-summaries)))
+                      (org-entry-get (point) key))))
+            (when value
+              (let ((displayed (org-columns--displayed-value spec value))
+                    (format (overlay-get ov 'org-columns-format))
+                    (width
+                     (aref org-columns-current-maxwidths (current-column))))
+                (overlay-put ov 'org-columns-value value)
+                (overlay-put ov 'org-columns-value-modified displayed)
+                (overlay-put ov
+                             'display
+                             (org-columns--overlay-text
+                              displayed format width property value)))))))))))
 
 (defun org-columns-redo ()
   "Construct the column display again."
   (interactive)
   (message "Recomputing columns...")
-  (let ((line (org-current-line))
-       (col (current-column)))
-    (save-excursion
-      (if (marker-position org-columns-begin-marker)
-         (goto-char org-columns-begin-marker))
-      (org-columns-remove-overlays)
-      (if (derived-mode-p 'org-mode)
-         (call-interactively 'org-columns)
-       (org-agenda-redo)
-       (call-interactively 'org-agenda-columns)))
-    (org-goto-line line)
-    (move-to-column col))
+  (org-with-wide-buffer
+   (when (marker-position org-columns-begin-marker)
+     (goto-char org-columns-begin-marker))
+   (org-columns-remove-overlays)
+   (if (derived-mode-p 'org-mode)
+       ;; Since we already know the columns format, provide it instead
+       ;; of computing again.
+       (call-interactively #'org-columns org-columns-current-fmt)
+     (org-agenda-redo)
+     (call-interactively #'org-agenda-columns)))
   (message "Recomputing columns...done"))
 
-(defun org-columns-not-in-agenda ()
-  (if (eq major-mode 'org-agenda-mode)
-      (error "This command is only allowed in Org-mode buffers")))
-
-(defun org-string-to-number (s)
-  "Convert string to number, and interpret hh:mm:ss."
-  (if (not (string-match ":" s))
-      (string-to-number s)
-    (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
-      (while l
-       (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
-      sum)))
-
-;;;###autoload
-(defun org-columns-number-to-string (n fmt &optional printf)
-  "Convert a computed column number to a string value, according to FMT."
-  (cond
-   ((memq fmt '(estimate)) (org-estimate-print n printf))
-   ((not (numberp n)) "")
-   ((memq fmt '(add_times max_times min_times mean_times))
-    (org-hours-to-clocksum-string n))
-   ((eq fmt 'checkbox)
-    (cond ((= n (floor n)) "[X]")
-         ((> n 1.) "[-]")
-         (t "[ ]")))
-   ((memq fmt '(checkbox-n-of-m checkbox-percent))
-    (let* ((n1 (floor n)) (n2 (floor (+ .5 (* 1000000 (- n n1))))))
-      (org-nofm-to-completion n1 (+ n2 n1) (eq fmt 'checkbox-percent))))
-   (printf (format printf n))
-   ((eq fmt 'currency)
-    (format "%.2f" n))
-   ((memq fmt '(min_age max_age mean_age))
-    (org-format-time-period n))
-   (t (number-to-string n))))
-
-(defun org-nofm-to-completion (n m &optional percent)
-  (if (not percent)
-      (format "[%d/%d]" n m)
-    (format "[%d%%]" (round (* 100.0 n) m))))
-
-
-(defun org-columns-string-to-number (s fmt)
-  "Convert a column value to a number that can be used for column computing."
-  (if s
-      (cond
-       ((memq fmt '(min_age max_age mean_age))
-        (cond ((string= s "") org-columns-time)
-              ((string-match
-                "\\([0-9]+\\)d \\([0-9]+\\)h \\([0-9]+\\)m \\([0-9]+\\)s"
-                s)
-               (+ (* 60 (+ (* 60 (+ (* 24 (string-to-number (match-string 1 
s)))
-                                    (string-to-number (match-string 2 s))))
-                           (string-to-number (match-string 3 s))))
-                  (string-to-number (match-string 4 s))))
-              (t (time-to-number-of-days (apply 'encode-time
-                                                (org-parse-time-string s 
t))))))
-       ((string-match ":" s)
-        (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
-          (while l
-            (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
-          sum))
-       ((string-match (concat "\\([0-9.]+\\) *\\("
-                             (regexp-opt (mapcar 'car org-effort-durations))
-                             "\\)") s)
-       (setq s (concat "0:" (org-duration-string-to-minutes s t)))
-        (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
-          (while l
-            (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
-          sum))
-       ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
-        (if (equal s "[X]") 1. 0.000001))
-       ((memq fmt '(estimate)) (org-string-to-estimate s))
-       (t (string-to-number s)))))
-
-(defun org-columns-uncompile-format (cfmt)
-  "Turn the compiled columns format back into a string representation."
-  (let ((rtn "") e s prop title op op-match width fmt printf fun calc)
-    (while (setq e (pop cfmt))
-      (setq prop (car e)
-           title (nth 1 e)
-           width (nth 2 e)
-           op (nth 3 e)
-           fmt (nth 4 e)
-           printf (nth 5 e)
-           fun (nth 6 e)
-           calc (nth 7 e))
-      (when (setq op-match (rassoc (list fmt fun calc) 
org-columns-compile-map))
-       (setq op (car op-match)))
-      (if (and op printf) (setq op (concat op ";" printf)))
-      (if (equal title prop) (setq title nil))
-      (setq s (concat "%" (if width (number-to-string width))
-                     prop
-                     (if title (concat "(" title ")"))
-                     (if op (concat "{" op "}"))))
-      (setq rtn (concat rtn " " s)))
-    (org-trim rtn)))
+(defun org-columns-uncompile-format (compiled)
+  "Turn the compiled columns format back into a string representation.
+COMPILED is an alist, as returned by
+`org-columns-compile-format', which see."
+  (mapconcat
+   (lambda (spec)
+     (pcase spec
+       (`(,prop ,title ,width ,op ,printf)
+       (concat "%"
+               (and width (number-to-string width))
+               prop
+               (and title (not (equal prop title)) (format "(%s)" title))
+               (cond ((not op) nil)
+                     (printf (format "{%s;%s}" op printf))
+                     (t (format "{%s}" op)))))))
+   compiled " "))
 
 (defun org-columns-compile-format (fmt)
-  "Turn a column format string into an alist of specifications.
+  "Turn a column format string FMT into an alist of specifications.
+
 The alist has one entry for each column in the format.  The elements of
 that list are:
-property     the property
-title        the title field for the columns
-width        the column width in characters, can be nil for automatic
-operator     the operator if any
-format       the output format for computed results, derived from operator
-printf       a printf format for computed values
-fun          the lisp function to compute summary values, derived from operator
-calc         function to get values from base elements"
-  (let ((start 0) width prop title op op-match f printf fun calc)
-    (setq org-columns-current-fmt-compiled nil)
+property    the property name, as an upper-case string
+title       the title field for the columns, as a string
+width       the column width in characters, can be nil for automatic width
+operator    the summary operator, as a string, or nil
+printf      a printf format for computed values, as a string, or nil
+
+This function updates `org-columns-current-fmt-compiled'."
+  (setq org-columns-current-fmt-compiled nil)
+  (let ((start 0))
     (while (string-match
-           (org-re 
"%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\\(?:{\\([^}]+\\)}\\)?\\s-*")
+           "%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\
+\\(?:{\\([^}]+\\)}\\)?\\s-*"
            fmt start)
-      (setq start (match-end 0)
-           width (match-string 1 fmt)
-           prop (match-string 2 fmt)
-           title (or (match-string 3 fmt) prop)
-           op (match-string 4 fmt)
-           f nil
-           printf nil
-           fun '+
-           calc nil)
-      (if width (setq width (string-to-number width)))
-      (when (and op (string-match ";" op))
-       (setq printf (substring op (match-end 0))
-             op (substring op 0 (match-beginning 0))))
-      (when (setq op-match (assoc op org-columns-compile-map))
-       (setq f (cadr op-match)
-             fun (caddr op-match)
-             calc (cadddr op-match)))
-      (push (list prop title width op f printf fun calc)
-           org-columns-current-fmt-compiled))
+      (setq start (match-end 0))
+      (let* ((width (and (match-end 1) (string-to-number (match-string 1 
fmt))))
+            (prop (match-string-no-properties 2 fmt))
+            (title (or (match-string-no-properties 3 fmt) prop))
+            (operator (match-string-no-properties 4 fmt)))
+       (push (if (not operator) (list (upcase prop) title width nil nil)
+               (let (printf)
+                 (when (string-match ";" operator)
+                   (setq printf (substring operator (match-end 0)))
+                   (setq operator (substring operator 0 (match-beginning 0))))
+                 (list (upcase prop) title width operator printf)))
+             org-columns-current-fmt-compiled)))
     (setq org-columns-current-fmt-compiled
          (nreverse org-columns-current-fmt-compiled))))
 
+
+;;;; Column View Summary
+
+(defconst org-columns--duration-re
+  (concat "[0-9.]+ *" (regexp-opt (mapcar #'car org-effort-durations)))
+  "Regexp matching a duration.")
+
+(defun org-columns--time-to-seconds (s)
+  "Turn time string S into a number of seconds.
+A time is expressed as HH:MM, HH:MM:SS, or with units defined in
+`org-effort-durations'.  Plain numbers are considered as hours."
+  (cond
+   ((string-match-p org-columns--duration-re s)
+    (* 60 (org-duration-string-to-minutes s)))
+   ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\'" s)
+    (+ (* 3600 (string-to-number (match-string 1 s)))
+       (* 60 (string-to-number (match-string 2 s)))
+       (if (match-end 3) (string-to-number (match-string 3 s)) 0)))
+   (t (* 3600 (string-to-number s)))))
+
+(defun org-columns--age-to-seconds (s)
+  "Turn age string S into a number of seconds.
+An age is either computed from a given time-stamp, or indicated
+as days/hours/minutes/seconds."
+  (cond
+   ((string-match-p org-ts-regexp s)
+    (floor
+     (- org-columns--time
+       (float-time (apply #'encode-time (org-parse-time-string s nil t))))))
+   ;; Match own output for computations in upper levels.
+   ((string-match "\\([0-9]+\\)d \\([0-9]+\\)h \\([0-9]+\\)m \\([0-9]+\\)s" s)
+    (+ (* 86400 (string-to-number (match-string 1 s)))
+       (* 3600 (string-to-number (match-string 2 s)))
+       (* 60 (string-to-number (match-string 3 s)))
+       (string-to-number (match-string 4 s))))
+   (t (user-error "Invalid age: %S" s))))
+
+(defun org-columns--summary-apply-times (fun times)
+  "Apply FUN to time values TIMES.
+If TIMES contains any time value expressed as a duration, return
+the result as a duration.  If it contains any H:M:S, use that
+format instead.  Otherwise, use H:M format."
+  (let* ((hms-flag nil)
+        (duration-flag nil)
+        (seconds
+         (apply fun
+                (mapcar
+                 (lambda (time)
+                   (cond
+                    (duration-flag)
+                    ((string-match-p org-columns--duration-re time)
+                     (setq duration-flag t))
+                    (hms-flag)
+                    ((string-match-p "\\`[0-9]+:[0-9]+:[0-9]+\\'" time)
+                     (setq hms-flag t)))
+                   (org-columns--time-to-seconds time))
+                 times))))
+    (cond (duration-flag (org-minutes-to-clocksum-string (/ seconds 60.0)))
+         (hms-flag (format-seconds "%h:%.2m:%.2s" seconds))
+         (t (format-seconds "%h:%.2m" seconds)))))
+
+(defun org-columns--compute-spec (spec &optional update)
+  "Update tree according to SPEC.
+SPEC is a column format specification.  When optional argument
+UPDATE is non-nil, summarized values can replace existing ones in
+properties drawers."
+  (let* ((lmax (if (bound-and-true-p org-inlinetask-min-level)
+                  org-inlinetask-min-level
+                29))                   ;Hard-code deepest level.
+        (lvals (make-vector (1+ lmax) nil))
+        (level 0)
+        (inminlevel lmax)
+        (last-level lmax)
+        (property (car spec))
+        (printf (nth 4 spec))
+        (summarize (org-columns--summarize (nth 3 spec))))
+    (org-with-wide-buffer
+     ;; Find the region to compute.
+     (goto-char org-columns-top-level-marker)
+     (goto-char (condition-case nil (org-end-of-subtree t) (error 
(point-max))))
+     ;; Walk the tree from the back and do the computations.
+     (while (re-search-backward
+            org-outline-regexp-bol org-columns-top-level-marker t)
+       (unless (or (= level 0) (eq level inminlevel))
+        (setq last-level level))
+       (setq level (org-reduced-level (org-outline-level)))
+       (let* ((pos (match-beginning 0))
+             (value (org-entry-get nil property))
+             (value-set (org-string-nw-p value)))
+        (cond
+         ((< level last-level)
+          ;; Collect values from lower levels and inline tasks here
+          ;; and summarize them using SUMMARIZE.  Store them in text
+          ;; property `org-summaries', in alist whose key is SPEC.
+          (let* ((summary
+                  (and summarize
+                       (let ((values (append (and (/= last-level inminlevel)
+                                                  (aref lvals last-level))
+                                             (aref lvals inminlevel))))
+                         (and values (funcall summarize values printf))))))
+            ;; Leaf values are not summaries: do not mark them.
+            (when summary
+              (let* ((summaries-alist (get-text-property pos 'org-summaries))
+                     (old (assoc spec summaries-alist)))
+                (if old (setcdr old summary)
+                  (push (cons spec summary) summaries-alist)
+                  (org-with-silent-modifications
+                   (add-text-properties
+                    pos (1+ pos) (list 'org-summaries summaries-alist)))))
+              ;; When PROPERTY exists in current node, even if empty,
+              ;; but its value doesn't match the one computed, use
+              ;; the latter instead.
+              ;;
+              ;; Ignore leading or trailing white spaces that might
+              ;; have been introduced in summary, since those are not
+              ;; significant in properties value.
+              (let ((new-value (org-trim summary)))
+                (when (and update value (not (equal value new-value)))
+                  (org-entry-put (point) property new-value))))
+            ;; Add current to current level accumulator.
+            (when (or summary value-set)
+              (push (or summary value) (aref lvals level)))
+            ;; Clear accumulators for deeper levels.
+            (cl-loop for l from (1+ level) to lmax do (aset lvals l nil))))
+         (value-set (push value (aref lvals level)))
+         (t nil)))))))
+
+;;;###autoload
+(defun org-columns-compute (property)
+  "Summarize the values of PROPERTY hierarchically.
+Also update existing values for PROPERTY according to the first
+column specification."
+  (interactive)
+  (let ((main-flag t)
+       (upcase-prop (upcase property)))
+    (dolist (spec org-columns-current-fmt-compiled)
+      (pcase spec
+       (`(,(pred (equal upcase-prop)) . ,_)
+        (org-columns--compute-spec spec main-flag)
+        ;; Only the first summary can update the property value.
+        (when main-flag (setq main-flag nil)))))))
 
+(defun org-columns-compute-all ()
+  "Compute all columns that have operators defined."
+  (org-with-silent-modifications
+   (remove-text-properties (point-min) (point-max) '(org-summaries t)))
+  (let ((org-columns--time (float-time (current-time)))
+       seen)
+    (dolist (spec org-columns-current-fmt-compiled)
+      (let ((property (car spec)))
+       ;; Property value is updated only the first time a given
+       ;; property is encountered.
+       (org-columns--compute-spec spec (not (member property seen)))
+       (push property seen)))))
+
+(defun org-columns--summary-sum (values printf)
+  "Compute the sum of VALUES.
+When PRINTF is non-nil, use it to format the result."
+  (format (or printf "%s") (apply #'+ (mapcar #'string-to-number values))))
+
+(defun org-columns--summary-currencies (values _)
+  "Compute the sum of VALUES, with two decimals."
+  (format "%.2f" (apply #'+ (mapcar #'string-to-number values))))
+
+(defun org-columns--summary-checkbox (check-boxes _)
+  "Summarize CHECK-BOXES with a check-box."
+  (let ((done (cl-count "[X]" check-boxes :test #'equal))
+       (all (length check-boxes)))
+    (cond ((= done all) "[X]")
+         ((> done 0) "[-]")
+         (t "[ ]"))))
+
+(defun org-columns--summary-checkbox-count (check-boxes _)
+  "Summarize CHECK-BOXES with a check-box cookie."
+  (format "[%d/%d]"
+         (cl-count-if (lambda (b) (or (equal b "[X]")
+                                 (string-match-p "\\[\\([1-9]\\)/\\1\\]" b)))
+                      check-boxes)
+         (length check-boxes)))
+
+(defun org-columns--summary-checkbox-percent (check-boxes _)
+  "Summarize CHECK-BOXES with a check-box percent."
+  (format "[%d%%]"
+         (round (* 100.0 (cl-count-if (lambda (b) (member b '("[X]" "[100%]")))
+                                      check-boxes))
+                (length check-boxes))))
+
+(defun org-columns--summary-min (values printf)
+  "Compute the minimum of VALUES.
+When PRINTF is non-nil, use it to format the result."
+  (format (or printf "%s")
+         (apply #'min (mapcar #'string-to-number values))))
+
+(defun org-columns--summary-max (values printf)
+  "Compute the maximum of VALUES.
+When PRINTF is non-nil, use it to format the result."
+  (format (or printf "%s")
+         (apply #'max (mapcar #'string-to-number values))))
+
+(defun org-columns--summary-mean (values printf)
+  "Compute the mean of VALUES.
+When PRINTF is non-nil, use it to format the result."
+  (format (or printf "%s")
+         (/ (apply #'+ (mapcar #'string-to-number values))
+            (float (length values)))))
+
+(defun org-columns--summary-sum-times (times _)
+  "Sum TIMES."
+  (org-columns--summary-apply-times #'+ times))
+
+(defun org-columns--summary-min-time (times _)
+  "Compute the minimum time among TIMES."
+  (org-columns--summary-apply-times #'min times))
+
+(defun org-columns--summary-max-time (times _)
+  "Compute the maximum time among TIMES."
+  (org-columns--summary-apply-times #'max times))
+
+(defun org-columns--summary-mean-time (times _)
+  "Compute the mean time among TIMES."
+  (org-columns--summary-apply-times
+   (lambda (&rest values) (/ (apply #'+ values) (float (length values))))
+   times))
+
+(defun org-columns--summary-min-age (ages _)
+  "Compute the minimum time among AGES."
+  (format-seconds
+   "%dd %.2hh %mm %ss"
+   (apply #'min (mapcar #'org-columns--age-to-seconds ages))))
+
+(defun org-columns--summary-max-age (ages _)
+  "Compute the maximum time among AGES."
+  (format-seconds
+   "%dd %.2hh %mm %ss"
+   (apply #'max (mapcar #'org-columns--age-to-seconds ages))))
+
+(defun org-columns--summary-mean-age (ages _)
+  "Compute the minimum time among AGES."
+  (format-seconds
+   "%dd %.2hh %mm %ss"
+   (/ (apply #'+ (mapcar #'org-columns--age-to-seconds ages))
+      (float (length ages)))))
+
+(defun org-columns--summary-estimate (estimates _)
+  "Combine a list of estimates, using mean and variance.
+The mean and variance of the result will be the sum of the means
+and variances (respectively) of the individual estimates."
+  (let ((mean 0)
+        (var 0))
+    (dolist (e estimates)
+      (pcase (mapcar #'string-to-number (split-string e "-"))
+       (`(,low ,high)
+        (let ((m (/ (+ low high) 2.0)))
+          (cl-incf mean m)
+          (cl-incf var (- (/ (+ (* low low) (* high high)) 2.0) (* m m)))))
+       (`(,value) (cl-incf mean value))))
+    (let ((sd (sqrt var)))
+      (format "%s-%s"
+             (format "%.0f" (- mean sd))
+             (format "%.0f" (+ mean sd))))))
+
+
+
 ;;; Dynamic block for Column view
 
-(defvar org-heading-regexp) ; defined in org.el
-(defvar org-heading-keyword-regexp-format) ; defined in org.el
-(defun org-columns-capture-view (&optional maxlevel skip-empty-rows)
-  "Get the column view of the current buffer or subtree.
-The first optional argument MAXLEVEL sets the level limit.  A
-second optional argument SKIP-EMPTY-ROWS tells whether to skip
+(defun org-columns--capture-view (maxlevel skip-empty format local)
+  "Get the column view of the current buffer.
+
+MAXLEVEL sets the level limit.  SKIP-EMPTY tells whether to skip
 empty rows, an empty row being one where all the column view
-specifiers except ITEM are empty.  This function returns a list
-containing the title row and all other rows.  Each row is a list
-of fields."
-  (save-excursion
-    (let* ((title (mapcar 'cadr org-columns-current-fmt-compiled))
-          (re-comment (format org-heading-keyword-regexp-format
-                              org-comment-string))
-          (re-archive (concat ".*:" org-archive-tag ":"))
-          (n (length title)) row tbl)
-      (goto-char (point-min))
-      (while (re-search-forward org-heading-regexp nil t)
-       (catch 'next
-         (when (and (or (null maxlevel)
-                        (>= maxlevel
-                            (if org-odd-levels-only
-                                (/ (1+ (length (match-string 1))) 2)
-                              (length (match-string 1)))))
-                    (get-char-property (match-beginning 0) 'org-columns-key))
-           (when (save-excursion
-                   (goto-char (point-at-bol))
-                   (or (looking-at re-comment)
-                       (looking-at re-archive)))
-             (org-end-of-subtree t)
-             (throw 'next t))
-           (setq row nil)
-           (loop for i from 0 to (1- n) do
-                 (push
-                  (org-quote-vert
-                   (or (get-char-property (+ (match-beginning 0) i) 
'org-columns-value-modified)
-                       (get-char-property (+ (match-beginning 0) i) 
'org-columns-value)
-                       ""))
-                  row))
-           (setq row (nreverse row))
-           (unless (and skip-empty-rows
-                        (eq 1 (length (delete "" (delete-dups (copy-sequence 
row))))))
-             (push row tbl)))))
-      (append (list title 'hline) (nreverse tbl)))))
+specifiers but ITEM are empty.  FORMAT is a format string for
+columns, or nil.  When LOCAL is non-nil, only capture headings in
+current subtree.
+
+This function returns a list containing the title row and all
+other rows.  Each row is a list of fields, as strings, or
+`hline'."
+  (org-columns (not local) format)
+  (goto-char org-columns-top-level-marker)
+  (let ((columns (length org-columns-current-fmt-compiled))
+       (has-item (assoc "ITEM" org-columns-current-fmt-compiled))
+       table)
+    (org-map-entries
+     (lambda ()
+       (when (get-char-property (point) 'org-columns-key)
+        (let (row)
+          (dotimes (i columns)
+            (let* ((col (+ (line-beginning-position) i))
+                   (p (get-char-property col 'org-columns-key)))
+              (push (org-quote-vert
+                     (get-char-property col
+                                        (if (string= p "ITEM")
+                                            'org-columns-value
+                                          'org-columns-value-modified)))
+                    row)))
+          (unless (and skip-empty
+                       (let ((r (delete-dups (remove "" row))))
+                         (or (null r) (and has-item (= (length r) 1)))))
+            (push (cons (org-reduced-level (org-current-level)) (nreverse row))
+                  table)))))
+     (and maxlevel (format "LEVEL<=%d" maxlevel))
+     (and local 'tree)
+     'archive 'comment)
+    (org-columns-quit)
+    ;; Add column titles and a horizontal rule in front of the table.
+    (cons (mapcar #'cadr org-columns-current-fmt-compiled)
+         (cons 'hline (nreverse table)))))
+
+(defun org-columns--clean-item (item)
+  "Remove sensitive contents from string ITEM.
+This includes objects that may not be duplicated within
+a document, e.g., a target, or those forbidden in tables, e.g.,
+an inline src-block."
+  (let ((data (org-element-parse-secondary-string
+              item (org-element-restriction 'headline))))
+    (org-element-map data
+       '(footnote-reference inline-babel-call inline-src-block target
+                            radio-target statistics-cookie)
+      #'org-element-extract-element)
+    (org-no-properties (org-element-interpret-data data))))
 
 ;;;###autoload
 (defun org-dblock-write:columnview (params)
   "Write the column view table.
 PARAMS is a property list of parameters:
 
-:width    enforce same column widths with <N> specifiers.
 :id       the :ID: property of the entry where the columns view
          should be built.  When the symbol `local', call locally.
          When `global' call column view with the cursor at the beginning
@@ -1247,339 +1392,269 @@ PARAMS is a property list of parameters:
          using `org-id-find'.
 :hlines   When t, insert a hline before each item.  When a number, insert
          a hline before each level <= that number.
+:indent   When non-nil, indent each ITEM field according to its level.
 :vlines   When t, make each column a colgroup to enforce vertical lines.
 :maxlevel When set to a number, don't capture headlines below this level.
 :skip-empty-rows
          When t, skip rows where all specifiers other than ITEM are empty.
+:width    apply widths specified in columns format using <N> specifiers.
 :format   When non-nil, specify the column view format to use."
-  (let ((pos (point-marker))
-       (hlines (plist-get params :hlines))
-       (vlines (plist-get params :vlines))
-       (maxlevel (plist-get params :maxlevel))
-       (content-lines (org-split-string (plist-get params :content) "\n"))
-       (skip-empty-rows (plist-get params :skip-empty-rows))
-       (columns-fmt (plist-get params :format))
-       (case-fold-search t)
-       tbl id idpos nfields tmp recalc line
-       id-as-string view-file view-pos)
-    (when (setq id (plist-get params :id))
-      (setq id-as-string (cond ((numberp id) (number-to-string id))
-                              ((symbolp id) (symbol-name id))
-                              ((stringp id) id)
-                              (t "")))
-      (cond ((not id) nil)
-           ((eq id 'global) (setq view-pos (point-min)))
-           ((eq id 'local))
-           ((string-match "^file:\\(.*\\)" id-as-string)
-            (setq view-file (match-string 1 id-as-string)
-                  view-pos 1)
-            (unless (file-exists-p view-file)
-              (error "No such file: \"%s\"" id-as-string)))
-           ((setq idpos (org-find-entry-with-id id))
-            (setq view-pos idpos))
-           ((setq idpos (org-id-find id))
-            (setq view-file (car idpos))
-            (setq view-pos (cdr idpos)))
-           (t (error "Cannot find entry with :ID: %s" id))))
-    (with-current-buffer (if view-file
-                            (get-file-buffer view-file)
-                          (current-buffer))
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (or view-pos (point)))
-         (org-columns columns-fmt)
-         (setq tbl (org-columns-capture-view maxlevel skip-empty-rows))
-         (setq nfields (length (car tbl)))
-         (org-columns-quit))))
-    (goto-char pos)
-    (move-marker pos nil)
-    (when tbl
-      (when (plist-get params :hlines)
-       (setq tmp nil)
-       (while tbl
-         (if (eq (car tbl) 'hline)
-             (push (pop tbl) tmp)
-           (if (string-match "\\` *\\(\\*+\\)" (caar tbl))
-               (if (and (not (eq (car tmp) 'hline))
-                        (or (eq hlines t)
-                            (and (numberp hlines)
-                                 (<= (- (match-end 1) (match-beginning 1))
-                                     hlines))))
-                   (push 'hline tmp)))
-           (push (pop tbl) tmp)))
-       (setq tbl (nreverse tmp)))
-      (when vlines
-       (setq tbl (mapcar (lambda (x)
-                           (if (eq 'hline x) x (cons "" x)))
-                         tbl))
-       (setq tbl (append tbl (list (cons "/" (make-list nfields "<>"))))))
-      (when content-lines
-       (while (string-match "^#" (car content-lines))
-         (insert (pop content-lines) "\n")))
-      (setq pos (point))
-      (insert (org-listtable-to-string tbl))
+  (let ((table
+        (let ((id (plist-get params :id))
+              view-file view-pos)
+          (pcase id
+            (`global nil)
+            ((or `local `nil) (setq view-pos (point)))
+            ((and (let id-string (format "%s" id))
+                  (guard (string-match "^file:\\(.*\\)" id-string)))
+             (setq view-file (match-string-no-properties 1 id-string))
+             (unless (file-exists-p view-file)
+               (user-error "No such file: %S" id-string)))
+            ((and (let idpos (org-find-entry-with-id id)) (guard idpos))
+             (setq view-pos idpos))
+            ((let `(,filename . ,position) (org-id-find id))
+             (setq view-file filename)
+             (setq view-pos position))
+            (_ (user-error "Cannot find entry with :ID: %s" id)))
+          (with-current-buffer (if view-file (get-file-buffer view-file)
+                                 (current-buffer))
+            (org-with-wide-buffer
+             (when view-pos (goto-char view-pos))
+             (org-columns--capture-view (plist-get params :maxlevel)
+                                        (plist-get params :skip-empty-rows)
+                                        (plist-get params :format)
+                                        view-pos))))))
+    (when table
+      ;; Prune level information from the table.  Also normalize
+      ;; headings: remove stars, add indentation entities, if
+      ;; required, and possibly precede some of them with a horizontal
+      ;; rule.
+      (let ((item-index
+            (let ((p (assoc "ITEM" org-columns-current-fmt-compiled)))
+              (and p (cl-position p
+                                  org-columns-current-fmt-compiled
+                                  :test #'equal))))
+           (hlines (plist-get params :hlines))
+           (indent (plist-get params :indent))
+           new-table)
+       ;; Copy header and first rule.
+       (push (pop table) new-table)
+       (push (pop table) new-table)
+       (dolist (row table (setq table (nreverse new-table)))
+         (let ((level (car row)))
+           (when (and (not (eq (car new-table) 'hline))
+                      (or (eq hlines t)
+                          (and (numberp hlines) (<= level hlines))))
+             (push 'hline new-table))
+           (when item-index
+             (let ((item (org-columns--clean-item (nth item-index (cdr row)))))
+               (setf (nth item-index (cdr row))
+                     (if (and indent (> level 1))
+                         (concat "\\_" (make-string (* 2 (1- level)) ?\s) item)
+                       item))))
+           (push (cdr row) new-table))))
       (when (plist-get params :width)
-       (insert "\n|" (mapconcat (lambda (x) (format "<%d>" (max 3 x)))
-                                org-columns-current-widths "|")))
-      (while (setq line (pop content-lines))
-       (when (string-match "^#" line)
-         (insert "\n" line)
-         (when (string-match "^[ \t]*#\\+tblfm" line)
-           (setq recalc t))))
-      (if recalc
-         (progn (goto-char pos) (org-table-recalculate 'all))
-       (goto-char pos)
+       (setq table
+             (append table
+                     (list
+                      (mapcar (lambda (spec)
+                                (let ((w (nth 2 spec)))
+                                  (if w (format "<%d>" (max 3 w)) "")))
+                              org-columns-current-fmt-compiled)))))
+      (when (plist-get params :vlines)
+       (setq table
+             (let ((size (length org-columns-current-fmt-compiled)))
+               (append (mapcar (lambda (x) (if (eq 'hline x) x (cons "" x)))
+                               table)
+                       (list (cons "/" (make-list size "<>")))))))
+      (let ((content-lines (org-split-string (plist-get params :content) "\n"))
+           recalc)
+       ;; Insert affiliated keywords before the table.
+       (when content-lines
+         (while (string-match-p "\\`[ \t]*#\\+" (car content-lines))
+           (insert (pop content-lines) "\n")))
+       (save-excursion
+         ;; Insert table at point.
+         (insert
+          (mapconcat (lambda (row)
+                       (if (eq row 'hline) "|-|"
+                         (format "|%s|" (mapconcat #'identity row "|"))))
+                     table
+                     "\n"))
+         ;; Insert TBLFM lines following table.
+         (let ((case-fold-search t))
+           (dolist (line content-lines)
+             (when (string-match-p "\\`[ \t]*#\\+TBLFM:" line)
+               (insert "\n" line)
+               (unless recalc (setq recalc t))))))
+       (when recalc (org-table-recalculate 'all t))
        (org-table-align)))))
 
-(defun org-listtable-to-string (tbl)
-  "Convert a listtable TBL to a string that contains the Org-mode table.
-The table still need to be aligned.  The resulting string has no leading
-and tailing newline characters."
-  (mapconcat
-   (lambda (x)
-     (cond
-      ((listp x)
-       (concat "|" (mapconcat 'identity x "|") "|"))
-      ((eq x 'hline) "|-|")
-      (t (error "Garbage in listtable: %s" x))))
-   tbl "\n"))
-
 ;;;###autoload
-(defun org-insert-columns-dblock ()
+(defun org-columns-insert-dblock ()
   "Create a dynamic block capturing a column view table."
   (interactive)
-  (let ((defaults '(:name "columnview" :hlines 1))
-       (id (org-icompleting-read
+  (let ((id (completing-read
             "Capture columns (local, global, entry with :ID: property) 
[local]: "
             (append '(("global") ("local"))
-                    (mapcar 'list (org-property-values "ID"))))))
-    (if (equal id "") (setq id 'local))
-    (if (equal id "global") (setq id 'global))
-    (setq defaults (append defaults (list :id id)))
-    (org-create-dblock defaults)
-    (org-update-dblock)))
+                    (mapcar #'list (org-property-values "ID"))))))
+    (org-create-dblock
+     (list :name "columnview"
+          :hlines 1
+          :id (cond ((string= id "global") 'global)
+                    ((member id '("" "local")) 'local)
+                    (id)))))
+  (org-update-dblock))
 
-;;; Column view in the agenda
-
-(defvar org-agenda-view-columns-initially nil
-  "When set, switch to columns view immediately after creating the agenda.")
 
-(defvar org-agenda-columns-show-summaries) ; defined in org-agenda.el
-(defvar org-agenda-columns-compute-summary-properties); defined in 
org-agenda.el
-(defvar org-agenda-columns-add-appointments-to-effort-sum); as well
+
+;;; Column view in the agenda
 
 ;;;###autoload
 (defun org-agenda-columns ()
   "Turn on or update column view in the agenda."
   (interactive)
-  (org-verify-version 'columns)
   (org-columns-remove-overlays)
   (move-marker org-columns-begin-marker (point))
-  (let ((org-columns-time (time-to-number-of-days (current-time)))
-       cache maxwidths m p a d fmt)
-    (cond
-     ((and (boundp 'org-agenda-overriding-columns-format)
-          org-agenda-overriding-columns-format)
-      (setq fmt org-agenda-overriding-columns-format))
-     ((setq m (org-get-at-bol 'org-hd-marker))
-      (setq fmt (or (org-entry-get m "COLUMNS" t)
-                   (with-current-buffer (marker-buffer m)
-                     org-columns-default-format))))
-     ((and (boundp 'org-columns-current-fmt)
-          (local-variable-p 'org-columns-current-fmt)
-          org-columns-current-fmt)
-      (setq fmt org-columns-current-fmt))
-     ((setq m (next-single-property-change (point-min) 'org-hd-marker))
-      (setq m (get-text-property m 'org-hd-marker))
-      (setq fmt (or (org-entry-get m "COLUMNS" t)
-                   (with-current-buffer (marker-buffer m)
-                     org-columns-default-format)))))
-    (setq fmt (or fmt org-columns-default-format))
-    (org-set-local 'org-columns-current-fmt fmt)
-    (org-columns-compile-format fmt)
+  (let* ((org-columns--time (float-time (current-time)))
+        (fmt
+         (cond
+          ((bound-and-true-p org-agenda-overriding-columns-format))
+          ((let ((m (org-get-at-bol 'org-hd-marker)))
+             (and m
+                  (or (org-entry-get m "COLUMNS" t)
+                      (with-current-buffer (marker-buffer m)
+                        org-columns-default-format)))))
+          ((and (local-variable-p 'org-columns-current-fmt)
+                org-columns-current-fmt))
+          ((let ((m (next-single-property-change (point-min) 'org-hd-marker)))
+             (and m
+                  (let ((m (get-text-property m 'org-hd-marker)))
+                    (or (org-entry-get m "COLUMNS" t)
+                        (with-current-buffer (marker-buffer m)
+                          org-columns-default-format))))))
+          (t org-columns-default-format)))
+        (compiled-fmt (org-columns-compile-format fmt)))
+    (setq org-columns-current-fmt fmt)
     (when org-agenda-columns-compute-summary-properties
       (org-agenda-colview-compute org-columns-current-fmt-compiled))
     (save-excursion
-      ;; Get and cache the properties
+      ;; Collect properties for each headline in current view.
       (goto-char (point-min))
-      (while (not (eobp))
-       (when (setq m (or (org-get-at-bol 'org-hd-marker)
-                         (org-get-at-bol 'org-marker)))
-         (setq p (org-entry-properties m))
-
-         (when (or (not (setq a (assoc org-effort-property p)))
-                   (not (string-match "\\S-" (or (cdr a) ""))))
-           ;; OK, the property is not defined.  Use appointment duration?
-           (when (and org-agenda-columns-add-appointments-to-effort-sum
-                      (setq d (get-text-property (point) 'duration)))
-             (setq d (org-minutes-to-clocksum-string d))
-             (put-text-property 0 (length d) 'face 'org-warning d)
-             (push (cons org-effort-property d) p)))
-         (push (cons (org-current-line) p) cache))
-       (beginning-of-line 2))
-      (when cache
-       (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
-       (org-set-local 'org-columns-current-maxwidths maxwidths)
-       (org-columns-display-here-title)
-       (when (org-set-local 'org-columns-flyspell-was-active
-                            (org-bound-and-true-p flyspell-mode))
-         (flyspell-mode 0))
-       (mapc (lambda (x)
-               (org-goto-line (car x))
-               (org-columns-display-here (cdr x)))
-             cache)
-       (when org-agenda-columns-show-summaries
-         (org-agenda-colview-summarize cache))))))
+      (let (cache)
+       (while (not (eobp))
+         (let ((m (org-get-at-bol 'org-hd-marker)))
+           (when m
+             (push (cons (line-beginning-position)
+                         ;; `org-columns-current-fmt-compiled' is
+                         ;; initialized but only set locally to the
+                         ;; agenda buffer.  Since current buffer is
+                         ;; changing, we need to force the original
+                         ;; compiled-fmt there.
+                         (org-with-point-at m
+                           (org-columns--collect-values compiled-fmt)))
+                   cache)))
+         (forward-line))
+       (when cache
+         (org-columns--set-widths cache)
+         (org-columns--display-here-title)
+         (when (setq-local org-columns-flyspell-was-active
+                           (bound-and-true-p flyspell-mode))
+           (flyspell-mode 0))
+         (dolist (entry cache)
+           (goto-char (car entry))
+           (org-columns--display-here (cdr entry)))
+         (when org-agenda-columns-show-summaries
+           (org-agenda-colview-summarize cache)))))))
 
 (defun org-agenda-colview-summarize (cache)
   "Summarize the summarizable columns in column view in the agenda.
 This will add overlays to the date lines, to show the summary for each day."
-  (let* ((fmt (mapcar (lambda (x)
-                       (if (string-match "CLOCKSUM.*" (car x))
-                           (list (match-string 0 (car x))
-                                 (nth 1 x) (nth 2 x) ":" 'add_times
-                                 nil '+ nil)
-                         x))
-                     org-columns-current-fmt-compiled))
-        line c c1 stype calc sumfunc props lsum entries prop v title)
-    (catch 'exit
-      (when (delq nil (mapcar 'cadr fmt))
-       ;; OK, at least one summation column, it makes sense to try this
-       (goto-char (point-max))
+  (let ((fmt (mapcar
+             (lambda (spec)
+               (pcase spec
+                 (`(,property ,title ,width . ,_)
+                  (if (member property '("CLOCKSUM" "CLOCKSUM_T"))
+                      (list property title width ":" nil)
+                    spec))))
+             org-columns-current-fmt-compiled)))
+    ;; Ensure there's at least one summation column.
+    (when (cl-some (lambda (spec) (nth 3 spec)) fmt)
+      (goto-char (point-max))
+      (catch :complete
        (while t
          (when (or (get-text-property (point) 'org-date-line)
                    (eq (get-text-property (point) 'face)
                        'org-agenda-structure))
-           ;; OK, this is a date line that should be used
-           (setq line (org-current-line))
-           (setq entries nil c cache cache nil)
-           (while (setq c1 (pop c))
-             (if (> (car c1) line)
-                 (push c1 entries)
-               (push c1 cache)))
-           ;; now ENTRIES are the ones we want to use, CACHE is the rest
-           ;; Compute the summaries for the properties we want,
-           ;; set nil properties for the rest.
-           (when (setq entries (mapcar 'cdr entries))
-             (setq props
-                   (mapcar
-                    (lambda (f)
-                      (setq prop (car f)
-                            title (nth 1 f)
-                            stype (nth 4 f)
-                            sumfunc (nth 6 f)
-                            calc (or (nth 7 f) 'identity))
-                      (cond
-                       ((equal prop "ITEM")
-                        (cons prop (buffer-substring (point-at-bol)
-                                                     (point-at-eol))))
-                       ((not stype) (cons prop ""))
-                       (t ;; do the summary
-                        (setq lsum nil)
-                        (dolist (x entries)
-                          (setq v (cdr (assoc prop x)))
-                          (if v
-                              (push
-                               (funcall
-                                (if (not (get-text-property 0 'org-computed v))
-                                    calc
-                                  'identity)
-                                (org-columns-string-to-number
-                                 v stype))
-                               lsum)))
-                        (setq lsum (remove nil lsum))
-                        (setq lsum
-                              (cond ((> (length lsum) 1)
-                                     (org-columns-number-to-string
-                                      (apply sumfunc lsum) stype))
-                                    ((eq (length lsum) 1)
-                                     (org-columns-number-to-string
-                                      (car lsum) stype))
-                                    (t "")))
-                        (put-text-property 0 (length lsum) 'face 'bold lsum)
-                        (unless (eq calc 'identity)
-                          (put-text-property 0 (length lsum) 'org-computed t 
lsum))
-                        (cons prop lsum))))
-                    fmt))
-             (org-columns-display-here props 'dateline)
-             (org-set-local 'org-agenda-columns-active t)))
-         (if (bobp) (throw 'exit t))
-         (beginning-of-line 0))))))
+           ;; OK, this is a date line that should be used.
+           (let (entries)
+             (let (rest)
+               (dolist (c cache)
+                 (if (> (car c) (point))
+                     (push c entries)
+                   (push c rest)))
+               (setq cache rest))
+             ;; ENTRIES contains entries below the current one.
+             ;; CACHE is the rest.  Compute the summaries for the
+             ;; properties we want, set nil properties for the rest.
+             (when (setq entries (mapcar #'cdr entries))
+               (org-columns--display-here
+                (mapcar
+                 (lambda (spec)
+                   (pcase spec
+                     (`("ITEM" . ,_)
+                      ;; Replace ITEM with current date.  Preserve
+                      ;; properties for fontification.
+                      (let ((date (buffer-substring
+                                   (line-beginning-position)
+                                   (line-end-position))))
+                        (list spec date date)))
+                     (`(,_ ,_ ,_ nil ,_) (list spec "" ""))
+                     (`(,_ ,_ ,_ ,operator ,printf)
+                      (let* ((summarize (org-columns--summarize operator))
+                             (values
+                              ;; Use real values for summary, not
+                              ;; those prepared for display.
+                              (delq nil
+                                    (mapcar
+                                     (lambda (e) (org-string-nw-p
+                                             (nth 1 (assoc spec e))))
+                                     entries)))
+                             (final (if values
+                                        (funcall summarize values printf)
+                                      "")))
+                        (unless (equal final "")
+                          (put-text-property 0 (length final)
+                                             'face 'bold final))
+                        (list spec final final)))))
+                 fmt)
+                'dateline)
+               (setq-local org-agenda-columns-active t))))
+         (if (bobp) (throw :complete t) (forward-line -1)))))))
 
 (defun org-agenda-colview-compute (fmt)
   "Compute the relevant columns in the contributing source buffers."
   (let ((files org-agenda-contributing-files)
        (org-columns-begin-marker (make-marker))
-       (org-columns-top-level-marker (make-marker))
-       f fm a b)
-    (while (setq f (pop files))
-      (setq b (find-buffer-visiting f))
-      (with-current-buffer (or (buffer-base-buffer b) b)
-       (save-excursion
-         (save-restriction
-           (widen)
-           (org-with-silent-modifications
-            (remove-text-properties (point-min) (point-max) '(org-summaries 
t)))
-           (goto-char (point-min))
-           (org-columns-get-format-and-top-level)
-           (while (setq fm (pop fmt))
-             (cond ((equal (car fm) "CLOCKSUM")
-                    (org-clock-sum))
-                   ((equal (car fm) "CLOCKSUM_T")
-                    (org-clock-sum-today))
-                   ((and (nth 4 fm)
-                         (setq a (assoc (car fm)
-                                        org-columns-current-fmt-compiled))
-                         (equal (nth 4 a) (nth 4 fm)))
-                    (org-columns-compute (car fm)))))))))))
-
-(defun org-format-time-period (interval)
-  "Convert time in fractional days to days/hours/minutes/seconds."
-  (if (numberp interval)
-      (let* ((days (floor interval))
-            (frac-hours (* 24 (- interval days)))
-            (hours (floor frac-hours))
-            (minutes (floor (* 60 (- frac-hours hours))))
-            (seconds (floor (* 60 (- (* 60 (- frac-hours hours)) minutes)))))
-       (format "%dd %02dh %02dm %02ds" days hours minutes seconds))
-    ""))
-
-(defun org-estimate-mean-and-var (v)
-  "Return the mean and variance of an estimate."
-  (let* ((low (float (car v)))
-         (high (float (cadr v)))
-         (mean (/ (+ low high) 2.0))
-         (var (/ (+ (expt (- mean low) 2.0) (expt (- high mean) 2.0)) 2.0)))
-    (list  mean var)))
-
-(defun org-estimate-combine (&rest el)
-  "Combine a list of estimates, using mean and variance.
-The mean and variance of the result will be the sum of the means
-and variances (respectively) of the individual estimates."
-  (let ((mean 0)
-        (var 0))
-    (mapc (lambda (e)
-           (let ((stats (org-estimate-mean-and-var e)))
-             (setq mean (+ mean (car stats)))
-             (setq var (+ var (cadr stats)))))
-         el)
-    (let ((stdev (sqrt var)))
-      (list (- mean stdev) (+ mean stdev)))))
-
-(defun org-estimate-print (e &optional fmt)
-  "Prepare a string representation of an estimate.
-This formats these numbers as two numbers with a \"-\" between them."
-  (if (null fmt) (set 'fmt "%.0f"))
-  (format "%s" (mapconcat (lambda (n) (format fmt n))  e "-")))
-
-(defun org-string-to-estimate (s)
-  "Convert a string to an estimate.
-The string should be two numbers joined with a \"-\"."
-  (if (string-match "\\(.*\\)-\\(.*\\)" s)
-      (list (string-to-number (match-string 1 s))
-           (string-to-number(match-string 2 s)))
-    (list (string-to-number s) (string-to-number s))))
+       (org-columns-top-level-marker (make-marker)))
+    (dolist (f files)
+      (let ((b (find-buffer-visiting f)))
+       (with-current-buffer (or (buffer-base-buffer b) b)
+         (org-with-wide-buffer
+          (org-with-silent-modifications
+           (remove-text-properties (point-min) (point-max) '(org-summaries t)))
+          (goto-char (point-min))
+          (org-columns-get-format-and-top-level)
+          (dolist (spec fmt)
+            (let ((prop (car spec)))
+              (cond
+               ((equal prop "CLOCKSUM") (org-clock-sum))
+               ((equal prop "CLOCKSUM_T") (org-clock-sum-today))
+               ((and (nth 3 spec)
+                     (let ((a (assoc prop org-columns-current-fmt-compiled)))
+                       (equal (nth 3 a) (nth 3 spec))))
+                (org-columns-compute prop)))))))))))
+
 
 (provide 'org-colview)
 
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index 42e2271..e1d4036 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -1,4 +1,4 @@
-;;; org-compat.el --- Compatibility code for Org-mode
+;;; org-compat.el --- Compatibility Code for Older Emacsen -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,65 +24,287 @@
 ;;
 ;;; Commentary:
 
-;; This file contains code needed for compatibility with XEmacs and older
+;; This file contains code needed for compatibility with older
 ;; versions of GNU Emacs.
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
-
+(require 'cl-lib)
 (require 'org-macs)
 
-;; The following constant is for backward compatibility.  We do not use
-;; it in org-mode, because the Byte compiler evaluates (featurep 'xemacs)
-;; at compilation time and can therefore optimize code better.
-(defconst org-xemacs-p (featurep 'xemacs))
-(defconst org-format-transports-properties-p
-  (let ((x "a"))
-    (add-text-properties 0 1 '(test t) x)
-    (get-text-property 0 'test (format "%s" x)))
-  "Does format transport text properties?")
+(declare-function org-at-table.el-p "org" (&optional table-type))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-type "org-element" (element))
+(declare-function org-link-set-parameters "org" (type &rest rest))
+(declare-function org-table-end (&optional table-type))
+(declare-function table--at-cell-p "table" (position &optional object 
at-column))
+
+(defvar org-table-any-border-regexp)
+(defvar org-table-dataline-regexp)
+(defvar org-table-tab-recognizes-table.el)
+(defvar org-table1-hline-regexp)
+
+;; As of Emacs 25.1, `outline-mode' functions are under the 'outline-'
+;; prefix, `find-tag' is replaced with `xref-find-definition' and
+;; `x-get-selection' with `gui-get-selection'.
+(when (< emacs-major-version 25)
+  (defalias 'outline-hide-entry 'hide-entry)
+  (defalias 'outline-hide-sublevels 'hide-sublevels)
+  (defalias 'outline-hide-subtree 'hide-subtree)
+  (defalias 'outline-show-all 'show-all)
+  (defalias 'outline-show-branches 'show-branches)
+  (defalias 'outline-show-children 'show-children)
+  (defalias 'outline-show-entry 'show-entry)
+  (defalias 'outline-show-subtree 'show-subtree)
+  (defalias 'xref-find-definitions 'find-tag)
+  (defalias 'format-message 'format)
+  (defalias 'gui-get-selection 'x-get-selection))
+
+
+;;; Obsolete aliases (remove them after the next major release).
+
+;;;; XEmacs compatibility, now removed.
+(define-obsolete-function-alias 'org-activate-mark 'activate-mark)
+(define-obsolete-function-alias 'org-add-hook 'add-hook "Org 9.0")
+(define-obsolete-function-alias 'org-bound-and-true-p 'bound-and-true-p "Org 
9.0")
+(define-obsolete-function-alias 'org-decompose-region 'decompose-region "Org 
9.0")
+(define-obsolete-function-alias 'org-defvaralias 'defvaralias "Org 9.0")
+(define-obsolete-function-alias 'org-detach-overlay 'delete-overlay "Org 9.0")
+(define-obsolete-function-alias 'org-file-equal-p 'file-equal-p "Org 9.0")
+(define-obsolete-function-alias 'org-float-time 'float-time "Org 9.0")
+(define-obsolete-function-alias 'org-indent-line-to 'indent-line-to "Org 9.0")
+(define-obsolete-function-alias 'org-indent-to-column 'indent-to-column "Org 
9.0")
+(define-obsolete-function-alias 'org-looking-at-p 'looking-at-p "Org 9.0")
+(define-obsolete-function-alias 'org-looking-back 'looking-back "Org 9.0")
+(define-obsolete-function-alias 'org-match-string-no-properties 
'match-string-no-properties "Org 9.0")
+(define-obsolete-function-alias 'org-propertize 'propertize "Org 9.0")
+(define-obsolete-function-alias 'org-select-frame-set-input-focus 
'select-frame-set-input-focus "Org 9.0")
+
+(defmacro org-re (s)
+  "Replace posix classes in regular expression S."
+  (declare (debug (form))
+          (obsolete "you can safely remove it." "Org 9.0"))
+  s)
+
+;;;; Functions from cl-lib that Org used to have its own implementation of.
+(define-obsolete-function-alias 'org-count 'cl-count "Org 9.0")
+(define-obsolete-function-alias 'org-every 'cl-every "Org 9.0")
+(define-obsolete-function-alias 'org-find-if 'cl-find-if "Org 9.0")
+(define-obsolete-function-alias 'org-reduce 'cl-reduce "Org 9.0")
+(define-obsolete-function-alias 'org-remove-if 'cl-remove-if "Org 9.0")
+(define-obsolete-function-alias 'org-remove-if-not 'cl-remove-if-not "Org 9.0")
+(define-obsolete-function-alias 'org-some 'cl-some "Org 9.0")
+(define-obsolete-function-alias 'org-floor* 'cl-floor "Org 9.0")
+
+(defun org-sublist (list start end)
+  "Return a section of LIST, from START to END.
+Counting starts at 1."
+  (cl-subseq list (1- start) end))
+(make-obsolete 'org-sublist
+              "use cl-subseq (note the 0-based counting)."
+              "Org 9.0")
+
+
+;;;; Functions available since Emacs 24.3
+(define-obsolete-function-alias 'org-buffer-narrowed-p 'buffer-narrowed-p "Org 
9.0")
+(define-obsolete-function-alias 'org-called-interactively-p 
'called-interactively-p "Org 9.0")
+(define-obsolete-function-alias 'org-char-to-string 'char-to-string "Org 9.0")
+(define-obsolete-function-alias 'org-delete-directory 'delete-directory "Org 
9.0")
+(define-obsolete-function-alias 'org-format-seconds 'format-seconds "Org 9.0")
+(define-obsolete-function-alias 'org-link-escape-browser 'url-encode-url "Org 
9.0")
+(define-obsolete-function-alias 'org-no-warnings 'with-no-warnings "Org 9.0")
+(define-obsolete-function-alias 'org-number-sequence 'number-sequence "Org 
9.0")
+(define-obsolete-function-alias 'org-pop-to-buffer-same-window 
'pop-to-buffer-same-window "Org 9.0")
+(define-obsolete-function-alias 'org-string-match-p 'string-match-p "Org 9.0")
+
+;;;; Functions and variables from previous releases now obsolete.
+(define-obsolete-function-alias 'org-element-remove-indentation
+  'org-remove-indentation "Org 9.0")
+(define-obsolete-variable-alias 'org-hierarchical-checkbox-statistics
+  'org-checkbox-hierarchical-statistics "Org 8.0")
+(define-obsolete-variable-alias 'org-description-max-indent
+  'org-list-description-max-indent "Org 8.0")
+(define-obsolete-variable-alias 'org-latex-create-formula-image-program
+  'org-preview-latex-default-process "Org 9.0")
+(define-obsolete-variable-alias 'org-latex-preview-ltxpng-directory
+ 'org-preview-latex-image-directory "Org 9.0")
+(define-obsolete-function-alias 'org-table-p 'org-at-table-p "Org 9.0")
+(define-obsolete-function-alias 'org-on-heading-p 'org-at-heading-p "Org 9.0")
+(define-obsolete-function-alias 'org-at-regexp-p 'org-in-regexp "Org 8.3")
+(define-obsolete-function-alias 'org-speed-command-default-hook
+  'org-speed-command-activate "Org 8.0")
+(define-obsolete-function-alias 'org-babel-speed-command-hook
+  'org-babel-speed-command-activate "Org 8.0")
+(define-obsolete-function-alias 'org-image-file-name-regexp
+  'image-file-name-regexp "Org 9.0")
+(define-obsolete-function-alias 'org-get-legal-level
+  'org-get-valid-level "Org 7.8")
+(define-obsolete-function-alias 'org-completing-read-no-i
+  'completing-read "Org 9.0")
+(define-obsolete-function-alias 'org-icompleting-read
+  'completing-read "Org 9.0")
+(define-obsolete-function-alias 'org-iread-file-name 'read-file-name "Org 9.0")
+(define-obsolete-function-alias 'org-days-to-time
+  'org-time-stamp-to-now "Org 8.2")
+(define-obsolete-variable-alias 'org-agenda-ignore-drawer-properties
+  'org-agenda-ignore-properties "Org 9.0")
+(define-obsolete-function-alias 'org-preview-latex-fragment
+  'org-toggle-latex-fragment "Org 8.3")
+(define-obsolete-function-alias 'org-display-inline-modification-hook
+  'org-display-inline-remove-overlay "Org 8.0")
+(define-obsolete-function-alias 'org-export-get-genealogy
+  'org-element-lineage "Org 9.0")
+(define-obsolete-variable-alias 'org-latex-with-hyperref
+  'org-latex-hyperref-template "Org 9.0")
+(define-obsolete-variable-alias 'org-link-to-org-use-id
+  'org-id-link-to-org-use-id "Org 8.0")
+(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "Org 
9.0")
+(define-obsolete-variable-alias 'org-clock-modeline-total
+  'org-clock-mode-line-total "Org 8.0")
+(define-obsolete-function-alias 'org-protocol-unhex-compound
+  'org-link-unescape-compound "Org 7.8")
+(define-obsolete-function-alias 'org-protocol-unhex-string
+  'org-link-unescape "Org 7.8")
+(define-obsolete-function-alias 'org-protocol-unhex-single-byte-sequence
+  'org-link-unescape-single-byte-sequence "Org 7.8")
+(define-obsolete-variable-alias 'org-export-htmlized-org-css-url
+  'org-org-htmlized-css-url "Org 8.2")
+(define-obsolete-variable-alias 'org-alphabetical-lists
+  'org-list-allow-alphabetical "Org 8.0")
+(define-obsolete-function-alias 'org-list-parse-list 'org-list-to-lisp "Org 
9.0")
+(define-obsolete-variable-alias 'org-agenda-menu-two-column
+  'org-agenda-menu-two-columns "Org 8.0")
+(define-obsolete-variable-alias 'org-finalize-agenda-hook
+  'org-agenda-finalize-hook "Org 8.0")
+(make-obsolete-variable 'org-agenda-ndays 'org-agenda-span "Org 7.8")
+(define-obsolete-function-alias 'org-agenda-post-command-hook
+  'org-agenda-update-agenda-type "Org 8.0")
+(define-obsolete-function-alias 'org-agenda-todayp
+  'org-agenda-today-p "Org 9.0")
+(define-obsolete-function-alias 'org-babel-examplize-region
+  'org-babel-examplify-region "Org 9.0")
+(define-obsolete-function-alias 'org-babel-trim 'org-trim "Org 9.0")
+(define-obsolete-variable-alias 'org-html-style-include-scripts
+  'org-html-head-include-scripts "Org 8.0")
+(define-obsolete-variable-alias 'org-html-style-include-default
+  'org-html-head-include-default-style "Org 8.0")
+(define-obsolete-variable-alias 'org-html-style 'org-html-head "24.4")
+(define-obsolete-function-alias 'org-insert-columns-dblock
+  'org-columns-insert-dblock "Org 9.0")
+(define-obsolete-function-alias 'org-activate-bracket-links
+  'org-activate-links "Org 9.0")
+(define-obsolete-function-alias 'org-activate-plain-links 'ignore "Org 9.0")
+(define-obsolete-function-alias 'org-activate-angle-links 'ignore "Org 9.0")
+
+(defun org-in-fixed-width-region-p ()
+  "Non-nil if point in a fixed-width region."
+  (save-match-data
+    (eq 'fixed-width (org-element-type (org-element-at-point)))))
+(make-obsolete 'org-in-fixed-width-region-p
+              "use `org-element' library"
+              "Org 9.0")
+
+(defcustom org-read-date-minibuffer-setup-hook nil
+  "Hook to be used to set up keys for the date/time interface.
+Add key definitions to `minibuffer-local-map', which will be a
+temporary copy."
+  :group 'org-time
+  :type 'hook)
+(make-obsolete-variable
+ 'org-read-date-minibuffer-setup-hook
+ "set `org-read-date-minibuffer-local-map' instead." "Org 8.0")
 
 (defun org-compatible-face (inherits specs)
   "Make a compatible face specification.
-If INHERITS is an existing face and if the Emacs version supports it,
-just inherit the face.  If INHERITS is set and the Emacs version does
-not support it, copy the face specification from the inheritance face.
-If INHERITS is not given and SPECS is, use SPECS to define the face.
-XEmacs and Emacs 21 do not know about the `min-colors' attribute.
-For them we convert a (min-colors 8) entry to a `tty' entry and move it
-to the top of the list.  The `min-colors' attribute will be removed from
-any other entries, and any resulting duplicates will be removed entirely."
-  (when (and inherits (facep inherits) (not specs))
-    (setq specs (or specs
-                   (get inherits 'saved-face)
-                   (get inherits 'face-defface-spec))))
-  (cond
-   ((and inherits (facep inherits)
-        (not (featurep 'xemacs))
-        (>= emacs-major-version 22)
-        ;; do not inherit outline faces before Emacs 23
-        (or (>= emacs-major-version 23)
-            (not (string-match "\\`outline-[0-9]+"
-                               (symbol-name inherits)))))
-    (list (list t :inherit inherits)))
-   ((or (featurep 'xemacs) (< emacs-major-version 22))
-    ;; These do not understand the `min-colors' attribute.
-    (let (r e a)
-      (while (setq e (pop specs))
-       (cond
-        ((memq (car e) '(t default)) (push e r))
-        ((setq a (member '(min-colors 8) (car e)))
-         (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
-                              (cdr e)))))
-        ((setq a (assq 'min-colors (car e)))
-         (setq e (cons (delq a (car e)) (cdr e)))
-         (or (assoc (car e) r) (push e r)))
-        (t (or (assoc (car e) r) (push e r)))))
-      (nreverse r)))
-   (t specs)))
-(put 'org-compatible-face 'lisp-indent-function 1)
+If INHERITS is an existing face and if the Emacs version supports
+it, just inherit the face.  If INHERITS is not given and SPECS
+is, use SPECS to define the face."
+  (declare (indent 1))
+  (if (facep inherits)
+      (list (list t :inherit inherits))
+    specs))
+(make-obsolete 'org-compatible-face "you can remove it." "Org 9.0")
+
+(defun org-add-link-type (type &optional follow export)
+  "Add a new TYPE link.
+FOLLOW and EXPORT are two functions.
+
+FOLLOW should take the link path as the single argument and do whatever
+is necessary to follow the link, for example find a file or display
+a mail message.
+
+EXPORT should format the link path for export to one of the export formats.
+It should be a function accepting three arguments:
+
+  path    the path of the link, the text after the prefix (like \"http:\")
+  desc    the description of the link, if any
+  format  the export format, a symbol like `html' or `latex' or `ascii'.
+
+The function may use the FORMAT information to return different values
+depending on the format.  The return value will be put literally into
+the exported file.  If the return value is nil, this means Org should
+do what it normally does with links which do not have EXPORT defined.
+
+Org mode has a built-in default for exporting links.  If you are happy with
+this default, there is no need to define an export function for the link
+type.  For a simple example of an export function, see `org-bbdb.el'.
+
+If TYPE already exists, update it with the arguments.
+See `org-link-parameters' for documentation on the other parameters."
+  (org-link-set-parameters type :follow follow :export export)
+  (message "Created %s link." type))
+
+(make-obsolete 'org-add-link-type "use `org-link-set-parameters' instead." 
"Org 9.0")
+
+(defun org-table-recognize-table.el ()
+  "If there is a table.el table nearby, recognize it and move into it."
+  (when (and org-table-tab-recognizes-table.el (org-at-table.el-p))
+    (beginning-of-line)
+    (unless (or (looking-at org-table-dataline-regexp)
+               (not (looking-at org-table1-hline-regexp)))
+      (forward-line)
+      (when (looking-at org-table-any-border-regexp)
+       (forward-line -2)))
+    (if (re-search-forward "|" (org-table-end t) t)
+       (progn
+         (require 'table)
+         (if (table--at-cell-p (point)) t
+           (message "recognizing table.el table...")
+           (table-recognize-table)
+           (message "recognizing table.el table...done")))
+      (error "This should not happen"))))
+
+;; Not used by Org core since commit 6d1e3082, Feb 2010.
+(make-obsolete 'org-table-recognize-table.el
+              "please notify the org mailing list if you use this function."
+              "Org 9.0")
+
+(define-obsolete-function-alias
+  'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string "Org 8.0")
+
+(defun org-remove-angle-brackets (s)
+  (org-unbracket-string "<" ">" s))
+(make-obsolete 'org-remove-angle-brackets 'org-unbracket-string "Org 9.0")
+
+(defun org-remove-double-quotes (s)
+  (org-unbracket-string "\"" "\"" s))
+(make-obsolete 'org-remove-double-quotes 'org-unbracket-string "Org 9.0")
+
+(define-obsolete-function-alias 'org-babel-number-p
+  'org-babel--string-to-number "Org 9.0")
+
+
+
+;;;; Obsolete link types
+
+(eval-after-load 'org
+  '(progn
+     (org-link-set-parameters "file+emacs") ;since Org 9.0
+     (org-link-set-parameters "file+sys"))) ;since Org 9.0
+
+
+
+;;; Miscellaneous functions
 
 (defun org-version-check (version feature level)
   (let* ((v1 (mapcar 'string-to-number (split-string version "[.]")))
@@ -108,110 +330,19 @@ any other entries, and any resulting duplicates will be 
removed entirely."
            t))
       t)))
 
-
-;;;; Emacs/XEmacs compatibility
-
-(eval-and-compile
-  (defun org-defvaralias (new-alias base-variable &optional docstring)
-    "Compatibility function for defvaralias.
-Don't do the aliasing when `defvaralias' is not bound."
-    (declare (indent 1))
-    (when (fboundp 'defvaralias)
-      (defvaralias new-alias base-variable docstring)))
-
-  (when (and (not (boundp 'user-emacs-directory))
-            (boundp 'user-init-directory))
-    (org-defvaralias 'user-emacs-directory 'user-init-directory)))
-
-(when (featurep 'xemacs)
-  (defadvice custom-handle-keyword
-    (around org-custom-handle-keyword
-           activate preactivate)
-    "Remove custom keywords not recognized to avoid producing an error."
-    (cond
-     ((eq (ad-get-arg 1) :package-version))
-     (t ad-do-it)))
-  (defadvice define-obsolete-variable-alias
-    (around org-define-obsolete-variable-alias
-           (obsolete-name current-name &optional when docstring)
-           activate preactivate)
-    "Declare arguments defined in later versions of Emacs."
-    ad-do-it)
-  (defadvice define-obsolete-function-alias
-    (around org-define-obsolete-function-alias
-           (obsolete-name current-name &optional when docstring)
-           activate preactivate)
-    "Declare arguments defined in later versions of Emacs."
-    ad-do-it)
-  (defvar customize-package-emacs-version-alist nil)
-  (defvar temporary-file-directory (temp-directory)))
-
-;; Keys
-(defconst org-xemacs-key-equivalents
-  '(([mouse-1] . [button1])
-    ([mouse-2] . [button2])
-    ([mouse-3] . [button3])
-    ([C-mouse-4] . [(control mouse-4)])
-    ([C-mouse-5] . [(control mouse-5)]))
-  "Translation alist for a couple of keys.")
-
-;; Overlay compatibility functions
-(defun org-detach-overlay (ovl)
-  (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
-(defun org-overlay-display (ovl text &optional face evap)
-  "Make overlay OVL display TEXT with face FACE."
-  (if (featurep 'xemacs)
-      (let ((gl (make-glyph text)))
-       (and face (set-glyph-face gl face))
-       (set-extent-property ovl 'invisible t)
-       (set-extent-property ovl 'end-glyph gl))
-    (overlay-put ovl 'display text)
-    (if face (overlay-put ovl 'face face))
-    (if evap (overlay-put ovl 'evaporate t))))
-(defun org-overlay-before-string (ovl text &optional face evap)
-  "Make overlay OVL display TEXT with face FACE."
-  (if (featurep 'xemacs)
-      (let ((gl (make-glyph text)))
-       (and face (set-glyph-face gl face))
-       (set-extent-property ovl 'begin-glyph gl))
-    (if face (org-add-props text nil 'face face))
-    (overlay-put ovl 'before-string text)
-    (if evap (overlay-put ovl 'evaporate t))))
-(defun org-find-overlays (prop &optional pos delete)
-  "Find all overlays specifying PROP at POS or point.
-If DELETE is non-nil, delete all those overlays."
-  (let ((overlays (overlays-at (or pos (point))))
-       ov found)
-    (while (setq ov (pop overlays))
-      (if (overlay-get ov prop)
-          (if delete (delete-overlay ov) (push ov found))))
-    found))
-
 (defun org-get-x-clipboard (value)
-  "Get the value of the x or Windows clipboard, compatible with XEmacs, and 
GNU Emacs 21."
-  (cond ((eq window-system 'x)
-        (let ((x (org-get-x-clipboard-compat value)))
-          (if x (org-no-properties x))))
+  "Get the value of the X or Windows clipboard."
+  (cond ((and (eq window-system 'x)
+             (fboundp 'gui-get-selection)) ;Silence byte-compiler.
+        (org-no-properties
+         (ignore-errors
+           (or (gui-get-selection value 'UTF8_STRING)
+               (gui-get-selection value 'COMPOUND_TEXT)
+               (gui-get-selection value 'STRING)
+               (gui-get-selection value 'TEXT)))))
        ((and (eq window-system 'w32) (fboundp 'w32-get-clipboard-data))
         (w32-get-clipboard-data))))
 
-(defsubst org-decompose-region (beg end)
-  "Decompose from BEG to END."
-  (if (featurep 'xemacs)
-      (let ((modified-p (buffer-modified-p))
-           (buffer-read-only nil))
-       (remove-text-properties beg end '(composition nil))
-       (set-buffer-modified-p modified-p))
-    (decompose-region beg end)))
-
-;; Miscellaneous functions
-
-(defun org-add-hook (hook function &optional append local)
-  "Add-hook, compatible with both Emacsen."
-  (if (and local (featurep 'xemacs))
-      (add-local-hook hook function append)
-    (add-hook hook function append local)))
-
 (defun org-add-props (string plist &rest props)
   "Add text properties to entire string, from beginning to end.
 PLIST may be a list of properties, PROPS are individual properties and values
@@ -238,66 +369,29 @@ ignored in this case."
         (shrink-window-if-larger-than-buffer window)))
   (or window (selected-window)))
 
-(defun org-number-sequence (from &optional to inc)
-  "Call `number-sequence' or emulate it."
-  (if (fboundp 'number-sequence)
-      (number-sequence from to inc)
-    (if (or (not to) (= from to))
-       (list from)
-      (or inc (setq inc 1))
-      (when (zerop inc) (error "The increment can not be zero"))
-      (let (seq (n 0) (next from))
-       (if (> inc 0)
-           (while (<= next to)
-             (setq seq (cons next seq)
-                   n (1+ n)
-                   next (+ from (* n inc))))
-         (while (>= next to)
-           (setq seq (cons next seq)
-                 n (1+ n)
-                 next (+ from (* n inc)))))
-       (nreverse seq)))))
-
 ;; `set-transient-map' is only in Emacs >= 24.4
 (defalias 'org-set-transient-map
   (if (fboundp 'set-transient-map)
       'set-transient-map
     'set-temporary-overlay-map))
 
-;; Region compatibility
+;;; Region compatibility
 
 (defvar org-ignore-region nil
   "Non-nil means temporarily disable the active region.")
 
 (defun org-region-active-p ()
-  "Is `transient-mark-mode' on and the region active?
-Works on both Emacs and XEmacs."
-  (if org-ignore-region
-      nil
-    (if (featurep 'xemacs)
-       (and zmacs-regions (region-active-p))
-      (if (fboundp 'use-region-p)
-         (use-region-p)
-       (and transient-mark-mode mark-active))))) ; Emacs 22 and before
+  "Non-nil when the region active.
+Unlike to `use-region-p', this function also checks
+`org-ignore-region'."
+  (and (not org-ignore-region) (use-region-p)))
 
 (defun org-cursor-to-region-beginning ()
   (when (and (org-region-active-p)
             (> (point) (region-beginning)))
     (exchange-point-and-mark)))
 
-;; Emacs 22 misses `activate-mark'
-(if (fboundp 'activate-mark)
-    (defalias 'org-activate-mark 'activate-mark)
-  (defun org-activate-mark ()
-    (when (mark t)
-      (setq mark-active t)
-      (when (and (boundp 'transient-mark-mode)
-                (not transient-mark-mode))
-       (set (make-local-variable 'transient-mark-mode) 'lambda))
-      (when (boundp 'zmacs-regions)
-       (setq zmacs-regions t)))))
-
-;; Invisibility compatibility
+;;; Invisibility compatibility
 
 (defun org-remove-from-invisibility-spec (arg)
   "Remove elements from `buffer-invisibility-spec'."
@@ -312,63 +406,14 @@ Works on both Emacs and XEmacs."
   (if (consp buffer-invisibility-spec)
       (member arg buffer-invisibility-spec)))
 
-(defmacro org-xemacs-without-invisibility (&rest body)
-  "Turn off extents with invisibility while executing BODY."
-  `(let ((ext-inv (extent-list nil (point-at-bol) (point-at-eol)
-                              'all-extents-closed-open 'invisible))
-        ext-inv-specs)
-     (dolist (ext ext-inv)
-       (when (extent-property ext 'invisible)
-        (add-to-list 'ext-inv-specs (list ext (extent-property
-                                               ext 'invisible)))
-        (set-extent-property ext 'invisible nil)))
-     ,@body
-     (dolist (ext-inv-spec ext-inv-specs)
-       (set-extent-property (car ext-inv-spec) 'invisible
-                           (cadr ext-inv-spec)))))
-(def-edebug-spec org-xemacs-without-invisibility (body))
-
-(defun org-indent-to-column (column &optional minimum buffer)
-  "Work around a bug with extents with invisibility in XEmacs."
-  (if (featurep 'xemacs)
-      (org-xemacs-without-invisibility (indent-to-column column minimum 
buffer))
-    (indent-to-column column minimum)))
-
-(defun org-indent-line-to (column)
-  "Work around a bug with extents with invisibility in XEmacs."
-  (if (featurep 'xemacs)
-      (org-xemacs-without-invisibility (indent-line-to column))
-    (indent-line-to column)))
-
-(defun org-move-to-column (column &optional force buffer)
+(defun org-move-to-column (column &optional force _buffer)
   "Move to column COLUMN.
-Pass COLUMN and FORCE to `move-to-column'.
-Pass BUFFER to the XEmacs version of `move-to-column'."
+Pass COLUMN and FORCE to `move-to-column'."
   (let ((buffer-invisibility-spec
-        (remove '(org-filtered) buffer-invisibility-spec)))
-    (if (featurep 'xemacs)
-       (org-xemacs-without-invisibility
-        (move-to-column column force buffer))
-      (move-to-column column force))))
-
-(defun org-get-x-clipboard-compat (value)
-  "Get the clipboard value on XEmacs or Emacs 21."
-  (cond ((featurep 'xemacs)
-        (org-no-warnings (get-selection-no-error value)))
-       ((fboundp 'x-get-selection)
-        (condition-case nil
-            (or (x-get-selection value 'UTF8_STRING)
-                (x-get-selection value 'COMPOUND_TEXT)
-                (x-get-selection value 'STRING)
-                (x-get-selection value 'TEXT))
-          (error nil)))))
-
-(defun org-propertize (string &rest properties)
-  (if (featurep 'xemacs)
-      (progn
-       (add-text-properties 0 (length string) properties string)
-       string)
-    (apply 'propertize string properties)))
+        (if (listp buffer-invisibility-spec)
+            (remove '(org-filtered) buffer-invisibility-spec)
+          buffer-invisibility-spec)))
+    (move-to-column column force)))
 
 (defmacro org-find-library-dir (library)
   `(file-name-directory (or (locate-library ,library) "")))
@@ -387,37 +432,20 @@ Pass BUFFER to the XEmacs version of `move-to-column'."
                          string)
   (apply 'kill-new string args))
 
-(defun org-select-frame-set-input-focus (frame)
-  "Select FRAME, raise it, and set input focus, if possible."
-  (cond ((featurep 'xemacs)
-        (if (fboundp 'select-frame-set-input-focus)
-            (select-frame-set-input-focus frame)
-          (raise-frame frame)
-          (select-frame frame)
-          (focus-frame frame)))
-       ;; `select-frame-set-input-focus' defined in Emacs 21 will not
-       ;; set the input focus.
-       ((>= emacs-major-version 22)
-        (select-frame-set-input-focus frame))
-       (t
-        (raise-frame frame)
-        (select-frame frame)
-        (cond ((memq window-system '(x ns mac))
-               (x-focus-frame frame))
-              ((eq window-system 'w32)
-               (w32-focus-frame frame)))
-        (when focus-follows-mouse
-          (set-mouse-position frame (1- (frame-width frame)) 0)))))
-
-(define-obsolete-function-alias 'org-float-time 'float-time "26.1")
-
-;; `user-error' is only available from 24.3 on
-(unless (fboundp 'user-error)
-  (defalias 'user-error 'error))
-
-;; ‘format-message’ is available only from 25 on
-(unless (fboundp 'format-message)
-  (defalias 'format-message 'format))
+;; `font-lock-ensure' is only available from 24.4.50 on
+(defalias 'org-font-lock-ensure
+  (if (fboundp 'font-lock-ensure)
+      #'font-lock-ensure
+    (lambda (&optional _beg _end)
+      (with-no-warnings (font-lock-fontify-buffer)))))
+
+;; `file-local-name' was added in Emacs 26.1.
+(defalias 'org-babel-local-file-name
+  (if (fboundp 'file-local-name)
+      'file-local-name
+    (lambda (file)
+      "Return the local name component of FILE."
+      (or (file-remote-p file 'localname) file))))
 
 (defmacro org-no-popups (&rest body)
   "Suppress popup windows.
@@ -429,93 +457,6 @@ effect, which variables to use depends on the Emacs 
version."
     `(let (pop-up-frames special-display-buffer-names special-display-regexps 
special-display-function)
        ,@body)))
 
-(if (fboundp 'string-match-p)
-    (defalias 'org-string-match-p 'string-match-p)
-  (defun org-string-match-p (regexp string &optional start)
-    (save-match-data
-      (funcall 'string-match regexp string start))))
-
-(if (fboundp 'looking-at-p)
-    (defalias 'org-looking-at-p 'looking-at-p)
-  (defun org-looking-at-p (&rest args)
-    (save-match-data
-      (apply 'looking-at args))))
-
-;; XEmacs does not have `looking-back'.
-(if (fboundp 'looking-back)
-    (defalias 'org-looking-back 'looking-back)
-  (defun org-looking-back (regexp &optional limit greedy)
-    "Return non-nil if text before point matches regular expression REGEXP.
-Like `looking-at' except matches before point, and is slower.
-LIMIT if non-nil speeds up the search by specifying a minimum
-starting position, to avoid checking matches that would start
-before LIMIT.
-
-If GREEDY is non-nil, extend the match backwards as far as
-possible, stopping when a single additional previous character
-cannot be part of a match for REGEXP.  When the match is
-extended, its starting position is allowed to occur before
-LIMIT."
-    (let ((start (point))
-         (pos
-          (save-excursion
-            (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t)
-                 (point)))))
-      (if (and greedy pos)
-         (save-restriction
-           (narrow-to-region (point-min) start)
-           (while (and (> pos (point-min))
-                       (save-excursion
-                         (goto-char pos)
-                         (backward-char 1)
-                         (looking-at (concat "\\(?:"  regexp "\\)\\'"))))
-             (setq pos (1- pos)))
-           (save-excursion
-             (goto-char pos)
-             (looking-at (concat "\\(?:"  regexp "\\)\\'")))))
-      (not (null pos)))))
-
-(defalias 'org-font-lock-ensure
-  (if (fboundp 'font-lock-ensure)
-      #'font-lock-ensure
-    (lambda (&optional _beg _end) (font-lock-fontify-buffer))))
-
-(defun org-floor* (x &optional y)
-  "Return a list of the floor of X and the fractional part of X.
-With two arguments, return floor and remainder of their quotient."
-  (let ((q (floor x y)))
-    (list q (- x (if y (* y q) q)))))
-
-;; `pop-to-buffer-same-window' has been introduced in Emacs 24.1.
-(defun org-pop-to-buffer-same-window
-  (&optional buffer-or-name norecord label)
-  "Pop to buffer specified by BUFFER-OR-NAME in the selected window."
-  (if (fboundp 'pop-to-buffer-same-window)
-      (funcall
-       'pop-to-buffer-same-window buffer-or-name norecord)
-    (funcall 'switch-to-buffer buffer-or-name norecord)))
-
-;; RECURSIVE has been introduced with Emacs 23.2.
-;; This is copying and adapted from `tramp-compat-delete-directory'
-(defun org-delete-directory (directory &optional recursive)
-  "Compatibility function for `delete-directory'."
-  (if (null recursive)
-      (delete-directory directory)
-    (condition-case nil
-       (funcall 'delete-directory directory recursive)
-      ;; This Emacs version does not support the RECURSIVE flag.  We
-      ;; use the implementation from Emacs 23.2.
-      (wrong-number-of-arguments
-       (setq directory (directory-file-name (expand-file-name directory)))
-       (if (not (file-symlink-p directory))
-          (mapc (lambda (file)
-                  (if (eq t (car (file-attributes file)))
-                      (org-delete-directory file recursive)
-                    (delete-file file)))
-                (directory-files
-                 directory 'full "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")))
-       (delete-directory directory)))))
-
 ;;;###autoload
 (defmacro org-check-version ()
   "Try very hard to provide sensible version strings."
@@ -534,29 +475,33 @@ With two arguments, return floor and remainder of their 
quotient."
           (defun org-release () "N/A")
           (defun org-git-version () "N/A !!check installation!!"))))))
 
-(defun org-file-equal-p (f1 f2)
-  "Return t if files F1 and F2 are the same.
-Implements `file-equal-p' for older emacsen and XEmacs."
-  (if (fboundp 'file-equal-p)
-      (file-equal-p f1 f2)
-    (let (f1-attr f2-attr)
-      (and (setq f1-attr (file-attributes (file-truename f1)))
-          (setq f2-attr (file-attributes (file-truename f2)))
-          (equal f1-attr f2-attr)))))
-
-;; `buffer-narrowed-p' is available for Emacs >=24.3
-(defun org-buffer-narrowed-p ()
-  "Compatibility function for `buffer-narrowed-p'."
-  (if (fboundp 'buffer-narrowed-p)
-      (buffer-narrowed-p)
-    (/= (- (point-max) (point-min)) (buffer-size))))
-
 (defmacro org-with-silent-modifications (&rest body)
   (if (fboundp 'with-silent-modifications)
       `(with-silent-modifications ,@body)
     `(org-unmodified ,@body)))
 (def-edebug-spec org-with-silent-modifications (body))
 
+;; Functions for Emacs < 24.4 compatibility
+(defun org-define-error (name message)
+  "Define NAME as a new error signal.
+MESSAGE is a string that will be output to the echo area if such
+an error is signaled without being caught by a `condition-case'.
+Implements `define-error' for older emacsen."
+  (if (fboundp 'define-error) (define-error name message)
+    (put name 'error-conditions
+        (copy-sequence (cons name (get 'error 'error-conditions))))))
+
+(unless (fboundp 'string-suffix-p)
+  ;; From Emacs subr.el.
+  (defun string-suffix-p (suffix string  &optional ignore-case)
+    "Return non-nil if SUFFIX is a suffix of STRING.
+If IGNORE-CASE is non-nil, the comparison is done without paying
+attention to case differences."
+    (let ((start-pos (- (length string) (length suffix))))
+      (and (>= start-pos 0)
+          (eq t (compare-strings suffix nil nil
+                                 string start-pos nil ignore-case))))))
+
 (provide 'org-compat)
 
 ;;; org-compat.el ends here
diff --git a/lisp/org/org-crypt.el b/lisp/org/org-crypt.el
index 36144e2..3c431e4 100644
--- a/lisp/org/org-crypt.el
+++ b/lisp/org/org-crypt.el
@@ -1,5 +1,4 @@
-;;; org-crypt.el --- Public key encryption for org-mode entries
-
+;;; org-crypt.el --- Public Key Encryption for Org Entries -*- 
lexical-binding: t; -*-
 ;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
 
 ;; Emacs Lisp Archive Entry
@@ -7,7 +6,7 @@
 ;; Keywords: org-mode
 ;; Author: John Wiegley <address@hidden>
 ;; Maintainer: Peter Jones <address@hidden>
-;; Description: Adds public key encryption to org-mode buffers
+;; Description: Adds public key encryption to Org buffers
 ;; URL: http://www.newartisans.com/software/emacs.html
 ;; Compatibility: Emacs22
 
@@ -104,10 +103,10 @@ t        : Disable auto-save-mode for the current buffer
 nil      : Leave auto-save-mode enabled.
            This may cause data to be written to disk unencrypted!
 
-'ask     : Ask user whether or not to disable auto-save-mode
+`ask'    : Ask user whether or not to disable auto-save-mode
            for the current buffer.
 
-'encrypt : Leave auto-save-mode enabled for the current buffer,
+`encrypt': Leave auto-save-mode enabled for the current buffer,
            but automatically re-encrypt all decrypted entries
            *before* auto-saving.
            NOTE: This only works for entries which have a tag
@@ -142,7 +141,7 @@ See `org-crypt-disable-auto-save'."
       (message "org-decrypt: Decrypting entry with auto-save-mode enabled.  
This may cause leakage."))
      ((eq org-crypt-disable-auto-save 'encrypt)
       (message "org-decrypt: Enabling re-encryption on auto-save.")
-      (org-add-hook 'auto-save-hook
+      (add-hook 'auto-save-hook
                    (lambda ()
                      (message "org-crypt: Re-encrypting all decrypted entries 
due to auto-save.")
                      (org-encrypt-entries))
@@ -164,96 +163,96 @@ See `org-crypt-disable-auto-save'."
   (if (and (string= crypt-key (get-text-property 0 'org-crypt-key str))
           (string= (sha1 str) (get-text-property 0 'org-crypt-checksum str)))
       (get-text-property 0 'org-crypt-text str)
-    (set (make-local-variable 'epg-context) (epg-make-context nil t t))
+    (setq-local epg-context (epg-make-context nil t t))
     (epg-encrypt-string epg-context str (epg-list-keys epg-context 
crypt-key))))
 
 (defun org-encrypt-entry ()
   "Encrypt the content of the current headline."
   (interactive)
   (require 'epg)
-  (save-excursion
-    (org-back-to-heading t)
-    (set (make-local-variable 'epg-context) (epg-make-context nil t t))
-    (let ((start-heading (point)))
-      (forward-line)
-      (when (not (looking-at "-----BEGIN PGP MESSAGE-----"))
-        (let ((folded (outline-invisible-p))
-              (crypt-key (org-crypt-key-for-heading))
-              (beg (point))
-              end encrypted-text)
-          (goto-char start-heading)
-          (org-end-of-subtree t t)
-          (org-back-over-empty-lines)
-          (setq end (point)
-                encrypted-text
-               (org-encrypt-string (buffer-substring beg end) crypt-key))
-          (delete-region beg end)
-          (insert encrypted-text)
-          (when folded
-            (goto-char start-heading)
-            (hide-subtree))
-          nil)))))
+  (org-with-wide-buffer
+   (org-back-to-heading t)
+   (setq-local epg-context (epg-make-context nil t t))
+   (let ((start-heading (point)))
+     (org-end-of-meta-data)
+     (unless (looking-at-p "-----BEGIN PGP MESSAGE-----")
+       (let ((folded (org-invisible-p))
+            (crypt-key (org-crypt-key-for-heading))
+            (beg (point)))
+        (goto-char start-heading)
+        (org-end-of-subtree t t)
+        (org-back-over-empty-lines)
+        (let ((contents (delete-and-extract-region beg (point))))
+          (condition-case err
+              (insert (org-encrypt-string contents crypt-key))
+            ;; If encryption failed, make sure to insert back entry
+            ;; contents in the buffer.
+            (error (insert contents) (error (nth 1 err)))))
+        (when folded
+          (goto-char start-heading)
+          (outline-hide-subtree))
+        nil)))))
 
 (defun org-decrypt-entry ()
   "Decrypt the content of the current headline."
   (interactive)
   (require 'epg)
   (unless (org-before-first-heading-p)
-    (save-excursion
-      (org-back-to-heading t)
-      (let ((heading-point (point))
-           (heading-was-invisible-p
-            (save-excursion
-              (outline-end-of-heading)
-              (outline-invisible-p))))
-       (forward-line)
-       (when (looking-at "-----BEGIN PGP MESSAGE-----")
-         (org-crypt-check-auto-save)
-          (set (make-local-variable 'epg-context) (epg-make-context nil t t))
-         (let* ((end (save-excursion
-                       (search-forward "-----END PGP MESSAGE-----")
-                       (forward-line)
-                       (point)))
-                (encrypted-text (buffer-substring-no-properties (point) end))
-                (decrypted-text
-                 (decode-coding-string
-                  (epg-decrypt-string
-                   epg-context
-                   encrypted-text)
-                  'utf-8)))
-           ;; Delete region starting just before point, because the
-           ;; outline property starts at the \n of the heading.
-           (delete-region (1- (point)) end)
-           ;; Store a checksum of the decrypted and the encrypted
-           ;; text value.  This allow reusing the same encrypted text
-           ;; if the text does not change, and therefore avoid a
-           ;; re-encryption process.
-           (insert "\n" (propertize decrypted-text
-                                    'org-crypt-checksum (sha1 decrypted-text)
-                                    'org-crypt-key (org-crypt-key-for-heading)
-                                    'org-crypt-text encrypted-text))
-           (when heading-was-invisible-p
-             (goto-char heading-point)
-             (org-flag-subtree t))
-           nil))))))
+    (org-with-wide-buffer
+     (org-back-to-heading t)
+     (let ((heading-point (point))
+          (heading-was-invisible-p
+           (save-excursion
+             (outline-end-of-heading)
+             (org-invisible-p))))
+       (org-end-of-meta-data)
+       (when (looking-at "-----BEGIN PGP MESSAGE-----")
+        (org-crypt-check-auto-save)
+        (setq-local epg-context (epg-make-context nil t t))
+        (let* ((end (save-excursion
+                      (search-forward "-----END PGP MESSAGE-----")
+                      (forward-line)
+                      (point)))
+               (encrypted-text (buffer-substring-no-properties (point) end))
+               (decrypted-text
+                (decode-coding-string
+                 (epg-decrypt-string
+                  epg-context
+                  encrypted-text)
+                 'utf-8)))
+          ;; Delete region starting just before point, because the
+          ;; outline property starts at the \n of the heading.
+          (delete-region (1- (point)) end)
+          ;; Store a checksum of the decrypted and the encrypted
+          ;; text value.  This allows reusing the same encrypted text
+          ;; if the text does not change, and therefore avoid a
+          ;; re-encryption process.
+          (insert "\n" (propertize decrypted-text
+                                   'org-crypt-checksum (sha1 decrypted-text)
+                                   'org-crypt-key (org-crypt-key-for-heading)
+                                   'org-crypt-text encrypted-text))
+          (when heading-was-invisible-p
+            (goto-char heading-point)
+            (org-flag-subtree t))
+          nil))))))
 
 (defun org-encrypt-entries ()
   "Encrypt all top-level entries in the current buffer."
   (interactive)
-  (let (todo-only)
+  (let ((org--matcher-tags-todo-only nil))
     (org-scan-tags
      'org-encrypt-entry
      (cdr (org-make-tags-matcher org-crypt-tag-matcher))
-     todo-only)))
+     org--matcher-tags-todo-only)))
 
 (defun org-decrypt-entries ()
   "Decrypt all entries in the current buffer."
   (interactive)
-  (let (todo-only)
+  (let ((org--matcher-tags-todo-only nil))
     (org-scan-tags
      'org-decrypt-entry
      (cdr (org-make-tags-matcher org-crypt-tag-matcher))
-     todo-only)))
+     org--matcher-tags-todo-only)))
 
 (defun org-at-encrypted-entry-p ()
   "Is the current entry encrypted?"
@@ -267,7 +266,7 @@ See `org-crypt-disable-auto-save'."
   "Add a hook to automatically encrypt entries before a file is saved to disk."
   (add-hook
    'org-mode-hook
-   (lambda () (org-add-hook 'before-save-hook 'org-encrypt-entries nil t))))
+   (lambda () (add-hook 'before-save-hook 'org-encrypt-entries nil t))))
 
 (add-hook 'org-reveal-start-hook 'org-decrypt-entry)
 
diff --git a/lisp/org/org-ctags.el b/lisp/org/org-ctags.el
index 1ecf674..98eb806 100644
--- a/lisp/org/org-ctags.el
+++ b/lisp/org/org-ctags.el
@@ -1,4 +1,4 @@
-;;; org-ctags.el - Integrate Emacs "tags" facility with org mode.
+;;; org-ctags.el - Integrate Emacs "tags" Facility with Org -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
 
@@ -26,20 +26,21 @@
 ;; Synopsis
 ;; ========
 ;;
-;; Allows org-mode to make use of the Emacs `etags' system.  Defines tag
-;; destinations in org-mode files as any text between <<double angled
-;; brackets>>. This allows the tags-generation program `exuberant ctags' to
-;; parse these files and create tag tables that record where these
-;; destinations are found.  Plain [[links]] in org mode files which do not have
-;; <<matching destinations>> within the same file will then be interpreted as
-;; links to these 'tagged' destinations, allowing seamless navigation between
-;; multiple org-mode files.  Topics can be created in any org mode file and
-;; will always be found by plain links from other files.  Other file types
-;; recognized by ctags (source code files, latex files, etc) will also be
-;; available as destinations for plain links, and similarly, org-mode links
-;; will be available as tags from source files.  Finally, the function
-;; `org-ctags-find-tag-interactive' lets you choose any known tag, using
-;; autocompletion, and quickly jump to it.
+;; Allows Org mode to make use of the Emacs `etags' system.  Defines
+;; tag destinations in Org files as any text between <<double angled
+;; brackets>>. This allows the tags-generation program `exuberant
+;; ctags' to parse these files and create tag tables that record where
+;; these destinations are found.  Plain [[links]] in org mode files
+;; which do not have <<matching destinations>> within the same file
+;; will then be interpreted as links to these 'tagged' destinations,
+;; allowing seamless navigation between multiple Org files.  Topics
+;; can be created in any org mode file and will always be found by
+;; plain links from other files.  Other file types recognized by ctags
+;; (source code files, latex files, etc) will also be available as
+;; destinations for plain links, and similarly, Org links will be
+;; available as tags from source files.  Finally, the function
+;; `org-ctags-find-tag-interactive' lets you choose any known tag,
+;; using autocompletion, and quickly jump to it.
 ;;
 ;; Installation
 ;; ============
@@ -110,8 +111,9 @@
 ;; Keeping the TAGS file up to date
 ;; ================================
 ;;
-;; Tags mode has no way of knowing that you have created new tags by typing in
-;; your org-mode buffer.  New tags make it into the TAGS file in 3 ways:
+;; Tags mode has no way of knowing that you have created new tags by
+;; typing in your Org buffer.  New tags make it into the TAGS file in
+;; 3 ways:
 ;;
 ;; 1. You re-run (org-ctags-create-tags "directory") to rebuild the file.
 ;; 2. You put the function `org-ctags-ask-rebuild-tags-file-then-find-tag' in
@@ -135,12 +137,8 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
-
 (require 'org)
 
-(declare-function org-pop-to-buffer-same-window "org-compat" (&optional 
buffer-or-name norecord label))
-
 (defgroup org-ctags nil
   "Options concerning use of ctags within org mode."
   :tag "Org-Ctags"
@@ -151,7 +149,7 @@
 
 (defvar org-ctags-tag-regexp "/<<([^>]+)>>/\\1/d,definition/"
   "Regexp expression used by ctags external program.
-The regexp matches tag destinations in org-mode files.
+The regexp matches tag destinations in Org files.
 Format is: /REGEXP/TAGNAME/FLAGS,TAGTYPE/
 See the ctags documentation for more information.")
 
@@ -210,8 +208,8 @@ The following patterns are replaced in the string:
 
 (defadvice visit-tags-table (after org-ctags-load-tag-list activate compile)
   (when (and org-ctags-enabled-p tags-file-name)
-    (set (make-local-variable 'org-ctags-tag-list)
-         (org-ctags-all-tags-in-current-tags-table))))
+    (setq-local org-ctags-tag-list
+               (org-ctags-all-tags-in-current-tags-table))))
 
 
 (defun org-ctags-enable ()
@@ -273,11 +271,6 @@ Return the list."
   (replace-regexp-in-string (regexp-quote search) replace string t t))
 
 
-(defun y-or-n-minibuffer (prompt)
-  (let ((use-dialog-box nil))
-    (y-or-n-p prompt)))
-
-
 ;;; Internal functions =======================================================
 
 
@@ -285,29 +278,28 @@ Return the list."
   "Visit or create a file called `NAME.org', and insert a new topic.
 The new topic will be titled NAME (or TITLE if supplied)."
   (interactive "sFile name: ")
-  (let ((filename (substitute-in-file-name (expand-file-name name))))
-    (condition-case v
-        (progn
-          (org-open-file name t)
-          (message "Opened file OK")
-          (goto-char (point-max))
-          (insert (org-ctags-string-search-and-replace
-                   "%t" (capitalize (or title name))
-                   org-ctags-new-topic-template))
-          (message "Inserted new file text OK")
-          (org-mode-restart))
-      (error (error "Error %S in org-ctags-open-file" v)))))
+  (condition-case v
+      (progn
+       (org-open-file name t)
+       (message "Opened file OK")
+       (goto-char (point-max))
+       (insert (org-ctags-string-search-and-replace
+                "%t" (capitalize (or title name))
+                org-ctags-new-topic-template))
+       (message "Inserted new file text OK")
+       (org-mode-restart))
+    (error (error "Error %S in org-ctags-open-file" v))))
 
 
 ;;;; Misc interoperability with etags system =================================
 
 
-(defadvice find-tag (before org-ctags-set-org-mark-before-finding-tag
-                           activate compile)
+(defadvice xref-find-definitions
+    (before org-ctags-set-org-mark-before-finding-tag activate compile)
   "Before trying to find a tag, save our current position on org mark ring."
   (save-excursion
-    (if (and (derived-mode-p 'org-mode) org-ctags-enabled-p)
-        (org-mark-ring-push))))
+    (when (and (derived-mode-p 'org-mode) org-ctags-enabled-p)
+      (org-mark-ring-push))))
 
 
 
@@ -359,7 +351,7 @@ visit the file and location where the tag is found."
         (old-pnt (point-marker))
         (old-mark (copy-marker (mark-marker))))
     (condition-case nil
-        (progn (find-tag name)
+        (progn (xref-find-definitions name)
                t)
       (error
        ;; only restore old location if find-tag raises error
@@ -386,7 +378,7 @@ the new file."
     (cond
      ((get-buffer (concat name ".org"))
       ;; Buffer is already open
-      (org-pop-to-buffer-same-window (get-buffer (concat name ".org"))))
+      (pop-to-buffer-same-window (get-buffer (concat name ".org"))))
      ((file-exists-p filename)
       ;; File exists but is not open --> open it
       (message "Opening existing org file `%S'..."
@@ -421,7 +413,6 @@ the heading a destination for the tag `NAME'."
   (insert (org-ctags-string-search-and-replace
            "%t" (capitalize name) org-ctags-new-topic-template))
   (backward-char 4)
-  (org-update-radio-target-regexp)
   (end-of-line)
   (forward-line 2)
   (when narrowp
@@ -464,10 +455,10 @@ Wrapper for org-ctags-rebuild-tags-file-then-find-tag."
     nil))
 
 
-(defun org-ctags-fail-silently (name)
+(defun org-ctags-fail-silently (_name)
   "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS.
-Put as the last function in the list if you want to prevent org's default
-behavior of free text search."
+Put as the last function in the list if you want to prevent Org's
+default behavior of free text search."
   t)
 
 
@@ -484,7 +475,7 @@ end up in one file, called TAGS, located in the directory.  
This
 function may take several seconds to finish if the directory or
 its subdirectories contain large numbers of taggable files."
   (interactive)
-  (assert (buffer-file-name))
+  (cl-assert (buffer-file-name))
   (let ((dir-name (or directory-name
                       (file-name-directory (buffer-file-name))))
         (exitcode nil))
@@ -499,8 +490,8 @@ its subdirectories contain large numbers of taggable files."
                      (expand-file-name (concat dir-name "/*")))))
       (cond
        ((eql 0 exitcode)
-        (set (make-local-variable 'org-ctags-tag-list)
-             (org-ctags-all-tags-in-current-tags-table)))
+        (setq-local org-ctags-tag-list
+                   (org-ctags-all-tags-in-current-tags-table)))
        (t
         ;; This seems to behave differently on Linux, so just ignore
         ;; error codes for now
@@ -528,7 +519,7 @@ a new topic."
        ((member tag org-ctags-tag-list)
         ;; Existing tag
         (push tag org-ctags-find-tag-history)
-        (find-tag tag))
+        (xref-find-definitions tag))
        (t
         ;; New tag
         (run-hook-with-args-until-success
diff --git a/lisp/org/org-datetree.el b/lisp/org/org-datetree.el
index 891e64f..540753d 100644
--- a/lisp/org/org-datetree.el
+++ b/lisp/org/org-datetree.el
@@ -1,4 +1,4 @@
-;;; org-datetree.el --- Create date entries in a tree
+;;; org-datetree.el --- Create date entries in a tree -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -34,12 +34,14 @@
 
 (defvar org-datetree-base-level 1
   "The level at which years should be placed in the date tree.
-This is normally one, but if the buffer has an entry with a DATE_TREE
-property (any value), the date tree will become a subtree under that entry,
-so the base level will be properly adjusted.")
+This is normally one, but if the buffer has an entry with a
+DATE_TREE (or WEEK_TREE for ISO week entries) property (any
+value), the date tree will become a subtree under that entry, so
+the base level will be properly adjusted.")
 
 (defcustom org-datetree-add-timestamp nil
-  "When non-nil, add a time stamp when create a datetree entry."
+  "When non-nil, add a time stamp matching date of entry.
+Added time stamp is active unless value is `inactive'."
   :group 'org-capture
   :version "24.3"
   :type '(choice
@@ -48,115 +50,129 @@ so the base level will be properly adjusted.")
          (const :tag "Add an active time stamp" active)))
 
 ;;;###autoload
-(defun org-datetree-find-date-create (date &optional keep-restriction)
-  "Find or create an entry for DATE.
+(defun org-datetree-find-date-create (d &optional keep-restriction)
+  "Find or create an entry for date D.
 If KEEP-RESTRICTION is non-nil, do not widen the buffer.
 When it is nil, the buffer will be widened to make sure an existing date
 tree can be found."
-  (let ((year (nth 2 date))
-       (month (car date))
-       (day (nth 1 date)))
-    (org-set-local 'org-datetree-base-level 1)
-    (or keep-restriction (widen))
+  (setq-local org-datetree-base-level 1)
+  (or keep-restriction (widen))
+  (save-restriction
+    (let ((prop (org-find-property "DATE_TREE")))
+      (when prop
+       (goto-char prop)
+       (setq-local org-datetree-base-level
+                   (org-get-valid-level (org-current-level) 1))
+       (org-narrow-to-subtree)))
     (goto-char (point-min))
-    (save-restriction
-      (when (re-search-forward "^[ \t]*:DATE_TREE:[ \t]+\\S-" nil t)
-       (org-back-to-heading t)
-       (org-set-local 'org-datetree-base-level
-                      (org-get-valid-level (funcall outline-level) 1))
-       (org-narrow-to-subtree))
-      (goto-char (point-min))
-      (org-datetree-find-year-create year)
-      (org-datetree-find-month-create year month)
-      (org-datetree-find-day-create year month day)
-      (goto-char (prog1 (point) (widen))))))
-
-(defun org-datetree-find-year-create (year)
-  "Find the YEAR datetree or create it."
-  (let ((re "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\\([ 
\t]:[[:alnum:]:address@hidden:\\)?\\s-*$\\)")
-       match)
-    (goto-char (point-min))
-    (while (and (setq match (re-search-forward re nil t))
-               (goto-char (match-beginning 1))
-               (< (string-to-number (match-string 1)) year)))
-    (cond
-     ((not match)
-      (goto-char (point-max))
-      (or (bolp) (newline))
-      (org-datetree-insert-line year))
-     ((= (string-to-number (match-string 1)) year)
-      (goto-char (point-at-bol)))
-     (t
-      (beginning-of-line 1)
-      (org-datetree-insert-line year)))))
+    (let ((year (calendar-extract-year d))
+         (month (calendar-extract-month d))
+         (day (calendar-extract-day d)))
+      (org-datetree--find-create
+       "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\
+\\([ \t]:[[:alnum:]:address@hidden:\\)?\\s-*$\\)"
+       year)
+      (org-datetree--find-create
+       "^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$"
+       year month)
+      (org-datetree--find-create
+       "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$"
+       year month day))))
 
-(defun org-datetree-find-month-create (year month)
-  "Find the datetree for YEAR and MONTH or create it."
-  (org-narrow-to-subtree)
-  (let ((re (format "^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$" year))
-       match)
+;;;###autoload
+(defun org-datetree-find-iso-week-create (d &optional keep-restriction)
+  "Find or create an ISO week entry for date D.
+Compared to `org-datetree-find-date-create' this function creates
+entries ordered by week instead of months.
+If KEEP-RESTRICTION is non-nil, do not widen the buffer.  When it
+is nil, the buffer will be widened to make sure an existing date
+tree can be found."
+  (setq-local org-datetree-base-level 1)
+  (or keep-restriction (widen))
+  (save-restriction
+    (let ((prop (org-find-property "WEEK_TREE")))
+      (when prop
+       (goto-char prop)
+       (setq-local org-datetree-base-level
+                   (org-get-valid-level (org-current-level) 1))
+       (org-narrow-to-subtree)))
     (goto-char (point-min))
-    (while (and (setq match (re-search-forward re nil t))
-               (goto-char (match-beginning 1))
-               (< (string-to-number (match-string 1)) month)))
-    (cond
-     ((not match)
-      (goto-char (point-max))
-      (or (bolp) (newline))
-      (org-datetree-insert-line year month))
-     ((= (string-to-number (match-string 1)) month)
-      (goto-char (point-at-bol)))
-     (t
-      (beginning-of-line 1)
-      (org-datetree-insert-line year month)))))
-
-(defun org-datetree-find-day-create (year month day)
-  "Find the datetree for YEAR, MONTH and DAY or create it."
-  (org-narrow-to-subtree)
-  (let ((re (format "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$" year month))
+    (require 'cal-iso)
+    (let* ((year (calendar-extract-year d))
+          (month (calendar-extract-month d))
+          (day (calendar-extract-day d))
+          (time (encode-time 0 0 0 day month year))
+          (iso-date (calendar-iso-from-absolute
+                     (calendar-absolute-from-gregorian d)))
+          (weekyear (nth 2 iso-date))
+          (week (nth 0 iso-date)))
+      ;; ISO 8601 week format is %G-W%V(-%u)
+      (org-datetree--find-create
+       "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\
+\\([ \t]:[[:alnum:]:address@hidden:\\)?\\s-*$\\)"
+       weekyear nil nil
+       (format-time-string "%G" time))
+      (org-datetree--find-create
+       "^\\*+[ \t]+%d-W\\([0-5][0-9]\\)$"
+       weekyear week nil
+       (format-time-string "%G-W%V" time))
+      ;; For the actual day we use the regular date instead of ISO week.
+      (org-datetree--find-create
+       "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$"
+       year month day))))
+
+(defun org-datetree--find-create (regex year &optional month day insert)
+  "Find the datetree matched by REGEX for YEAR, MONTH, or DAY.
+REGEX is passed to `format' with YEAR, MONTH, and DAY as
+arguments.  Match group 1 is compared against the specified date
+component.  If INSERT is non-nil and there is no match then it is
+inserted into the buffer."
+  (when (or month day)
+    (org-narrow-to-subtree))
+  (let ((re (format regex year month day))
        match)
     (goto-char (point-min))
     (while (and (setq match (re-search-forward re nil t))
                (goto-char (match-beginning 1))
-               (< (string-to-number (match-string 1)) day)))
+               (< (string-to-number (match-string 1)) (or day month year))))
     (cond
      ((not match)
       (goto-char (point-max))
-      (or (bolp) (newline))
-      (org-datetree-insert-line year month day))
-     ((= (string-to-number (match-string 1)) day)
-      (goto-char (point-at-bol)))
+      (unless (bolp) (insert "\n"))
+      (org-datetree-insert-line year month day insert))
+     ((= (string-to-number (match-string 1)) (or day month year))
+      (beginning-of-line))
      (t
-      (beginning-of-line 1)
-      (org-datetree-insert-line year month day)))))
-
-(defun org-datetree-insert-line (year &optional month day)
-  (let ((pos (point)) ts-type)
-    (skip-chars-backward " \t\n")
-    (delete-region (point) pos)
-    (insert "\n" (make-string org-datetree-base-level ?*) " \n")
-    (backward-char 1)
-    (if month (org-do-demote))
-    (if day (org-do-demote))
+      (beginning-of-line)
+      (org-datetree-insert-line year month day insert)))))
+
+(defun org-datetree-insert-line (year &optional month day text)
+  (delete-region (save-excursion (skip-chars-backward " \t\n") (point)) 
(point))
+  (insert "\n" (make-string org-datetree-base-level ?*) " \n")
+  (backward-char)
+  (when month (org-do-demote))
+  (when day (org-do-demote))
+  (if text
+      (insert text)
     (insert (format "%d" year))
     (when month
-      (insert (format "-%02d" month))
-      (if day
-         (insert (format "-%02d %s"
-                         day (format-time-string
-                              "%A" (encode-time 0 0 0 day month year))))
-       (insert (format " %s"
-                       (format-time-string
-                        "%B" (encode-time 0 0 0 1 month year))))))
-    (when (and day (setq ts-type org-datetree-add-timestamp))
+      (insert
+       (if day
+          (format-time-string "-%m-%d %A" (encode-time 0 0 0 day month year))
+        (format-time-string "-%m %B" (encode-time 0 0 0 1 month year))))))
+  (when (and day org-datetree-add-timestamp)
+    (save-excursion
       (insert "\n")
       (org-indent-line)
-      (org-insert-time-stamp (encode-time 0 0 0 day month year) nil ts-type))
-    (beginning-of-line 1)))
-
-(defun org-datetree-file-entry-under (txt date)
-  "Insert a node TXT into the date tree under DATE."
-  (org-datetree-find-date-create date)
+      (org-insert-time-stamp
+       (encode-time 0 0 0 day month year)
+       nil
+       (eq org-datetree-add-timestamp 'inactive))))
+  (beginning-of-line))
+
+(defun org-datetree-file-entry-under (txt d)
+  "Insert a node TXT into the date tree under date D."
+  (org-datetree-find-date-create d)
   (let ((level (org-get-valid-level (funcall outline-level) 1)))
     (org-end-of-subtree t t)
     (org-back-over-empty-lines)
@@ -169,44 +185,42 @@ before running this command, even though the command 
tries to be smart."
   (interactive)
   (goto-char (point-min))
   (let ((dre (concat "\\<" org-deadline-string "\\>[ \t]*\\'"))
-       (sre (concat "\\<" org-scheduled-string "\\>[ \t]*\\'"))
-       dct ts tmp date year month day pos hdl-pos)
+       (sre (concat "\\<" org-scheduled-string "\\>[ \t]*\\'")))
     (while (re-search-forward org-ts-regexp nil t)
       (catch 'next
-       (setq ts (match-string 0))
-       (setq tmp (buffer-substring
-                  (max (point-at-bol) (- (match-beginning 0)
-                                         org-ds-keyword-length))
-                  (match-beginning 0)))
-       (if (or (string-match "-\\'" tmp)
-               (string-match dre tmp)
-               (string-match sre tmp))
+       (let ((tmp (buffer-substring
+                   (max (line-beginning-position)
+                        (- (match-beginning 0) org-ds-keyword-length))
+                   (match-beginning 0))))
+         (when (or (string-suffix-p "-" tmp)
+                   (string-match dre tmp)
+                   (string-match sre tmp))
            (throw 'next nil))
-       (setq dct (decode-time (org-time-string-to-time (match-string 0)))
-             date (list (nth 4 dct) (nth 3 dct) (nth 5 dct))
-             year (nth 2 date)
-             month (car date)
-             day (nth 1 date)
-             pos (point))
-       (org-back-to-heading t)
-       (setq hdl-pos (point))
-       (unless (org-up-heading-safe)
-         ;; No parent, we are not in a date tree
-         (goto-char pos)
-         (throw 'next nil))
-       (unless (looking-at "\\*+[ \t]+[0-9]+-[0-1][0-9]-[0-3][0-9]")
-         ;; Parent looks wrong, we are not in a date tree
-         (goto-char pos)
-         (throw 'next nil))
-       (when (looking-at (format "\\*+[ \t]+%d-%02d-%02d" year month day))
-         ;; At correct date already, do nothing
-         (progn (goto-char pos) (throw 'next nil)))
-       ;; OK, we need to refile this entry
-       (goto-char hdl-pos)
-       (org-cut-subtree)
-       (save-excursion
-         (save-restriction
-           (org-datetree-file-entry-under (current-kill 0) date)))))))
+         (let* ((dct (decode-time (org-time-string-to-time (match-string 0))))
+                (date (list (nth 4 dct) (nth 3 dct) (nth 5 dct)))
+                (year (nth 2 date))
+                (month (car date))
+                (day (nth 1 date))
+                (pos (point))
+                (hdl-pos (progn (org-back-to-heading t) (point))))
+           (unless (org-up-heading-safe)
+             ;; No parent, we are not in a date tree.
+             (goto-char pos)
+             (throw 'next nil))
+           (unless (looking-at "\\*+[ \t]+[0-9]+-[0-1][0-9]-[0-3][0-9]")
+             ;; Parent looks wrong, we are not in a date tree.
+             (goto-char pos)
+             (throw 'next nil))
+           (when (looking-at (format "\\*+[ \t]+%d-%02d-%02d" year month day))
+             ;; At correct date already, do nothing.
+             (goto-char pos)
+             (throw 'next nil))
+           ;; OK, we need to refile this entry.
+           (goto-char hdl-pos)
+           (org-cut-subtree)
+           (save-excursion
+             (save-restriction
+               (org-datetree-file-entry-under (current-kill 0) date)))))))))
 
 (provide 'org-datetree)
 
diff --git a/lisp/org/org-docview.el b/lisp/org/org-docview.el
index c5d0115..dfad893 100644
--- a/lisp/org/org-docview.el
+++ b/lisp/org/org-docview.el
@@ -1,4 +1,4 @@
-;;; org-docview.el --- support for links to doc-view-mode buffers
+;;; org-docview.el --- Support for links to doc-view-mode buffers -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -25,7 +25,7 @@
 ;;; Commentary:
 
 ;; This file implements links to open files in doc-view-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;; The links take the form
@@ -49,13 +49,15 @@
 (declare-function doc-view-goto-page "doc-view" (page))
 (declare-function image-mode-window-get "image-mode" (prop &optional winprops))
 
-(org-add-link-type "docview" 'org-docview-open 'org-docview-export)
-(add-hook 'org-store-link-functions 'org-docview-store-link)
+(org-link-set-parameters "docview"
+                        :follow #'org-docview-open
+                        :export #'org-docview-export
+                        :store #'org-docview-store-link)
 
 (defun org-docview-export (link description format)
   "Export a docview link from Org files."
-  (let* ((path (when (string-match "\\(.+\\)::.+" link)
-                (match-string 1 link)))
+  (let* ((path (if (string-match "\\(.+\\)::.+" link) (match-string 1 link)
+                link))
          (desc (or description link)))
     (when (stringp path)
       (setq path (org-link-escape (expand-file-name path)))
@@ -66,13 +68,14 @@
        (t path)))))
 
 (defun org-docview-open (link)
-  (when (string-match "\\(.*\\)::\\([0-9]+\\)$"  link)
-    (let* ((path (match-string 1 link))
-          (page (string-to-number (match-string 2 link))))
-      (org-open-file path 1) ;; let org-mode open the file (in-emacs = 1)
-      ;; to ensure org-link-frame-setup is respected
-      (doc-view-goto-page page)
-      )))
+  (string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link)
+  (let ((path (match-string 1 link))
+       (page (and (match-beginning 2)
+                  (string-to-number (match-string 2 link)))))
+    ;; Let Org mode open the file (in-emacs = 1) to ensure
+    ;; org-link-frame-setup is respected.
+    (org-open-file path 1)
+    (when page (doc-view-goto-page page))))
 
 (defun org-docview-store-link ()
   "Store a link to a docview buffer."
@@ -80,8 +83,7 @@
     ;; This buffer is in doc-view-mode
     (let* ((path buffer-file-name)
           (page (image-mode-window-get 'page))
-          (link (concat "docview:" path "::" (number-to-string page)))
-          (description ""))
+          (link (concat "docview:" path "::" (number-to-string page))))
       (org-store-link-props
        :type "docview"
        :link link
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index e9731c1..41b4a3a 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -1,4 +1,4 @@
-;;; org-element.el --- Parser And Applications for Org syntax
+;;; org-element.el --- Parser for Org Syntax         -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -22,80 +22,21 @@
 
 ;;; Commentary:
 ;;
-;; Org syntax can be divided into three categories: "Greater
-;; elements", "Elements" and "Objects".
+;; See <http://orgmode.org/worg/dev/org-syntax.html> for details about
+;; Org syntax.
 ;;
-;; Elements are related to the structure of the document.  Indeed, all
-;; elements are a cover for the document: each position within belongs
-;; to at least one element.
-;;
-;; An element always starts and ends at the beginning of a line.  With
-;; a few exceptions (`clock', `headline', `inlinetask', `item',
-;; `planning', `node-property', `quote-section' `section' and
-;; `table-row' types), it can also accept a fixed set of keywords as
-;; attributes.  Those are called "affiliated keywords" to distinguish
-;; them from other keywords, which are full-fledged elements.  Almost
-;; all affiliated keywords are referenced in
-;; `org-element-affiliated-keywords'; the others are export attributes
-;; and start with "ATTR_" prefix.
-;;
-;; Element containing other elements (and only elements) are called
-;; greater elements.  Concerned types are: `center-block', `drawer',
-;; `dynamic-block', `footnote-definition', `headline', `inlinetask',
-;; `item', `plain-list', `property-drawer', `quote-block', `section'
-;; and `special-block'.
-;;
-;; Other element types are: `babel-call', `clock', `comment',
-;; `comment-block', `diary-sexp', `example-block', `export-block',
-;; `fixed-width', `horizontal-rule', `keyword', `latex-environment',
-;; `node-property', `paragraph', `planning', `quote-section',
-;; `src-block', `table', `table-row' and `verse-block'.  Among them,
-;; `paragraph' and `verse-block' types can contain Org objects and
-;; plain text.
-;;
-;; Objects are related to document's contents.  Some of them are
-;; recursive.  Associated types are of the following: `bold', `code',
-;; `entity', `export-snippet', `footnote-reference',
-;; `inline-babel-call', `inline-src-block', `italic',
-;; `latex-fragment', `line-break', `link', `macro', `radio-target',
-;; `statistics-cookie', `strike-through', `subscript', `superscript',
-;; `table-cell', `target', `timestamp', `underline' and `verbatim'.
-;;
-;; Some elements also have special properties whose value can hold
-;; objects themselves (e.g. an item tag or a headline name).  Such
-;; values are called "secondary strings".  Any object belongs to
-;; either an element or a secondary string.
-;;
-;; Notwithstanding affiliated keywords, each greater element, element
-;; and object has a fixed set of properties attached to it.  Among
-;; them, four are shared by all types: `:begin' and `:end', which
-;; refer to the beginning and ending buffer positions of the
-;; considered element or object, `:post-blank', which holds the number
-;; of blank lines, or white spaces, at its end and `:parent' which
-;; refers to the element or object containing it.  Greater elements,
-;; elements and objects containing objects will also have
-;; `:contents-begin' and `:contents-end' properties to delimit
-;; contents.  Eventually, greater elements and elements accepting
-;; affiliated keywords will have a `:post-affiliated' property,
-;; referring to the buffer position after all such keywords.
-;;
-;; At the lowest level, a `:parent' property is also attached to any
-;; string, as a text property.
-;;
-;; Lisp-wise, an element or an object can be represented as a list.
+;; Lisp-wise, a syntax object can be represented as a list.
 ;; It follows the pattern (TYPE PROPERTIES CONTENTS), where:
-;;   TYPE is a symbol describing the Org element or object.
+;;   TYPE is a symbol describing the object.
 ;;   PROPERTIES is the property list attached to it.  See docstring of
-;;              appropriate parsing function to get an exhaustive
-;;              list.
-;;   CONTENTS is a list of elements, objects or raw strings contained
-;;            in the current element or object, when applicable.
+;;              appropriate parsing function to get an exhaustive list.
+;;   CONTENTS is a list of syntax objects or raw strings contained
+;;            in the current object, when applicable.
 ;;
-;; An Org buffer is a nested list of such elements and objects, whose
-;; type is `org-data' and properties is nil.
+;; For the whole document, TYPE is `org-data' and PROPERTIES is nil.
 ;;
-;; The first part of this file defines Org syntax, while the second
-;; one provide accessors and setters functions.
+;; The first part of this file defines constants for the Org syntax,
+;; while the second one provide accessors and setters functions.
 ;;
 ;; The next part implements a parser and an interpreter for each
 ;; element and object type in Org syntax.
@@ -111,13 +52,15 @@
 ;;
 ;; The library ends by furnishing `org-element-at-point' function, and
 ;; a way to give information about document structure around point
-;; with `org-element-context'.
+;; with `org-element-context'.  A cache mechanism is also provided for
+;; these functions.
 
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
 (require 'org)
+(require 'avl-tree)
+(require 'cl-lib)
 
 
 
@@ -127,56 +70,116 @@
 ;; along with the affiliated keywords recognized.  Also set up
 ;; restrictions on recursive objects combinations.
 ;;
-;; These variables really act as a control center for the parsing
-;; process.
-
-(defconst org-element-paragraph-separate
-  (concat "^\\(?:"
-          ;; Headlines, inlinetasks.
-          org-outline-regexp "\\|"
-          ;; Footnote definitions.
-         "\\[\\(?:[0-9]+\\|fn:[-_[:word:]]+\\)\\]" "\\|"
-         ;; Diary sexps.
-         "%%(" "\\|"
-          "[ \t]*\\(?:"
-          ;; Empty lines.
-          "$" "\\|"
-         ;; Tables (any type).
-         "\\(?:|\\|\\+-[-+]\\)" "\\|"
-          ;; Blocks (any type), Babel calls and keywords.  Note: this
-         ;; is only an indication and need some thorough check.
-          "#\\(?:[+ ]\\|$\\)" "\\|"
-         ;; Drawers (any type) and fixed-width areas.  This is also
-         ;; only an indication.
-         ":" "\\|"
-          ;; Horizontal rules.
-          "-\\{5,\\}[ \t]*$" "\\|"
-          ;; LaTeX environments.
-          "\\\\begin{\\([A-Za-z0-9]+\\*?\\)}" "\\|"
-          ;; Planning and Clock lines.
-          (regexp-opt (list org-scheduled-string
-                            org-deadline-string
-                            org-closed-string
-                            org-clock-string))
-          "\\|"
-          ;; Lists.
-          (let ((term (case org-plain-list-ordered-item-terminator
-                        (?\) ")") (?. "\\.") (otherwise "[.)]")))
-                (alpha (and org-list-allow-alphabetical "\\|[A-Za-z]")))
-            (concat "\\(?:[-+*]\\|\\(?:[0-9]+" alpha "\\)" term "\\)"
-                    "\\(?:[ \t]\\|$\\)"))
-          "\\)\\)")
+;; `org-element-update-syntax' builds proper syntax regexps according
+;; to current setup.
+
+(defvar org-element-paragraph-separate nil
   "Regexp to separate paragraphs in an Org buffer.
 In the case of lines starting with \"#\" and \":\", this regexp
 is not sufficient to know if point is at a paragraph ending.  See
 `org-element-paragraph-parser' for more information.")
 
+(defvar org-element--object-regexp nil
+  "Regexp possibly matching the beginning of an object.
+This regexp allows false positives.  Dedicated parser (e.g.,
+`org-export-bold-parser') will take care of further filtering.
+Radio links are not matched by this regexp, as they are treated
+specially in `org-element--object-lex'.")
+
+(defun org-element--set-regexps ()
+  "Build variable syntax regexps."
+  (setq org-element-paragraph-separate
+       (concat "^\\(?:"
+               ;; Headlines, inlinetasks.
+               org-outline-regexp "\\|"
+               ;; Footnote definitions.
+               "\\[fn:[-_[:word:]]+\\]" "\\|"
+               ;; Diary sexps.
+               "%%(" "\\|"
+               "[ \t]*\\(?:"
+               ;; Empty lines.
+               "$" "\\|"
+               ;; Tables (any type).
+               "|" "\\|"
+               "\\+\\(?:-+\\+\\)+[ \t]*$" "\\|"
+               ;; Comments, keyword-like or block-like constructs.
+               ;; Blocks and keywords with dual values need to be
+               ;; double-checked.
+               "#\\(?: \\|$\\|\\+\\(?:"
+               "BEGIN_\\S-+" "\\|"
+               "\\S-+\\(?:\\[.*\\]\\)?:[ \t]*\\)\\)"
+               "\\|"
+               ;; Drawers (any type) and fixed-width areas.  Drawers
+               ;; need to be double-checked.
+               ":\\(?: \\|$\\|[-_[:word:]]+:[ \t]*$\\)" "\\|"
+               ;; Horizontal rules.
+               "-\\{5,\\}[ \t]*$" "\\|"
+               ;; LaTeX environments.
+               "\\\\begin{\\([A-Za-z0-9*]+\\)}" "\\|"
+               ;; Clock lines.
+               (regexp-quote org-clock-string) "\\|"
+               ;; Lists.
+               (let ((term (pcase org-plain-list-ordered-item-terminator
+                             (?\) ")") (?. "\\.") (_ "[.)]")))
+                     (alpha (and org-list-allow-alphabetical "\\|[A-Za-z]")))
+                 (concat "\\(?:[-+*]\\|\\(?:[0-9]+" alpha "\\)" term "\\)"
+                         "\\(?:[ \t]\\|$\\)"))
+               "\\)\\)")
+       org-element--object-regexp
+       (mapconcat #'identity
+                  (let ((link-types (regexp-opt (org-link-types))))
+                    (list
+                     ;; Sub/superscript.
+                     "\\(?:[_^][-{(*+.,[:alnum:]]\\)"
+                     ;; Bold, code, italic, strike-through, underline
+                     ;; and verbatim.
+                     (concat "[*~=+_/]"
+                             (format "[^%s]"
+                                     (nth 2 org-emphasis-regexp-components)))
+                     ;; Plain links.
+                     (concat "\\<" link-types ":")
+                     ;; Objects starting with "[": regular link,
+                     ;; footnote reference, statistics cookie,
+                     ;; timestamp (inactive).
+                     (concat "\\[\\(?:"
+                             "fn:" "\\|"
+                             "\\[" "\\|"
+                             "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" "\\|"
+                             "[0-9]*\\(?:%\\|/[0-9]*\\)\\]"
+                             "\\)")
+                     ;; Objects starting with "@": export snippets.
+                     "@@"
+                     ;; Objects starting with "{": macro.
+                     "{{{"
+                     ;; Objects starting with "<" : timestamp
+                     ;; (active, diary), target, radio target and
+                     ;; angular links.
+                     (concat "<\\(?:%%\\|<\\|[0-9]\\|" link-types "\\)")
+                     ;; Objects starting with "$": latex fragment.
+                     "\\$"
+                     ;; Objects starting with "\": line break,
+                     ;; entity, latex fragment.
+                     "\\\\\\(?:[a-zA-Z[(]\\|\\\\[ \t]*$\\|_ +\\)"
+                     ;; Objects starting with raw text: inline Babel
+                     ;; source block, inline Babel call.
+                     "\\(?:call\\|src\\)_"))
+                  "\\|")))
+
+(org-element--set-regexps)
+
+;;;###autoload
+(defun org-element-update-syntax ()
+  "Update parser internals."
+  (interactive)
+  (org-element--set-regexps)
+  (org-element-cache-reset 'all))
+
 (defconst org-element-all-elements
   '(babel-call center-block clock comment comment-block diary-sexp drawer
               dynamic-block example-block export-block fixed-width
               footnote-definition headline horizontal-rule inlinetask item
               keyword latex-environment node-property paragraph plain-list
-              planning property-drawer quote-block quote-section section
+              planning property-drawer quote-block section
               special-block src-block table table-row verse-block)
   "Complete list of element types.")
 
@@ -186,23 +189,6 @@ is not sufficient to know if point is at a paragraph 
ending.  See
                 special-block table)
   "List of recursive element types aka Greater Elements.")
 
-(defconst org-element-all-successors
-  '(link export-snippet footnote-reference inline-babel-call
-        inline-src-block latex-or-entity line-break macro plain-link
-        radio-target statistics-cookie sub/superscript table-cell target
-        text-markup timestamp)
-  "Complete list of successors.")
-
-(defconst org-element-object-successor-alist
-  '((subscript . sub/superscript) (superscript . sub/superscript)
-    (bold . text-markup) (code . text-markup) (italic . text-markup)
-    (strike-through . text-markup) (underline . text-markup)
-    (verbatim . text-markup) (entity . latex-or-entity)
-    (latex-fragment . latex-or-entity))
-  "Alist of translations between object type and successor name.
-Sharing the same successor comes handy when, for example, the
-regexp matching one object can also match the other object.")
-
 (defconst org-element-all-objects
   '(bold code entity export-snippet footnote-reference inline-babel-call
         inline-src-block italic line-break latex-fragment link macro
@@ -211,26 +197,13 @@ regexp matching one object can also match the other 
object.")
   "Complete list of object types.")
 
 (defconst org-element-recursive-objects
-  '(bold italic link subscript radio-target strike-through superscript
-        table-cell underline)
+  '(bold footnote-reference italic link subscript radio-target strike-through
+        superscript table-cell underline)
   "List of recursive object types.")
 
-(defvar org-element-block-name-alist
-  '(("CENTER" . org-element-center-block-parser)
-    ("COMMENT" . org-element-comment-block-parser)
-    ("EXAMPLE" . org-element-example-block-parser)
-    ("QUOTE" . org-element-quote-block-parser)
-    ("SRC" . org-element-src-block-parser)
-    ("VERSE" . org-element-verse-block-parser))
-  "Alist between block names and the associated parsing function.
-Names must be uppercase.  Any block whose name has no association
-is parsed with `org-element-special-block-parser'.")
-
-(defconst org-element-link-type-is-file
-  '("file" "file+emacs" "file+sys" "docview")
-  "List of link types equivalent to \"file\".
-Only these types can accept search options and an explicit
-application to open them.")
+(defconst org-element-object-containers
+  (append org-element-recursive-objects '(paragraph table-row verse-block))
+  "List of object or element types that can directly contain objects.")
 
 (defconst org-element-affiliated-keywords
   '("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" 
"RESULT"
@@ -268,6 +241,13 @@ strings and objects.
 This list is checked after translations have been applied.  See
 `org-element-keyword-translation-alist'.")
 
+(defconst org-element--parsed-properties-alist
+  (mapcar (lambda (k) (cons k (intern (concat ":" (downcase k)))))
+         org-element-parsed-keywords)
+  "Alist of parsed keywords and associated properties.
+This is generated from `org-element-parsed-keywords', which
+see.")
+
 (defconst org-element-dual-keywords '("CAPTION" "RESULTS")
   "List of affiliated keywords which can have a secondary value.
 
@@ -280,13 +260,8 @@ associated to a hash value with the following:
 This list is checked after translations have been applied.  See
 `org-element-keyword-translation-alist'.")
 
-(defconst org-element-document-properties '("AUTHOR" "DATE" "TITLE")
-  "List of properties associated to the whole document.
-Any keyword in this list will have its value parsed and stored as
-a secondary string.")
-
 (defconst org-element--affiliated-re
-  (format "[ \t]*#\\+\\(?:%s\\):\\(?: \\|$\\)"
+  (format "[ \t]*#\\+\\(?:%s\\):[ \t]*"
          (concat
           ;; Dual affiliated keywords.
           (format "\\(?1:%s\\)\\(?:\\[\\(.*\\)\\]\\)?"
@@ -295,9 +270,8 @@ a secondary string.")
           ;; Regular affiliated keywords.
           (format "\\(?1:%s\\)"
                   (regexp-opt
-                   (org-remove-if
-                    #'(lambda (keyword)
-                        (member keyword org-element-dual-keywords))
+                   (cl-remove-if
+                    (lambda (k) (member k org-element-dual-keywords))
                     org-element-affiliated-keywords)))
           "\\|"
           ;; Export attributes.
@@ -311,8 +285,7 @@ match group 2.
 Don't modify it, set `org-element-affiliated-keywords' instead.")
 
 (defconst org-element-object-restrictions
-  (let* ((standard-set
-         (remq 'plain-link (remq 'table-cell org-element-all-successors)))
+  (let* ((standard-set (remq 'table-cell org-element-all-objects))
         (standard-set-no-line-break (remq 'line-break standard-set)))
     `((bold ,@standard-set)
       (footnote-reference ,@standard-set)
@@ -320,30 +293,34 @@ Don't modify it, set `org-element-affiliated-keywords' 
instead.")
       (inlinetask ,@standard-set-no-line-break)
       (italic ,@standard-set)
       (item ,@standard-set-no-line-break)
-      (keyword ,@standard-set)
-      ;; Ignore all links excepted plain links in a link description.
-      ;; Also ignore radio-targets and line breaks.
-      (link export-snippet inline-babel-call inline-src-block latex-or-entity
-           macro plain-link statistics-cookie sub/superscript text-markup)
+      (keyword ,@(remq 'footnote-reference standard-set))
+      ;; Ignore all links excepted plain links and angular links in
+      ;; a link description.  Also ignore radio-targets and line
+      ;; breaks.
+      (link bold code entity export-snippet inline-babel-call inline-src-block
+           italic latex-fragment macro simple-link statistics-cookie
+           strike-through subscript superscript underline verbatim)
       (paragraph ,@standard-set)
       ;; Remove any variable object from radio target as it would
       ;; prevent it from being properly recognized.
-      (radio-target latex-or-entity sub/superscript text-markup)
+      (radio-target bold code entity italic latex-fragment strike-through
+                   subscript superscript underline superscript)
       (strike-through ,@standard-set)
       (subscript ,@standard-set)
       (superscript ,@standard-set)
       ;; Ignore inline babel call and inline src block as formulas are
       ;; possible.  Also ignore line breaks and statistics cookies.
-      (table-cell link export-snippet footnote-reference latex-or-entity macro
-                 radio-target sub/superscript target text-markup timestamp)
+      (table-cell bold code entity export-snippet footnote-reference italic
+                 latex-fragment link macro radio-target strike-through
+                 subscript superscript target timestamp underline verbatim)
       (table-row table-cell)
       (underline ,@standard-set)
       (verse-block ,@standard-set)))
   "Alist of objects restrictions.
 
-CAR is an element or object type containing objects and CDR is
-a list of successors that will be called within an element or
-object of such type.
+key is an element or object type containing objects and value is
+a list of types that can be contained within an element or object
+of such type.
 
 For example, in a `radio-target' object, one can only find
 entities, latex-fragments, subscript, superscript and text
@@ -354,12 +331,56 @@ This alist also applies to secondary string.  For 
example, an
 still has an entry since one of its properties (`:title') does.")
 
 (defconst org-element-secondary-value-alist
-  '((headline . :title)
-    (inlinetask . :title)
-    (item . :tag)
-    (footnote-reference . :inline-definition))
-  "Alist between element types and location of secondary value.")
-
+  '((headline :title)
+    (inlinetask :title)
+    (item :tag))
+  "Alist between element types and locations of secondary values.")
+
+(defconst org-element--pair-round-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\( "()" table)
+    (modify-syntax-entry ?\) ")(" table)
+    (dolist (char '(?\{ ?\} ?\[ ?\] ?\< ?\>) table)
+      (modify-syntax-entry char " " table)))
+  "Table used internally to pair only round brackets.
+Other brackets are treated as spaces.")
+
+(defconst org-element--pair-square-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\[ "(]" table)
+    (modify-syntax-entry ?\] ")[" table)
+    (dolist (char '(?\{ ?\} ?\( ?\) ?\< ?\>) table)
+      (modify-syntax-entry char " " table)))
+  "Table used internally to pair only square brackets.
+Other brackets are treated as spaces.")
+
+(defconst org-element--pair-curly-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\{ "(}" table)
+    (modify-syntax-entry ?\} "){" table)
+    (dolist (char '(?\[ ?\] ?\( ?\) ?\< ?\>) table)
+      (modify-syntax-entry char " " table)))
+  "Table used internally to pair only curly brackets.
+Other brackets are treated as spaces.")
+
+(defun org-element--parse-paired-brackets (char)
+  "Parse paired brackets at point.
+CHAR is the opening bracket to consider, as a character.  Return
+contents between brackets, as a string, or nil.  Also move point
+past the brackets."
+  (when (eq char (char-after))
+    (let ((syntax-table (pcase char
+                         (?\{ org-element--pair-curly-table)
+                         (?\[ org-element--pair-square-table)
+                         (?\( org-element--pair-round-table)
+                         (_ nil)))
+         (pos (point)))
+      (when syntax-table
+       (with-syntax-table syntax-table
+         (let ((end (ignore-errors (scan-lists pos 1 0))))
+           (when end
+             (goto-char end)
+             (buffer-substring-no-properties (1+ pos) (1- end)))))))))
 
 
 ;;; Accessors and Setters
@@ -368,10 +389,18 @@ still has an entry since one of its properties (`:title') 
does.")
 ;; `org-element-contents' and `org-element-restriction'.
 ;;
 ;; Setter functions allow modification of elements by side effect.
-;; There is `org-element-put-property', `org-element-set-contents',
-;; `org-element-set-element' and `org-element-adopt-element'.  Note
-;; that `org-element-set-element' and `org-element-adopt-elements' are
-;; higher level functions since also update `:parent' property.
+;; There is `org-element-put-property', `org-element-set-contents'.
+;; These low-level functions are useful to build a parse tree.
+;;
+;; `org-element-adopt-elements', `org-element-set-element',
+;; `org-element-extract-element' and `org-element-insert-before' are
+;; high-level functions useful to modify a parse tree.
+;;
+;; `org-element-secondary-p' is a predicate used to know if a given
+;; object belongs to a secondary string.  `org-element-class' tells if
+;; some parsed data is an element or an object, handling pseudo
+;; elements and objects.  `org-element-copy' returns an element or
+;; object, stripping its parent property in the process.
 
 (defsubst org-element-type (element)
   "Return type of ELEMENT.
@@ -411,29 +440,49 @@ Return modified element."
     element))
 
 (defsubst org-element-set-contents (element &rest contents)
-  "Set ELEMENT contents to CONTENTS.
-Return modified element."
-  (cond ((not element) (list contents))
+  "Set ELEMENT's contents to CONTENTS.
+Return ELEMENT."
+  (cond ((null element) contents)
        ((not (symbolp (car element))) contents)
-       ((cdr element) (setcdr (cdr element) contents))
+       ((cdr element) (setcdr (cdr element) contents) element)
        (t (nconc element contents))))
 
-(defsubst org-element-set-element (old new)
-  "Replace element or object OLD with element or object NEW.
-The function takes care of setting `:parent' property for NEW."
-  ;; Since OLD is going to be changed into NEW by side-effect, first
-  ;; make sure that every element or object within NEW has OLD as
-  ;; parent.
-  (mapc (lambda (blob) (org-element-put-property blob :parent old))
-       (org-element-contents new))
-  ;; Transfer contents.
-  (apply 'org-element-set-contents old (org-element-contents new))
-  ;; Ensure NEW has same parent as OLD, then overwrite OLD properties
-  ;; with NEW's.
-  (org-element-put-property new :parent (org-element-property :parent old))
-  (setcar (cdr old) (nth 1 new))
-  ;; Transfer type.
-  (setcar old (car new)))
+(defun org-element-secondary-p (object)
+  "Non-nil when OBJECT directly belongs to a secondary string.
+Return value is the property name, as a keyword, or nil."
+  (let* ((parent (org-element-property :parent object))
+        (properties (cdr (assq (org-element-type parent)
+                               org-element-secondary-value-alist))))
+    (catch 'exit
+      (dolist (p properties)
+       (and (memq object (org-element-property p parent))
+            (throw 'exit p))))))
+
+(defun org-element-class (datum &optional parent)
+  "Return class for ELEMENT, as a symbol.
+Class is either `element' or `object'.  Optional argument PARENT
+is the element or object containing DATUM.  It defaults to the
+value of DATUM `:parent' property."
+  (let ((type (org-element-type datum))
+       (parent (or parent (org-element-property :parent datum))))
+    (cond
+     ;; Trivial cases.
+     ((memq type org-element-all-objects) 'object)
+     ((memq type org-element-all-elements) 'element)
+     ;; Special cases.
+     ((eq type 'org-data) 'element)
+     ((eq type 'plain-text) 'object)
+     ((not type) 'object)
+     ;; Pseudo object or elements.  Make a guess about its class.
+     ;; Basically a pseudo object is contained within another object,
+     ;; a secondary string or a container element.
+     ((not parent) 'element)
+     (t
+      (let ((parent-type (org-element-type parent)))
+       (cond ((not parent-type) 'object)
+             ((memq parent-type org-element-object-containers) 'object)
+             ((org-element-secondary-p datum) 'object)
+             (t 'element)))))))
 
 (defsubst org-element-adopt-elements (parent &rest children)
   "Append elements to the contents of another element.
@@ -443,18 +492,108 @@ objects, or a strings.
 
 The function takes care of setting `:parent' property for CHILD.
 Return parent element."
-  ;; Link every child to PARENT. If PARENT is nil, it is a secondary
-  ;; string: parent is the list itself.
-  (mapc (lambda (child)
-         (org-element-put-property child :parent (or parent children)))
-       children)
-  ;; Add CHILDREN at the end of PARENT contents.
-  (when parent
-    (apply 'org-element-set-contents
-          parent
-          (nconc (org-element-contents parent) children)))
-  ;; Return modified PARENT element.
-  (or parent children))
+  (if (not children) parent
+    ;; Link every child to PARENT. If PARENT is nil, it is a secondary
+    ;; string: parent is the list itself.
+    (dolist (child children)
+      (org-element-put-property child :parent (or parent children)))
+    ;; Add CHILDREN at the end of PARENT contents.
+    (when parent
+      (apply #'org-element-set-contents
+            parent
+            (nconc (org-element-contents parent) children)))
+    ;; Return modified PARENT element.
+    (or parent children)))
+
+(defun org-element-extract-element (element)
+  "Extract ELEMENT from parse tree.
+Remove element from the parse tree by side-effect, and return it
+with its `:parent' property stripped out."
+  (let ((parent (org-element-property :parent element))
+       (secondary (org-element-secondary-p element)))
+    (if secondary
+        (org-element-put-property
+        parent secondary
+        (delq element (org-element-property secondary parent)))
+      (apply #'org-element-set-contents
+            parent
+            (delq element (org-element-contents parent))))
+    ;; Return ELEMENT with its :parent removed.
+    (org-element-put-property element :parent nil)))
+
+(defun org-element-insert-before (element location)
+  "Insert ELEMENT before LOCATION in parse tree.
+LOCATION is an element, object or string within the parse tree.
+Parse tree is modified by side effect."
+  (let* ((parent (org-element-property :parent location))
+        (property (org-element-secondary-p location))
+        (siblings (if property (org-element-property property parent)
+                    (org-element-contents parent)))
+        ;; Special case: LOCATION is the first element of an
+        ;; independent secondary string (e.g. :title property).  Add
+        ;; ELEMENT in-place.
+        (specialp (and (not property)
+                       (eq siblings parent)
+                       (eq (car parent) location))))
+    ;; Install ELEMENT at the appropriate LOCATION within SIBLINGS.
+    (cond (specialp)
+         ((or (null siblings) (eq (car siblings) location))
+          (push element siblings))
+         ((null location) (nconc siblings (list element)))
+         (t
+          (let ((index (cl-position location siblings)))
+            (unless index (error "No location found to insert element"))
+            (push element (cdr (nthcdr (1- index) siblings))))))
+    ;; Store SIBLINGS at appropriate place in parse tree.
+    (cond
+     (specialp (setcdr parent (copy-sequence parent)) (setcar parent element))
+     (property (org-element-put-property parent property siblings))
+     (t (apply #'org-element-set-contents parent siblings)))
+    ;; Set appropriate :parent property.
+    (org-element-put-property element :parent parent)))
+
+(defun org-element-set-element (old new)
+  "Replace element or object OLD with element or object NEW.
+The function takes care of setting `:parent' property for NEW."
+  ;; Ensure OLD and NEW have the same parent.
+  (org-element-put-property new :parent (org-element-property :parent old))
+  (if (or (memq (org-element-type old) '(plain-text nil))
+         (memq (org-element-type new) '(plain-text nil)))
+      ;; We cannot replace OLD with NEW since one of them is not an
+      ;; object or element.  We take the long path.
+      (progn (org-element-insert-before new old)
+            (org-element-extract-element old))
+    ;; Since OLD is going to be changed into NEW by side-effect, first
+    ;; make sure that every element or object within NEW has OLD as
+    ;; parent.
+    (dolist (blob (org-element-contents new))
+      (org-element-put-property blob :parent old))
+    ;; Transfer contents.
+    (apply #'org-element-set-contents old (org-element-contents new))
+    ;; Overwrite OLD's properties with NEW's.
+    (setcar (cdr old) (nth 1 new))
+    ;; Transfer type.
+    (setcar old (car new))))
+
+(defun org-element-create (type &optional props &rest children)
+  "Create a new element of type TYPE.
+Optional argument PROPS, when non-nil, is a plist defining the
+properties of the element.  CHILDREN can be elements, objects or
+strings."
+  (apply #'org-element-adopt-elements (list type props) children))
+
+(defun org-element-copy (datum)
+  "Return a copy of DATUM.
+DATUM is an element, object, string or nil.  `:parent' property
+is cleared and contents are removed in the process."
+  (when datum
+    (let ((type (org-element-type datum)))
+      (pcase type
+       (`org-data (list 'org-data nil))
+       (`plain-text (substring-no-properties datum))
+       (`nil (copy-sequence datum))
+       (_
+        (list type (plist-put (copy-sequence (nth 1 datum)) :parent nil)))))))
 
 
 
@@ -467,7 +606,7 @@ Return parent element."
 ;; Most of them accepts no argument.  Though, exceptions exist.  Hence
 ;; every element containing a secondary string (see
 ;; `org-element-secondary-value-alist') will accept an optional
-;; argument to toggle parsing of that secondary string.  Moreover,
+;; argument to toggle parsing of these secondary strings.  Moreover,
 ;; `item' parser requires current list's structure as its first
 ;; element.
 ;;
@@ -503,8 +642,8 @@ keyword and CDR is a plist of affiliated keywords along with
 their value.
 
 Return a list whose CAR is `center-block' and CDR is a plist
-containing `:begin', `:end', `:hiddenp', `:contents-begin',
-`:contents-end', `:post-blank' and `:post-affiliated' keywords.
+containing `:begin', `:end', `:contents-begin', `:contents-end',
+`:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at the beginning of the block."
   (let ((case-fold-search t))
@@ -520,7 +659,6 @@ Assume point is at the beginning of the block."
                                      (and (< (point) block-end-line)
                                           (point))))
               (contents-end (and contents-begin block-end-line))
-              (hidden (org-invisible-p2))
               (pos-before-blank (progn (goto-char block-end-line)
                                        (forward-line)
                                        (point)))
@@ -531,15 +669,14 @@ Assume point is at the beginning of the block."
                (nconc
                 (list :begin begin
                       :end end
-                      :hiddenp hidden
                       :contents-begin contents-begin
                       :contents-end contents-end
                       :post-blank (count-lines pos-before-blank end)
                       :post-affiliated post-affiliated)
                 (cdr affiliated))))))))
 
-(defun org-element-center-block-interpreter (center-block contents)
-  "Interpret CENTER-BLOCK element as Org syntax.
+(defun org-element-center-block-interpreter (_ contents)
+  "Interpret a center-block element as Org syntax.
 CONTENTS is the contents of the element."
   (format "#+BEGIN_CENTER\n%s#+END_CENTER" contents))
 
@@ -555,7 +692,7 @@ keyword and CDR is a plist of affiliated keywords along with
 their value.
 
 Return a list whose CAR is `drawer' and CDR is a plist containing
-`:drawer-name', `:begin', `:end', `:hiddenp', `:contents-begin',
+`:drawer-name', `:begin', `:end', `:contents-begin',
 `:contents-end', `:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at beginning of drawer."
@@ -566,7 +703,7 @@ Assume point is at beginning of drawer."
       (save-excursion
        (let* ((drawer-end-line (match-beginning 0))
               (name (progn (looking-at org-drawer-regexp)
-                           (org-match-string-no-properties 1)))
+                           (match-string-no-properties 1)))
               (begin (car affiliated))
               (post-affiliated (point))
               ;; Empty drawers have no contents.
@@ -574,7 +711,6 @@ Assume point is at beginning of drawer."
                                      (and (< (point) drawer-end-line)
                                           (point))))
               (contents-end (and contents-begin drawer-end-line))
-              (hidden (org-invisible-p2))
               (pos-before-blank (progn (goto-char drawer-end-line)
                                        (forward-line)
                                        (point)))
@@ -585,7 +721,6 @@ Assume point is at beginning of drawer."
                 (list :begin begin
                       :end end
                       :drawer-name name
-                      :hiddenp hidden
                       :contents-begin contents-begin
                       :contents-end contents-end
                       :post-blank (count-lines pos-before-blank end)
@@ -611,9 +746,9 @@ keyword and CDR is a plist of affiliated keywords along with
 their value.
 
 Return a list whose CAR is `dynamic-block' and CDR is a plist
-containing `:block-name', `:begin', `:end', `:hiddenp',
-`:contents-begin', `:contents-end', `:arguments', `:post-blank'
-and `:post-affiliated' keywords.
+containing `:block-name', `:begin', `:end', `:contents-begin',
+`:contents-end', `:arguments', `:post-blank' and
+`:post-affiliated' keywords.
 
 Assume point is at beginning of dynamic block."
   (let ((case-fold-search t))
@@ -624,8 +759,8 @@ Assume point is at beginning of dynamic block."
       (let ((block-end-line (match-beginning 0)))
        (save-excursion
          (let* ((name (progn (looking-at org-dblock-start-re)
-                             (org-match-string-no-properties 1)))
-                (arguments (org-match-string-no-properties 3))
+                             (match-string-no-properties 1)))
+                (arguments (match-string-no-properties 3))
                 (begin (car affiliated))
                 (post-affiliated (point))
                 ;; Empty blocks have no contents.
@@ -633,7 +768,6 @@ Assume point is at beginning of dynamic block."
                                        (and (< (point) block-end-line)
                                             (point))))
                 (contents-end (and contents-begin block-end-line))
-                (hidden (org-invisible-p2))
                 (pos-before-blank (progn (goto-char block-end-line)
                                          (forward-line)
                                          (point)))
@@ -645,7 +779,6 @@ Assume point is at beginning of dynamic block."
                         :end end
                         :block-name name
                         :arguments arguments
-                        :hiddenp hidden
                         :contents-begin contents-begin
                         :contents-end contents-end
                         :post-blank (count-lines pos-before-blank end)
@@ -658,12 +791,18 @@ CONTENTS is the contents of the element."
   (format "#+BEGIN: %s%s\n%s#+END:"
          (org-element-property :block-name dynamic-block)
          (let ((args (org-element-property :arguments dynamic-block)))
-           (and args (concat " " args)))
+           (if args (concat " " args) ""))
          contents))
 
 
 ;;;; Footnote Definition
 
+(defconst org-element--footnote-separator
+  (concat org-outline-regexp-bol "\\|"
+         org-footnote-definition-re "\\|"
+         "^\\([ \t]*\n\\)\\{2,\\}")
+  "Regexp used as a footnote definition separator.")
+
 (defun org-element-footnote-definition-parser (limit affiliated)
   "Parse a footnote definition.
 
@@ -679,59 +818,104 @@ a plist containing `:label', `:begin' `:end', 
`:contents-begin',
 Assume point is at the beginning of the footnote definition."
   (save-excursion
     (let* ((label (progn (looking-at org-footnote-definition-re)
-                        (org-match-string-no-properties 1)))
+                        (match-string-no-properties 1)))
           (begin (car affiliated))
           (post-affiliated (point))
-          (ending (save-excursion
-                    (if (progn
-                          (end-of-line)
-                          (re-search-forward
-                           (concat org-outline-regexp-bol "\\|"
-                                   org-footnote-definition-re "\\|"
-                                   "^\\([ \t]*\n\\)\\{2,\\}") limit 'move))
-                        (match-beginning 0)
-                      (point))))
-          (contents-begin (progn
-                            (search-forward "]")
-                            (skip-chars-forward " \r\t\n" ending)
-                            (cond ((= (point) ending) nil)
-                                  ((= (line-beginning-position) begin) (point))
-                                  (t (line-beginning-position)))))
-          (contents-end (and contents-begin ending))
-          (end (progn (goto-char ending)
-                      (skip-chars-forward " \r\t\n" limit)
-                      (if (eobp) (point) (line-beginning-position)))))
+          (end
+           (save-excursion
+             (end-of-line)
+             (cond
+              ((not
+                (re-search-forward org-element--footnote-separator limit t))
+               limit)
+              ((eq ?\[ (char-after (match-beginning 0)))
+               ;; At a new footnote definition, make sure we end
+               ;; before any affiliated keyword above.
+               (forward-line -1)
+               (while (and (> (point) post-affiliated)
+                           (looking-at-p org-element--affiliated-re))
+                 (forward-line -1))
+               (line-beginning-position 2))
+              ((eq ?* (char-after (match-beginning 0))) (match-beginning 0))
+              (t (skip-chars-forward " \r\t\n" limit)
+                 (if (= limit (point)) limit (line-beginning-position))))))
+          (contents-begin
+           (progn (search-forward "]")
+                  (skip-chars-forward " \r\t\n" end)
+                  (cond ((= (point) end) nil)
+                        ((= (line-beginning-position) post-affiliated) (point))
+                        (t (line-beginning-position)))))
+          (contents-end
+           (progn (goto-char end)
+                  (skip-chars-backward " \r\t\n")
+                  (line-beginning-position 2))))
       (list 'footnote-definition
            (nconc
             (list :label label
                   :begin begin
                   :end end
                   :contents-begin contents-begin
-                  :contents-end contents-end
-                  :post-blank (count-lines ending end)
+                  :contents-end (and contents-begin contents-end)
+                  :post-blank (count-lines contents-end end)
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
 (defun org-element-footnote-definition-interpreter (footnote-definition 
contents)
   "Interpret FOOTNOTE-DEFINITION element as Org syntax.
 CONTENTS is the contents of the footnote-definition."
-  (concat (format "[%s]" (org-element-property :label footnote-definition))
+  (concat (format "[fn:%s]" (org-element-property :label footnote-definition))
          " "
          contents))
 
 
 ;;;; Headline
 
+(defun org-element--get-node-properties ()
+  "Return node properties associated to headline at point.
+Upcase property names.  It avoids confusion between properties
+obtained through property drawer and default properties from the
+parser (e.g. `:end' and :END:).  Return value is a plist."
+  (save-excursion
+    (forward-line)
+    (when (looking-at-p org-planning-line-re) (forward-line))
+    (when (looking-at org-property-drawer-re)
+      (forward-line)
+      (let ((end (match-end 0)) properties)
+       (while (< (line-end-position) end)
+         (looking-at org-property-re)
+         (push (match-string-no-properties 3) properties)
+         (push (intern (concat ":" (upcase (match-string 2)))) properties)
+         (forward-line))
+       properties))))
+
+(defun org-element--get-time-properties ()
+  "Return time properties associated to headline at point.
+Return value is a plist."
+  (save-excursion
+    (when (progn (forward-line) (looking-at org-planning-line-re))
+      (let ((end (line-end-position)) plist)
+       (while (re-search-forward org-keyword-time-not-clock-regexp end t)
+         (goto-char (match-end 1))
+         (skip-chars-forward " \t")
+         (let ((keyword (match-string 1))
+               (time (org-element-timestamp-parser)))
+           (cond ((equal keyword org-scheduled-string)
+                  (setq plist (plist-put plist :scheduled time)))
+                 ((equal keyword org-deadline-string)
+                  (setq plist (plist-put plist :deadline time)))
+                 (t (setq plist (plist-put plist :closed time))))))
+       plist))))
+
 (defun org-element-headline-parser (limit &optional raw-secondary-p)
   "Parse a headline.
 
 Return a list whose CAR is `headline' and CDR is a plist
-containing `:raw-value', `:title', `:alt-title', `:begin',
-`:end', `:pre-blank', `:hiddenp', `:contents-begin',
-`:contents-end', `:level', `:priority', `:tags',
-`:todo-keyword',`:todo-type', `:scheduled', `:deadline',
-`:closed', `:quotedp', `:archivedp', `:commentedp',
-`:footnote-section-p' and `:post-blank' keywords.
+containing `:raw-value', `:title', `:begin', `:end',
+`:pre-blank', `:contents-begin' and `:contents-end', `:level',
+`:priority', `:tags', `:todo-keyword',`:todo-type', `:scheduled',
+`:deadline', `:closed', `:archivedp', `:commentedp'
+`:footnote-section-p', `:post-blank' and `:post-affiliated'
+keywords.
 
 The plist also contains any property set in the property drawer,
 with its name in upper cases and colons added at the
@@ -744,80 +928,46 @@ parsed as a secondary string, but as a plain string 
instead.
 
 Assume point is at beginning of the headline."
   (save-excursion
-    (let* ((components (org-heading-components))
-          (level (nth 1 components))
-          (todo (nth 2 components))
+    (let* ((begin (point))
+          (level (prog1 (org-reduced-level (skip-chars-forward "*"))
+                   (skip-chars-forward " \t")))
+          (todo (and org-todo-regexp
+                     (let (case-fold-search) (looking-at org-todo-regexp))
+                     (progn (goto-char (match-end 0))
+                            (skip-chars-forward " \t")
+                            (match-string 0))))
           (todo-type
            (and todo (if (member todo org-done-keywords) 'done 'todo)))
-          (tags (let ((raw-tags (nth 5 components)))
-                  (and raw-tags (org-split-string raw-tags ":"))))
-          (raw-value (or (nth 4 components) ""))
-          (quotedp
-           (let ((case-fold-search nil))
-             (string-match (format "^%s\\( \\|$\\)" org-quote-string)
-                           raw-value)))
+          (priority (and (looking-at "\\[#.\\][ \t]*")
+                         (progn (goto-char (match-end 0))
+                                (aref (match-string 0) 2))))
           (commentedp
-           (let ((case-fold-search nil))
-             (string-match (format "^%s\\( \\|$\\)" org-comment-string)
-                           raw-value)))
+           (and (let (case-fold-search) (looking-at org-comment-string))
+                (goto-char (match-end 0))))
+          (title-start (point))
+          (tags (when (re-search-forward
+                       "[ \t]+\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"
+                       (line-end-position)
+                       'move)
+                  (goto-char (match-beginning 0))
+                  (org-split-string (match-string 1) ":")))
+          (title-end (point))
+          (raw-value (org-trim
+                      (buffer-substring-no-properties title-start title-end)))
           (archivedp (member org-archive-tag tags))
           (footnote-section-p (and org-footnote-section
                                    (string= org-footnote-section raw-value)))
-          ;; Upcase property names.  It avoids confusion between
-          ;; properties obtained through property drawer and default
-          ;; properties from the parser (e.g. `:end' and :END:)
-          (standard-props
-           (let (plist)
-             (mapc
-              (lambda (p)
-                (setq plist
-                      (plist-put plist
-                                 (intern (concat ":" (upcase (car p))))
-                                 (cdr p))))
-              (org-entry-properties nil 'standard))
-             plist))
-          (time-props
-           ;; Read time properties on the line below the headline.
-           (save-excursion
-             (when (progn (forward-line)
-                          (looking-at org-planning-or-clock-line-re))
-               (let ((end (line-end-position)) plist)
-                 (while (re-search-forward
-                         org-keyword-time-not-clock-regexp end t)
-                   (goto-char (match-end 1))
-                   (skip-chars-forward " \t")
-                   (let ((keyword (match-string 1))
-                         (time (org-element-timestamp-parser)))
-                     (cond ((equal keyword org-scheduled-string)
-                            (setq plist (plist-put plist :scheduled time)))
-                           ((equal keyword org-deadline-string)
-                            (setq plist (plist-put plist :deadline time)))
-                           (t (setq plist (plist-put plist :closed time))))))
-                 plist))))
-          (begin (point))
+          (standard-props (org-element--get-node-properties))
+          (time-props (org-element--get-time-properties))
           (end (min (save-excursion (org-end-of-subtree t t)) limit))
-          (pos-after-head (progn (forward-line) (point)))
           (contents-begin (save-excursion
+                            (forward-line)
                             (skip-chars-forward " \r\t\n" end)
                             (and (/= (point) end) (line-beginning-position))))
-          (hidden (org-invisible-p2))
           (contents-end (and contents-begin
                              (progn (goto-char end)
                                     (skip-chars-backward " \r\t\n")
-                                    (forward-line)
-                                    (point)))))
-      ;; Clean RAW-VALUE from any quote or comment string.
-      (when (or quotedp commentedp)
-       (let ((case-fold-search nil))
-         (setq raw-value
-               (replace-regexp-in-string
-                (concat
-                 (regexp-opt (list org-quote-string org-comment-string))
-                 "\\(?: \\|$\\)")
-                ""
-                raw-value))))
-      ;; Clean TAGS from archive tag, if any.
-      (when archivedp (setq tags (delete org-archive-tag tags)))
+                                    (line-beginning-position 2)))))
       (let ((headline
             (list 'headline
                   (nconc
@@ -826,36 +976,37 @@ Assume point is at beginning of the headline."
                          :end end
                          :pre-blank
                          (if (not contents-begin) 0
-                           (count-lines pos-after-head contents-begin))
-                         :hiddenp hidden
+                           (1- (count-lines begin contents-begin)))
                          :contents-begin contents-begin
                          :contents-end contents-end
                          :level level
-                         :priority (nth 3 components)
+                         :priority priority
                          :tags tags
                          :todo-keyword todo
                          :todo-type todo-type
-                         :post-blank (count-lines
-                                      (or contents-end pos-after-head)
-                                      end)
+                         :post-blank
+                         (if contents-end
+                             (count-lines contents-end end)
+                           (1- (count-lines begin end)))
                          :footnote-section-p footnote-section-p
                          :archivedp archivedp
                          :commentedp commentedp
-                         :quotedp quotedp)
+                         :post-affiliated begin)
                    time-props
                    standard-props))))
-       (let ((alt-title (org-element-property :ALT_TITLE headline)))
-         (when alt-title
-           (org-element-put-property
-            headline :alt-title
-            (if raw-secondary-p alt-title
-              (org-element-parse-secondary-string
-               alt-title (org-element-restriction 'headline) headline)))))
        (org-element-put-property
         headline :title
         (if raw-secondary-p raw-value
-          (org-element-parse-secondary-string
-           raw-value (org-element-restriction 'headline) headline)))))))
+          (org-element--parse-objects
+           (progn (goto-char title-start)
+                  (skip-chars-forward " \t")
+                  (point))
+           (progn (goto-char title-end)
+                  (skip-chars-backward " \t")
+                  (point))
+           nil
+           (org-element-restriction 'headline)
+           headline)))))))
 
 (defun org-element-headline-interpreter (headline contents)
   "Interpret HEADLINE element as Org syntax.
@@ -865,22 +1016,17 @@ CONTENTS is the contents of the element."
         (priority (org-element-property :priority headline))
         (title (org-element-interpret-data
                 (org-element-property :title headline)))
-        (tags (let ((tag-list (if (org-element-property :archivedp headline)
-                                  (cons org-archive-tag
-                                        (org-element-property :tags headline))
-                                (org-element-property :tags headline))))
+        (tags (let ((tag-list (org-element-property :tags headline)))
                 (and tag-list
                      (format ":%s:" (mapconcat #'identity tag-list ":")))))
         (commentedp (org-element-property :commentedp headline))
-        (quotedp (org-element-property :quotedp headline))
         (pre-blank (or (org-element-property :pre-blank headline) 0))
         (heading
          (concat (make-string (if org-odd-levels-only (1- (* level 2)) level)
                               ?*)
                  (and todo (concat " " todo))
-                 (and quotedp (concat " " org-quote-string))
                  (and commentedp (concat " " org-comment-string))
-                 (and priority (format " [#%s]" (char-to-string priority)))
+                 (and priority (format " [#%c]" priority))
                  " "
                  (if (and org-footnote-section
                           (org-element-property :footnote-section-p headline))
@@ -912,10 +1058,11 @@ CONTENTS is the contents of the element."
   "Parse an inline task.
 
 Return a list whose CAR is `inlinetask' and CDR is a plist
-containing `:title', `:begin', `:end', `:hiddenp',
+containing `:title', `:begin', `:end', `:pre-blank',
 `:contents-begin' and `:contents-end', `:level', `:priority',
 `:raw-value', `:tags', `:todo-keyword', `:todo-type',
-`:scheduled', `:deadline', `:closed' and `:post-blank' keywords.
+`:scheduled', `:deadline', `:closed', `:post-blank' and
+`:post-affiliated' keywords.
 
 The plist also contains any property set in the property drawer,
 with its name in upper cases and colons added at the
@@ -928,59 +1075,45 @@ string instead.
 Assume point is at beginning of the inline task."
   (save-excursion
     (let* ((begin (point))
-          (components (org-heading-components))
-          (todo (nth 2 components))
+          (level (prog1 (org-reduced-level (skip-chars-forward "*"))
+                   (skip-chars-forward " \t")))
+          (todo (and org-todo-regexp
+                     (let (case-fold-search) (looking-at org-todo-regexp))
+                     (progn (goto-char (match-end 0))
+                            (skip-chars-forward " \t")
+                            (match-string 0))))
           (todo-type (and todo
                           (if (member todo org-done-keywords) 'done 'todo)))
-          (tags (let ((raw-tags (nth 5 components)))
-                  (and raw-tags (org-split-string raw-tags ":"))))
-          (raw-value (or (nth 4 components) ""))
-          ;; Upcase property names.  It avoids confusion between
-          ;; properties obtained through property drawer and default
-          ;; properties from the parser (e.g. `:end' and :END:)
-          (standard-props
-           (let (plist)
-             (mapc
-              (lambda (p)
-                (setq plist
-                      (plist-put plist
-                                 (intern (concat ":" (upcase (car p))))
-                                 (cdr p))))
-              (org-entry-properties nil 'standard))
-             plist))
-          (time-props
-           ;; Read time properties on the line below the inlinetask
-           ;; opening string.
-           (save-excursion
-             (when (progn (forward-line)
-                          (looking-at org-planning-or-clock-line-re))
-               (let ((end (line-end-position)) plist)
-                 (while (re-search-forward
-                         org-keyword-time-not-clock-regexp end t)
-                   (goto-char (match-end 1))
-                   (skip-chars-forward " \t")
-                   (let ((keyword (match-string 1))
-                         (time (org-element-timestamp-parser)))
-                     (cond ((equal keyword org-scheduled-string)
-                            (setq plist (plist-put plist :scheduled time)))
-                           ((equal keyword org-deadline-string)
-                            (setq plist (plist-put plist :deadline time)))
-                           (t (setq plist (plist-put plist :closed time))))))
-                 plist))))
+          (priority (and (looking-at "\\[#.\\][ \t]*")
+                         (progn (goto-char (match-end 0))
+                                (aref (match-string 0) 2))))
+          (title-start (point))
+          (tags (when (re-search-forward
+                       "[ \t]+\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"
+                       (line-end-position)
+                       'move)
+                  (goto-char (match-beginning 0))
+                  (org-split-string (match-string 1) ":")))
+          (title-end (point))
+          (raw-value (org-trim
+                      (buffer-substring-no-properties title-start title-end)))
           (task-end (save-excursion
                       (end-of-line)
                       (and (re-search-forward org-outline-regexp-bol limit t)
-                           (org-looking-at-p "END[ \t]*$")
+                           (looking-at-p "[ \t]*END[ \t]*$")
                            (line-beginning-position))))
-          (contents-begin (progn (forward-line)
-                                 (and task-end (< (point) task-end) (point))))
-          (hidden (and contents-begin (org-invisible-p2)))
+          (standard-props (and task-end (org-element--get-node-properties)))
+          (time-props (and task-end (org-element--get-time-properties)))
+          (contents-begin (and task-end
+                               (< (point) task-end)
+                               (progn
+                                 (forward-line)
+                                 (skip-chars-forward " \t\n")
+                                 (line-beginning-position))))
           (contents-end (and contents-begin task-end))
-          (before-blank (if (not task-end) (point)
-                          (goto-char task-end)
-                          (forward-line)
-                          (point)))
-          (end (progn (skip-chars-forward " \r\t\n" limit)
+          (end (progn (when task-end (goto-char task-end))
+                      (forward-line)
+                      (skip-chars-forward " \r\t\n" limit)
                       (if (eobp) (point) (line-beginning-position))))
           (inlinetask
            (list 'inlinetask
@@ -988,22 +1121,31 @@ Assume point is at beginning of the inline task."
                   (list :raw-value raw-value
                         :begin begin
                         :end end
-                        :hiddenp hidden
+                        :pre-blank
+                        (if (not contents-begin) 0
+                          (1- (count-lines begin contents-begin)))
                         :contents-begin contents-begin
                         :contents-end contents-end
-                        :level (nth 1 components)
-                        :priority (nth 3 components)
+                        :level level
+                        :priority priority
                         :tags tags
                         :todo-keyword todo
                         :todo-type todo-type
-                        :post-blank (count-lines before-blank end))
+                        :post-blank (1- (count-lines (or task-end begin) end))
+                        :post-affiliated begin)
                   time-props
                   standard-props))))
       (org-element-put-property
        inlinetask :title
        (if raw-secondary-p raw-value
-        (org-element-parse-secondary-string
-         raw-value
+        (org-element--parse-objects
+         (progn (goto-char title-start)
+                (skip-chars-forward " \t")
+                (point))
+         (progn (goto-char title-end)
+                (skip-chars-backward " \t")
+                (point))
+         nil
          (org-element-restriction 'inlinetask)
          inlinetask))))))
 
@@ -1020,8 +1162,7 @@ CONTENTS is the contents of inlinetask."
                      (format ":%s:" (mapconcat 'identity tag-list ":")))))
         (task (concat (make-string level ?*)
                       (and todo (concat " " todo))
-                      (and priority
-                           (format " [#%s]" (char-to-string priority)))
+                      (and priority (format " [#%c]" priority))
                       (and title (concat " " title)))))
     (concat task
            ;; Align tags.
@@ -1048,15 +1189,15 @@ CONTENTS is the contents of inlinetask."
 
 ;;;; Item
 
-(defun org-element-item-parser (limit struct &optional raw-secondary-p)
+(defun org-element-item-parser (_ struct &optional raw-secondary-p)
   "Parse an item.
 
 STRUCT is the structure of the plain list.
 
 Return a list whose CAR is `item' and CDR is a plist containing
 `:bullet', `:begin', `:end', `:contents-begin', `:contents-end',
-`:checkbox', `:counter', `:tag', `:structure', `:hiddenp' and
-`:post-blank' keywords.
+`:checkbox', `:counter', `:tag', `:structure', `:post-blank' and
+`:post-affiliated' keywords.
 
 When optional argument RAW-SECONDARY-P is non-nil, item's tag, if
 any, will not be parsed as a secondary string, but as a plain
@@ -1067,12 +1208,12 @@ Assume point is at the beginning of the item."
     (beginning-of-line)
     (looking-at org-list-full-item-re)
     (let* ((begin (point))
-          (bullet (org-match-string-no-properties 1))
-          (checkbox (let ((box (org-match-string-no-properties 3)))
+          (bullet (match-string-no-properties 1))
+          (checkbox (let ((box (match-string 3)))
                       (cond ((equal "[ ]" box) 'off)
                             ((equal "[X]" box) 'on)
                             ((equal "[-]" box) 'trans))))
-          (counter (let ((c (org-match-string-no-properties 2)))
+          (counter (let ((c (match-string 2)))
                      (save-match-data
                        (cond
                         ((not c) nil)
@@ -1081,9 +1222,8 @@ Assume point is at the beginning of the item."
                             64))
                         ((string-match "[0-9]+" c)
                          (string-to-number (match-string 0 c)))))))
-          (end (save-excursion (goto-char (org-list-get-item-end begin struct))
-                               (unless (bolp) (forward-line))
-                               (point)))
+          (end (progn (goto-char (nth 6 (assq (point) struct)))
+                      (if (bolp) (point) (line-beginning-position 2))))
           (contents-begin
            (progn (goto-char
                    ;; Ignore tags in un-ordered lists: they are just
@@ -1092,40 +1232,37 @@ Assume point is at the beginning of the item."
                             (save-match-data (string-match "[.)]" bullet)))
                        (match-beginning 4)
                      (match-end 0)))
-                  (skip-chars-forward " \r\t\n" limit)
-                  ;; If first line isn't empty, contents really start
-                  ;; at the text after item's meta-data.
-                  (if (= (point-at-bol) begin) (point) (point-at-bol))))
-          (hidden (progn (forward-line)
-                         (and (not (= (point) end)) (org-invisible-p2))))
-          (contents-end (progn (goto-char end)
-                               (skip-chars-backward " \r\t\n")
-                               (forward-line)
-                               (point)))
+                  (skip-chars-forward " \r\t\n" end)
+                  (cond ((= (point) end) nil)
+                        ;; If first line isn't empty, contents really
+                        ;; start at the text after item's meta-data.
+                        ((= (line-beginning-position) begin) (point))
+                        (t (line-beginning-position)))))
+          (contents-end (and contents-begin
+                             (progn (goto-char end)
+                                    (skip-chars-backward " \r\t\n")
+                                    (line-beginning-position 2))))
           (item
            (list 'item
                  (list :bullet bullet
                        :begin begin
                        :end end
-                       ;; CONTENTS-BEGIN and CONTENTS-END may be
-                       ;; mixed up in the case of an empty item
-                       ;; separated from the next by a blank line.
-                       ;; Thus ensure the former is always the
-                       ;; smallest.
-                       :contents-begin (min contents-begin contents-end)
-                       :contents-end (max contents-begin contents-end)
+                       :contents-begin contents-begin
+                       :contents-end contents-end
                        :checkbox checkbox
                        :counter counter
-                       :hiddenp hidden
                        :structure struct
-                       :post-blank (count-lines contents-end end)))))
+                       :post-blank (count-lines (or contents-end begin) end)
+                       :post-affiliated begin))))
       (org-element-put-property
        item :tag
-       (let ((raw-tag (org-list-get-tag begin struct)))
-        (and raw-tag
-             (if raw-secondary-p raw-tag
-               (org-element-parse-secondary-string
-                raw-tag (org-element-restriction 'item) item))))))))
+       (let ((raw (org-list-get-tag begin struct)))
+        (when raw
+          (if raw-secondary-p raw
+            (org-element--parse-objects
+             (match-beginning 4) (match-end 4) nil
+             (org-element-restriction 'item)
+             item))))))))
 
 (defun org-element-item-interpreter (item contents)
   "Interpret ITEM element as Org syntax.
@@ -1148,10 +1285,11 @@ CONTENTS is the contents of the element."
     (concat
      bullet
      (and counter (format "address@hidden " counter))
-     (case checkbox
-       (on "[X] ")
-       (off "[ ] ")
-       (trans "[-] "))
+     (pcase checkbox
+       (`on "[X] ")
+       (`off "[ ] ")
+       (`trans "[-] ")
+       (_ nil))
      (and tag (format "%s :: " tag))
      (when contents
        (let ((contents (replace-regexp-in-string
@@ -1168,9 +1306,6 @@ CONTENTS is the contents of the element."
   (let ((case-fold-search t)
        (top-ind limit)
        (item-re (org-item-re))
-       (drawers-re (concat ":\\("
-                           (mapconcat 'regexp-quote org-drawers "\\|")
-                           "\\):[ \t]*$"))
        (inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ "))
        items struct)
     (save-excursion
@@ -1222,11 +1357,12 @@ CONTENTS is the contents of the element."
            (forward-line)
            (let ((origin (point)))
              (when (re-search-forward inlinetask-re limit t)
-               (if (org-looking-at-p "END[ \t]*$") (forward-line)
+               (if (looking-at-p "END[ \t]*$") (forward-line)
                  (goto-char origin)))))
           ;; At some text line.  Check if it ends any previous item.
           (t
-           (let ((ind (progn (skip-chars-forward " \t") (current-column))))
+           (let ((ind (save-excursion (skip-chars-forward " \t")
+                                      (current-column))))
              (when (<= ind top-ind)
                (skip-chars-backward " \r\t\n")
                (forward-line))
@@ -1235,15 +1371,14 @@ CONTENTS is the contents of the element."
                  (setcar (nthcdr 6 item) (line-beginning-position))
                  (push item struct)
                  (unless items
-                   (throw 'exit (sort struct 'car-less-than-car))))))
+                   (throw 'exit (sort struct #'car-less-than-car))))))
            ;; Skip blocks (any type) and drawers contents.
            (cond
-            ((and (looking-at "#\\+BEGIN\\(:\\|_\\S-+\\)")
+            ((and (looking-at "[ \t]*#\\+BEGIN\\(:\\|_\\S-+\\)")
                   (re-search-forward
-                   (format "^[ \t]*#\\+END%s[ \t]*$"
-                           (org-match-string-no-properties 1))
+                   (format "^[ \t]*#\\+END%s[ \t]*$" (match-string 1))
                    limit t)))
-            ((and (looking-at drawers-re)
+            ((and (looking-at org-drawer-regexp)
                   (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))))
            (forward-line))))))))
 
@@ -1264,15 +1399,20 @@ containing `:type', `:begin', `:end', `:contents-begin' 
and
 Assume point is at the beginning of the list."
   (save-excursion
     (let* ((struct (or structure (org-element--list-struct limit)))
-          (prevs (org-list-prevs-alist struct))
-          (type (org-list-get-list-type (point) struct prevs))
+          (type (cond ((looking-at-p "[ \t]*[A-Za-z0-9]") 'ordered)
+                      ((nth 5 (assq (point) struct)) 'descriptive)
+                      (t 'unordered)))
           (contents-begin (point))
           (begin (car affiliated))
-          (contents-end
-           (progn (goto-char (org-list-get-list-end (point) struct prevs))
-                  (unless (bolp) (forward-line))
-                  (point)))
-          (end (progn (skip-chars-forward " \r\t\n" limit)
+          (contents-end (let* ((item (assq contents-begin struct))
+                               (ind (nth 1 item))
+                               (pos (nth 6 item)))
+                          (while (and (setq item (assq pos struct))
+                                      (= (nth 1 item) ind))
+                            (setq pos (nth 6 item)))
+                          pos))
+          (end (progn (goto-char contents-end)
+                      (skip-chars-forward " \r\t\n" limit)
                       (if (= (point) limit) limit (line-beginning-position)))))
       ;; Return value.
       (list 'plain-list
@@ -1287,8 +1427,8 @@ Assume point is at the beginning of the list."
                   :post-affiliated contents-begin)
             (cdr affiliated))))))
 
-(defun org-element-plain-list-interpreter (plain-list contents)
-  "Interpret PLAIN-LIST element as Org syntax.
+(defun org-element-plain-list-interpreter (_ contents)
+  "Interpret plain-list element as Org syntax.
 CONTENTS is the contents of the element."
   (with-temp-buffer
     (insert contents)
@@ -1299,52 +1439,36 @@ CONTENTS is the contents of the element."
 
 ;;;; Property Drawer
 
-(defun org-element-property-drawer-parser (limit affiliated)
+(defun org-element-property-drawer-parser (limit)
   "Parse a property drawer.
 
-LIMIT bounds the search.  AFFILIATED is a list of which CAR is
-the buffer position at the beginning of the first affiliated
-keyword and CDR is a plist of affiliated keywords along with
-their value.
+LIMIT bounds the search.
 
-Return a list whose CAR is `property-drawer' and CDR is a plist
-containing `:begin', `:end', `:hiddenp', `:contents-begin',
-`:contents-end', `:post-blank' and `:post-affiliated' keywords.
+Return a list whose car is `property-drawer' and cdr is a plist
+containing `:begin', `:end', `:contents-begin', `:contents-end',
+`:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at the beginning of the property drawer."
-  (let ((case-fold-search t))
-    (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit 
t)))
-       ;; Incomplete drawer: parse it as a paragraph.
-       (org-element-paragraph-parser limit affiliated)
-      (save-excursion
-       (let* ((drawer-end-line (match-beginning 0))
-              (begin (car affiliated))
-              (post-affiliated (point))
-              (contents-begin
-               (progn
-                 (forward-line)
-                 (and (re-search-forward org-property-re drawer-end-line t)
-                      (line-beginning-position))))
-              (contents-end (and contents-begin drawer-end-line))
-              (hidden (org-invisible-p2))
-              (pos-before-blank (progn (goto-char drawer-end-line)
-                                       (forward-line)
-                                       (point)))
-              (end (progn (skip-chars-forward " \r\t\n" limit)
-                          (if (eobp) (point) (line-beginning-position)))))
-         (list 'property-drawer
-               (nconc
-                (list :begin begin
-                      :end end
-                      :hiddenp hidden
-                      :contents-begin contents-begin
-                      :contents-end contents-end
-                      :post-blank (count-lines pos-before-blank end)
-                      :post-affiliated post-affiliated)
-                (cdr affiliated))))))))
-
-(defun org-element-property-drawer-interpreter (property-drawer contents)
-  "Interpret PROPERTY-DRAWER element as Org syntax.
+  (save-excursion
+    (let ((case-fold-search t)
+         (begin (point))
+         (contents-begin (line-beginning-position 2)))
+      (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)
+      (let ((contents-end (and (> (match-beginning 0) contents-begin)
+                              (match-beginning 0)))
+           (before-blank (progn (forward-line) (point)))
+           (end (progn (skip-chars-forward " \r\t\n" limit)
+                       (if (eobp) (point) (line-beginning-position)))))
+       (list 'property-drawer
+             (list :begin begin
+                   :end end
+                   :contents-begin (and contents-end contents-begin)
+                   :contents-end contents-end
+                   :post-blank (count-lines before-blank end)
+                   :post-affiliated begin))))))
+
+(defun org-element-property-drawer-interpreter (_ contents)
+  "Interpret property-drawer element as Org syntax.
 CONTENTS is the properties within the drawer."
   (format ":PROPERTIES:\n%s:END:" contents))
 
@@ -1360,8 +1484,8 @@ keyword and CDR is a plist of affiliated keywords along 
with
 their value.
 
 Return a list whose CAR is `quote-block' and CDR is a plist
-containing `:begin', `:end', `:hiddenp', `:contents-begin',
-`:contents-end', `:post-blank' and `:post-affiliated' keywords.
+containing `:begin', `:end', `:contents-begin', `:contents-end',
+`:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at the beginning of the block."
   (let ((case-fold-search t))
@@ -1378,7 +1502,6 @@ Assume point is at the beginning of the block."
                                        (and (< (point) block-end-line)
                                             (point))))
                 (contents-end (and contents-begin block-end-line))
-                (hidden (org-invisible-p2))
                 (pos-before-blank (progn (goto-char block-end-line)
                                          (forward-line)
                                          (point)))
@@ -1388,29 +1511,26 @@ Assume point is at the beginning of the block."
                  (nconc
                   (list :begin begin
                         :end end
-                        :hiddenp hidden
                         :contents-begin contents-begin
                         :contents-end contents-end
                         :post-blank (count-lines pos-before-blank end)
                         :post-affiliated post-affiliated)
                   (cdr affiliated)))))))))
 
-(defun org-element-quote-block-interpreter (quote-block contents)
-  "Interpret QUOTE-BLOCK element as Org syntax.
+(defun org-element-quote-block-interpreter (_ contents)
+  "Interpret quote-block element as Org syntax.
 CONTENTS is the contents of the element."
   (format "#+BEGIN_QUOTE\n%s#+END_QUOTE" contents))
 
 
 ;;;; Section
 
-(defun org-element-section-parser (limit)
+(defun org-element-section-parser (_)
   "Parse a section.
 
-LIMIT bounds the search.
-
 Return a list whose CAR is `section' and CDR is a plist
-containing `:begin', `:end', `:contents-begin', `contents-end'
-and `:post-blank' keywords."
+containing `:begin', `:end', `:contents-begin', `contents-end',
+`:post-blank' and `:post-affiliated' keywords."
   (save-excursion
     ;; Beginning of section is the beginning of the first non-blank
     ;; line after previous headline.
@@ -1418,17 +1538,17 @@ and `:post-blank' keywords."
          (end (progn (org-with-limited-levels (outline-next-heading))
                      (point)))
          (pos-before-blank (progn (skip-chars-backward " \r\t\n")
-                                  (forward-line)
-                                  (point))))
+                                  (line-beginning-position 2))))
       (list 'section
            (list :begin begin
                  :end end
                  :contents-begin begin
                  :contents-end pos-before-blank
-                 :post-blank (count-lines pos-before-blank end))))))
+                 :post-blank (count-lines pos-before-blank end)
+                 :post-affiliated begin)))))
 
-(defun org-element-section-interpreter (section contents)
-  "Interpret SECTION element as Org syntax.
+(defun org-element-section-interpreter (_ contents)
+  "Interpret section element as Org syntax.
 CONTENTS is the contents of the element."
   contents)
 
@@ -1444,14 +1564,13 @@ keyword and CDR is a plist of affiliated keywords along 
with
 their value.
 
 Return a list whose CAR is `special-block' and CDR is a plist
-containing `:type', `:begin', `:end', `:hiddenp',
-`:contents-begin', `:contents-end', `:post-blank' and
-`:post-affiliated' keywords.
+containing `:type', `:begin', `:end', `:contents-begin',
+`:contents-end', `:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at the beginning of the block."
   (let* ((case-fold-search t)
         (type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
-                     (upcase (match-string-no-properties 1)))))
+                     (match-string-no-properties 1))))
     (if (not (save-excursion
               (re-search-forward
                (format "^[ \t]*#\\+END_%s[ \t]*$" (regexp-quote type))
@@ -1467,7 +1586,6 @@ Assume point is at the beginning of the block."
                                        (and (< (point) block-end-line)
                                             (point))))
                 (contents-end (and contents-begin block-end-line))
-                (hidden (org-invisible-p2))
                 (pos-before-blank (progn (goto-char block-end-line)
                                          (forward-line)
                                          (point)))
@@ -1478,7 +1596,6 @@ Assume point is at the beginning of the block."
                   (list :type type
                         :begin begin
                         :end end
-                        :hiddenp hidden
                         :contents-begin contents-begin
                         :contents-end contents-end
                         :post-blank (count-lines pos-before-blank end)
@@ -1502,9 +1619,6 @@ CONTENTS is the contents of the element."
 ;; through the following steps: implement a parser and an interpreter,
 ;; tweak `org-element--current-element' so that it recognizes the new
 ;; type and add that new type to `org-element-all-elements'.
-;;
-;; As a special case, when the newly defined type is a block type,
-;; `org-element-block-name-alist' has to be modified accordingly.
 
 
 ;;;; Babel Call
@@ -1512,43 +1626,61 @@ CONTENTS is the contents of the element."
 (defun org-element-babel-call-parser (limit affiliated)
   "Parse a babel call.
 
-LIMIT bounds the search.  AFFILIATED is a list of which CAR is
+LIMIT bounds the search.  AFFILIATED is a list of which car is
 the buffer position at the beginning of the first affiliated
-keyword and CDR is a plist of affiliated keywords along with
+keyword and cdr is a plist of affiliated keywords along with
 their value.
 
-Return a list whose CAR is `babel-call' and CDR is a plist
-containing `:begin', `:end', `:info', `:post-blank' and
+Return a list whose car is `babel-call' and cdr is a plist
+containing `:call', `:inside-header', `:arguments',
+`:end-header', `:begin', `:end', `:value', `:post-blank' and
 `:post-affiliated' as keywords."
   (save-excursion
-    (let ((case-fold-search t)
-         (info (progn (looking-at org-babel-block-lob-one-liner-regexp)
-                      (org-babel-lob-get-info)))
-         (begin (car affiliated))
-         (post-affiliated (point))
-         (pos-before-blank (progn (forward-line) (point)))
-         (end (progn (skip-chars-forward " \r\t\n" limit)
-                     (if (eobp) (point) (line-beginning-position)))))
+    (let* ((begin (car affiliated))
+          (post-affiliated (point))
+          (before-blank (line-beginning-position 2))
+          (value (progn (search-forward ":" before-blank t)
+                        (skip-chars-forward " \t")
+                        (org-trim
+                         (buffer-substring-no-properties
+                          (point) (line-end-position)))))
+          (call
+           (or (org-string-nw-p
+                (buffer-substring-no-properties
+                 (point) (progn (skip-chars-forward "^[]()" before-blank)
+                                (point))))))
+          (inside-header (org-element--parse-paired-brackets ?\[))
+          (arguments (org-string-nw-p
+                      (org-element--parse-paired-brackets ?\()))
+          (end-header
+           (org-string-nw-p
+            (org-trim
+             (buffer-substring-no-properties (point) (line-end-position)))))
+          (end (progn (forward-line)
+                      (skip-chars-forward " \r\t\n" limit)
+                      (if (eobp) (point) (line-beginning-position)))))
       (list 'babel-call
            (nconc
-            (list :begin begin
+            (list :call call
+                  :inside-header inside-header
+                  :arguments arguments
+                  :end-header end-header
+                  :begin begin
                   :end end
-                  :info info
-                  :post-blank (count-lines pos-before-blank end)
+                  :value value
+                  :post-blank (count-lines before-blank end)
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-babel-call-interpreter (babel-call contents)
-  "Interpret BABEL-CALL element as Org syntax.
-CONTENTS is nil."
-  (let* ((babel-info (org-element-property :info babel-call))
-        (main (car babel-info))
-        (post-options (nth 1 babel-info)))
-    (concat "#+CALL: "
-           (if (not (string-match "\\[\\(\\[.*?\\]\\)\\]" main)) main
-             ;; Remove redundant square brackets.
-             (replace-match (match-string 1 main) nil nil main))
-           (and post-options (format "[%s]" post-options)))))
+(defun org-element-babel-call-interpreter (babel-call _)
+  "Interpret BABEL-CALL element as Org syntax."
+  (concat "#+CALL: "
+         (org-element-property :call babel-call)
+         (let ((h (org-element-property :inside-header babel-call)))
+           (and h (format "[%s]" h)))
+         (concat "(" (org-element-property :arguments babel-call) ")")
+         (let ((h (org-element-property :end-header babel-call)))
+           (and h (concat " " h)))))
 
 
 ;;;; Clock
@@ -1559,8 +1691,8 @@ CONTENTS is nil."
 LIMIT bounds the search.
 
 Return a list whose CAR is `clock' and CDR is a plist containing
-`:status', `:value', `:time', `:begin', `:end' and `:post-blank'
-as keywords."
+`:status', `:value', `:time', `:begin', `:end', `:post-blank' and
+`:post-affiliated' as keywords."
   (save-excursion
     (let* ((case-fold-search nil)
           (begin (point))
@@ -1570,7 +1702,7 @@ as keywords."
           (duration (and (search-forward " => " (line-end-position) t)
                          (progn (skip-chars-forward " \t")
                                 (looking-at "\\(\\S-+\\)[ \t]*$"))
-                         (org-match-string-no-properties 1)))
+                         (match-string-no-properties 1)))
           (status (if duration 'closed 'running))
           (post-blank (let ((before-blank (progn (forward-line) (point))))
                         (skip-chars-forward " \r\t\n" limit)
@@ -1584,11 +1716,11 @@ as keywords."
                  :duration duration
                  :begin begin
                  :end end
-                 :post-blank post-blank)))))
+                 :post-blank post-blank
+                 :post-affiliated begin)))))
 
-(defun org-element-clock-interpreter (clock contents)
-  "Interpret CLOCK element as Org syntax.
-CONTENTS is nil."
+(defun org-element-clock-interpreter (clock _)
+  "Interpret CLOCK element as Org syntax."
   (concat org-clock-string " "
          (org-element-timestamp-interpreter
           (org-element-property :value clock) nil)
@@ -1647,7 +1779,7 @@ Assume point is at comment beginning."
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-comment-interpreter (comment contents)
+(defun org-element-comment-interpreter (comment _)
   "Interpret COMMENT element as Org syntax.
 CONTENTS is nil."
   (replace-regexp-in-string "^" "# " (org-element-property :value comment)))
@@ -1664,8 +1796,8 @@ keyword and CDR is a plist of affiliated keywords along 
with
 their value.
 
 Return a list whose CAR is `comment-block' and CDR is a plist
-containing `:begin', `:end', `:hiddenp', `:value', `:post-blank'
-and `:post-affiliated' keywords.
+containing `:begin', `:end', `:value', `:post-blank' and
+`:post-affiliated' keywords.
 
 Assume point is at comment block beginning."
   (let ((case-fold-search t))
@@ -1678,7 +1810,6 @@ Assume point is at comment block beginning."
          (let* ((begin (car affiliated))
                 (post-affiliated (point))
                 (contents-begin (progn (forward-line) (point)))
-                (hidden (org-invisible-p2))
                 (pos-before-blank (progn (goto-char contents-end)
                                          (forward-line)
                                          (point)))
@@ -1691,16 +1822,16 @@ Assume point is at comment block beginning."
                   (list :begin begin
                         :end end
                         :value value
-                        :hiddenp hidden
                         :post-blank (count-lines pos-before-blank end)
                         :post-affiliated post-affiliated)
                   (cdr affiliated)))))))))
 
-(defun org-element-comment-block-interpreter (comment-block contents)
-  "Interpret COMMENT-BLOCK element as Org syntax.
-CONTENTS is nil."
+(defun org-element-comment-block-interpreter (comment-block _)
+  "Interpret COMMENT-BLOCK element as Org syntax."
   (format "#+BEGIN_COMMENT\n%s#+END_COMMENT"
-         (org-remove-indentation (org-element-property :value comment-block))))
+         (org-element-normalize-string
+          (org-remove-indentation
+           (org-element-property :value comment-block)))))
 
 
 ;;;; Diary Sexp
@@ -1720,7 +1851,7 @@ containing `:begin', `:end', `:value', `:post-blank' and
     (let ((begin (car affiliated))
          (post-affiliated (point))
          (value (progn (looking-at "\\(%%(.*\\)[ \t]*$")
-                       (org-match-string-no-properties 1)))
+                       (match-string-no-properties 1)))
          (pos-before-blank (progn (forward-line) (point)))
          (end (progn (skip-chars-forward " \r\t\n" limit)
                      (if (eobp) (point) (line-beginning-position)))))
@@ -1733,43 +1864,13 @@ containing `:begin', `:end', `:value', `:post-blank' and
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-diary-sexp-interpreter (diary-sexp contents)
-  "Interpret DIARY-SEXP as Org syntax.
-CONTENTS is nil."
+(defun org-element-diary-sexp-interpreter (diary-sexp _)
+  "Interpret DIARY-SEXP as Org syntax."
   (org-element-property :value diary-sexp))
 
 
 ;;;; Example Block
 
-(defun org-element--remove-indentation (s &optional n)
-  "Remove maximum common indentation in string S and return it.
-When optional argument N is a positive integer, remove exactly
-that much characters from indentation, if possible, or return
-S as-is otherwise.  Unlike to `org-remove-indentation', this
-function doesn't call `untabify' on S."
-  (catch 'exit
-    (with-temp-buffer
-      (insert s)
-      (goto-char (point-min))
-      ;; Find maximum common indentation, if not specified.
-      (setq n (or n
-                  (let ((min-ind (point-max)))
-                   (save-excursion
-                     (while (re-search-forward "^[ \t]*\\S-" nil t)
-                       (let ((ind (1- (current-column))))
-                         (if (zerop ind) (throw 'exit s)
-                           (setq min-ind (min min-ind ind))))))
-                   min-ind)))
-      (if (zerop n) s
-       ;; Remove exactly N indentation, but give up if not possible.
-       (while (not (eobp))
-         (let ((ind (progn (skip-chars-forward " \t") (current-column))))
-           (cond ((eolp) (delete-region (line-beginning-position) (point)))
-                 ((< ind n) (throw 'exit s))
-                 (t (org-indent-line-to (- ind n))))
-           (forward-line)))
-       (buffer-string)))))
-
 (defun org-element-example-block-parser (limit affiliated)
   "Parse an example block.
 
@@ -1780,9 +1881,8 @@ their value.
 
 Return a list whose CAR is `example-block' and CDR is a plist
 containing `:begin', `:end', `:number-lines', `:preserve-indent',
-`:retain-labels', `:use-labels', `:label-fmt', `:hiddenp',
-`:switches', `:value', `:post-blank' and `:post-affiliated'
-keywords."
+`:retain-labels', `:use-labels', `:label-fmt', `:switches',
+`:value', `:post-blank' and `:post-affiliated' keywords."
   (let ((case-fold-search t))
     (if (not (save-excursion
               (re-search-forward "^[ \t]*#\\+END_EXAMPLE[ \t]*$" limit t)))
@@ -1793,15 +1893,22 @@ keywords."
          (let* ((switches
                  (progn
                    (looking-at "^[ \t]*#\\+BEGIN_EXAMPLE\\(?: +\\(.*\\)\\)?")
-                   (org-match-string-no-properties 1)))
-                ;; Switches analysis
+                   (match-string-no-properties 1)))
+                ;; Switches analysis.
                 (number-lines
-                 (cond ((not switches) nil)
-                       ((string-match "-n\\>" switches) 'new)
-                       ((string-match "+n\\>" switches) 'continued)))
+                 (and switches
+                      (string-match "\\([-+]\\)n\\(?: *\\([0-9]+\\)\\)?\\>"
+                                    switches)
+                      (cons
+                       (if (equal (match-string 1 switches) "-")
+                           'new
+                         'continued)
+                       (if (not (match-end 2)) 0
+                         ;; Subtract 1 to give number of lines before
+                         ;; first line.
+                         (1- (string-to-number (match-string 2 switches)))))))
                 (preserve-indent
-                 (or org-src-preserve-indentation
-                     (and switches (string-match "-i\\>" switches))))
+                 (and switches (string-match "-i\\>" switches)))
                 ;; Should labels be retained in (or stripped from) example
                 ;; blocks?
                 (retain-labels
@@ -1821,14 +1928,10 @@ keywords."
                 ;; Standard block parsing.
                 (begin (car affiliated))
                 (post-affiliated (point))
-                (block-ind (progn (skip-chars-forward " \t") (current-column)))
-                (contents-begin (progn (forward-line) (point)))
-                (hidden (org-invisible-p2))
-                (value (org-element--remove-indentation
-                        (org-unescape-code-in-string
-                         (buffer-substring-no-properties
-                          contents-begin contents-end))
-                        (and preserve-indent block-ind)))
+                (contents-begin (line-beginning-position 2))
+                (value (org-unescape-code-in-string
+                        (buffer-substring-no-properties
+                         contents-begin contents-end)))
                 (pos-before-blank (progn (goto-char contents-end)
                                          (forward-line)
                                          (point)))
@@ -1845,18 +1948,21 @@ keywords."
                         :retain-labels retain-labels
                         :use-labels use-labels
                         :label-fmt label-fmt
-                        :hiddenp hidden
                         :post-blank (count-lines pos-before-blank end)
                         :post-affiliated post-affiliated)
                   (cdr affiliated)))))))))
 
-(defun org-element-example-block-interpreter (example-block contents)
-  "Interpret EXAMPLE-BLOCK element as Org syntax.
-CONTENTS is nil."
-  (let ((switches (org-element-property :switches example-block)))
+(defun org-element-example-block-interpreter (example-block _)
+  "Interpret EXAMPLE-BLOCK element as Org syntax."
+  (let ((switches (org-element-property :switches example-block))
+       (value (org-element-property :value example-block)))
     (concat "#+BEGIN_EXAMPLE" (and switches (concat " " switches)) "\n"
-           (org-escape-code-in-string
-            (org-element-property :value example-block))
+           (org-element-normalize-string
+            (org-escape-code-in-string
+             (if (or org-src-preserve-indentation
+                     (org-element-property :preserve-indent example-block))
+                 value
+               (org-remove-indentation value))))
            "#+END_EXAMPLE")))
 
 
@@ -1871,49 +1977,48 @@ keyword and CDR is a plist of affiliated keywords along 
with
 their value.
 
 Return a list whose CAR is `export-block' and CDR is a plist
-containing `:begin', `:end', `:type', `:hiddenp', `:value',
-`:post-blank' and `:post-affiliated' keywords.
+containing `:begin', `:end', `:type', `:value', `:post-blank' and
+`:post-affiliated' keywords.
 
 Assume point is at export-block beginning."
-  (let* ((case-fold-search t)
-        (type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
-                     (upcase (org-match-string-no-properties 1)))))
+  (let* ((case-fold-search t))
     (if (not (save-excursion
-              (re-search-forward
-               (format "^[ \t]*#\\+END_%s[ \t]*$" type) limit t)))
+              (re-search-forward "^[ \t]*#\\+END_EXPORT[ \t]*$" limit t)))
        ;; Incomplete block: parse it as a paragraph.
        (org-element-paragraph-parser limit affiliated)
-      (let ((contents-end (match-beginning 0)))
-       (save-excursion
-         (let* ((begin (car affiliated))
-                (post-affiliated (point))
-                (contents-begin (progn (forward-line) (point)))
-                (hidden (org-invisible-p2))
-                (pos-before-blank (progn (goto-char contents-end)
-                                         (forward-line)
-                                         (point)))
-                (end (progn (skip-chars-forward " \r\t\n" limit)
-                            (if (eobp) (point) (line-beginning-position))))
-                (value (buffer-substring-no-properties contents-begin
-                                                       contents-end)))
-           (list 'export-block
-                 (nconc
-                  (list :begin begin
-                        :end end
-                        :type type
-                        :value value
-                        :hiddenp hidden
-                        :post-blank (count-lines pos-before-blank end)
-                        :post-affiliated post-affiliated)
-                  (cdr affiliated)))))))))
+      (save-excursion
+       (let* ((contents-end (match-beginning 0))
+              (backend
+               (progn
+                 (looking-at
+                  "[ \t]*#\\+BEGIN_EXPORT\\(?:[ \t]+\\(\\S-+\\)\\)?[ \t]*$")
+                 (match-string-no-properties 1)))
+              (begin (car affiliated))
+              (post-affiliated (point))
+              (contents-begin (progn (forward-line) (point)))
+              (pos-before-blank (progn (goto-char contents-end)
+                                       (forward-line)
+                                       (point)))
+              (end (progn (skip-chars-forward " \r\t\n" limit)
+                          (if (eobp) (point) (line-beginning-position))))
+              (value (org-unescape-code-in-string
+                      (buffer-substring-no-properties contents-begin
+                                                      contents-end))))
+         (list 'export-block
+               (nconc
+                (list :type (and backend (upcase backend))
+                      :begin begin
+                      :end end
+                      :value value
+                      :post-blank (count-lines pos-before-blank end)
+                      :post-affiliated post-affiliated)
+                (cdr affiliated))))))))
 
-(defun org-element-export-block-interpreter (export-block contents)
-  "Interpret EXPORT-BLOCK element as Org syntax.
-CONTENTS is nil."
-  (let ((type (org-element-property :type export-block)))
-    (concat (format "#+BEGIN_%s\n" type)
-           (org-element-property :value export-block)
-           (format "#+END_%s" type))))
+(defun org-element-export-block-interpreter (export-block _)
+  "Interpret EXPORT-BLOCK element as Org syntax."
+  (format "#+BEGIN_EXPORT %s\n%s#+END_EXPORT"
+         (org-element-property :type export-block)
+         (org-element-property :value export-block)))
 
 
 ;;;; Fixed-width
@@ -1958,9 +2063,8 @@ Assume point is at the beginning of the fixed-width area."
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-fixed-width-interpreter (fixed-width contents)
-  "Interpret FIXED-WIDTH element as Org syntax.
-CONTENTS is nil."
+(defun org-element-fixed-width-interpreter (fixed-width _)
+  "Interpret FIXED-WIDTH element as Org syntax."
   (let ((value (org-element-property :value fixed-width)))
     (and value
         (replace-regexp-in-string
@@ -1995,9 +2099,8 @@ keywords."
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-horizontal-rule-interpreter (horizontal-rule contents)
-  "Interpret HORIZONTAL-RULE element as Org syntax.
-CONTENTS is nil."
+(defun org-element-horizontal-rule-interpreter (&rest _)
+  "Interpret HORIZONTAL-RULE element as Org syntax."
   "-----")
 
 
@@ -2015,10 +2118,13 @@ Return a list whose CAR is `keyword' and CDR is a plist
 containing `:key', `:value', `:begin', `:end', `:post-blank' and
 `:post-affiliated' keywords."
   (save-excursion
-    (let ((begin (car affiliated))
+    ;; An orphaned affiliated keyword is considered as a regular
+    ;; keyword.  In this case AFFILIATED is nil, so we take care of
+    ;; this corner case.
+    (let ((begin (or (car affiliated) (point)))
          (post-affiliated (point))
          (key (progn (looking-at "[ \t]*#\\+\\(\\S-+*\\):")
-                     (upcase (org-match-string-no-properties 1))))
+                     (upcase (match-string-no-properties 1))))
          (value (org-trim (buffer-substring-no-properties
                            (match-end 0) (point-at-eol))))
          (pos-before-blank (progn (forward-line) (point)))
@@ -2034,9 +2140,8 @@ containing `:key', `:value', `:begin', `:end', 
`:post-blank' and
                   :post-affiliated post-affiliated)
             (cdr affiliated))))))
 
-(defun org-element-keyword-interpreter (keyword contents)
-  "Interpret KEYWORD element as Org syntax.
-CONTENTS is nil."
+(defun org-element-keyword-interpreter (keyword _)
+  "Interpret KEYWORD element as Org syntax."
   (format "#+%s: %s"
          (org-element-property :key keyword)
          (org-element-property :value keyword)))
@@ -2044,6 +2149,18 @@ CONTENTS is nil."
 
 ;;;; Latex Environment
 
+(defconst org-element--latex-begin-environment
+  "^[ \t]*\\\\begin{\\([A-Za-z0-9*]+\\)}"
+  "Regexp matching the beginning of a LaTeX environment.
+The environment is captured by the first group.
+
+See also `org-element--latex-end-environment'.")
+
+(defconst org-element--latex-end-environment
+  "\\\\end{%s}[ \t]*$"
+  "Format string matching the ending of a LaTeX environment.
+See also `org-element--latex-begin-environment'.")
+
 (defun org-element-latex-environment-parser (limit affiliated)
   "Parse a LaTeX environment.
 
@@ -2060,8 +2177,8 @@ Assume point is at the beginning of the latex 
environment."
   (save-excursion
     (let ((case-fold-search t)
          (code-begin (point)))
-      (looking-at "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}")
-      (if (not (re-search-forward (format "^[ \t]*\\\\end{%s}[ \t]*$"
+      (looking-at org-element--latex-begin-environment)
+      (if (not (re-search-forward (format org-element--latex-end-environment
                                          (regexp-quote (match-string 1)))
                                  limit t))
          ;; Incomplete latex environment: parse it as a paragraph.
@@ -2080,9 +2197,8 @@ Assume point is at the beginning of the latex 
environment."
                       :post-affiliated code-begin)
                 (cdr affiliated))))))))
 
-(defun org-element-latex-environment-interpreter (latex-environment contents)
-  "Interpret LATEX-ENVIRONMENT element as Org syntax.
-CONTENTS is nil."
+(defun org-element-latex-environment-interpreter (latex-environment _)
+  "Interpret LATEX-ENVIRONMENT element as Org syntax."
   (org-element-property :value latex-environment))
 
 
@@ -2094,12 +2210,13 @@ CONTENTS is nil."
 LIMIT bounds the search.
 
 Return a list whose CAR is `node-property' and CDR is a plist
-containing `:key', `:value', `:begin', `:end' and `:post-blank'
-keywords."
+containing `:key', `:value', `:begin', `:end', `:post-blank' and
+`:post-affiliated' keywords."
   (looking-at org-property-re)
-  (let ((begin (point))
-       (key   (org-match-string-no-properties 2))
-       (value (org-match-string-no-properties 3))
+  (let ((case-fold-search t)
+       (begin (point))
+       (key   (match-string-no-properties 2))
+       (value (match-string-no-properties 3))
        (end (save-excursion
               (end-of-line)
               (if (re-search-forward org-property-re limit t)
@@ -2110,11 +2227,11 @@ keywords."
                :value value
                :begin begin
                :end end
-               :post-blank 0))))
+               :post-blank 0
+               :post-affiliated begin))))
 
-(defun org-element-node-property-interpreter (node-property contents)
-  "Interpret NODE-PROPERTY element as Org syntax.
-CONTENTS is nil."
+(defun org-element-node-property-interpreter (node-property _)
+  "Interpret NODE-PROPERTY element as Org syntax."
   (format org-property-format
          (format ":%s:" (org-element-property :key node-property))
          (or (org-element-property :value node-property) "")))
@@ -2141,66 +2258,42 @@ Assume point is at the beginning of the paragraph."
           (before-blank
            (let ((case-fold-search t))
              (end-of-line)
-             (if (not (re-search-forward
-                       org-element-paragraph-separate limit 'm))
-                 limit
-               ;; A matching `org-element-paragraph-separate' is not
-               ;; necessarily the end of the paragraph.  In
-               ;; particular, lines starting with # or : as a first
-               ;; non-space character are ambiguous.  We have to
-               ;; check if they are valid Org syntax (e.g., not an
-               ;; incomplete keyword).
-               (beginning-of-line)
-               (while (not
-                       (or
-                        ;; There's no ambiguity for other symbols or
-                        ;; empty lines: stop here.
-                        (looking-at "[ \t]*\\(?:[^:#]\\|$\\)")
-                        ;; Stop at valid fixed-width areas.
-                        (looking-at "[ \t]*:\\(?: \\|$\\)")
-                        ;; Stop at drawers.
-                        (and (looking-at org-drawer-regexp)
-                             (save-excursion
-                               (re-search-forward
-                                "^[ \t]*:END:[ \t]*$" limit t)))
-                        ;; Stop at valid comments.
-                        (looking-at "[ \t]*#\\(?: \\|$\\)")
-                        ;; Stop at valid dynamic blocks.
-                        (and (looking-at org-dblock-start-re)
-                             (save-excursion
-                               (re-search-forward
-                                "^[ \t]*#\\+END:?[ \t]*$" limit t)))
-                        ;; Stop at valid blocks.
-                        (and (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
-                             (save-excursion
-                               (re-search-forward
-                                (format "^[ \t]*#\\+END_%s[ \t]*$"
-                                        (regexp-quote
-                                         (org-match-string-no-properties 1)))
-                                limit t)))
-                        ;; Stop at valid latex environments.
-                        (and (looking-at
-                              "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}")
-                             (save-excursion
-                               (re-search-forward
-                                (format "^[ \t]*\\\\end{%s}[ \t]*$"
-                                        (regexp-quote
-                                         (org-match-string-no-properties 1)))
-                                limit t)))
-                        ;; Stop at valid keywords.
-                        (looking-at "[ \t]*#\\+\\S-+:")
-                        ;; Skip everything else.
-                        (not
-                         (progn
-                           (end-of-line)
-                           (re-search-forward org-element-paragraph-separate
-                                              limit 'm)))))
-                 (beginning-of-line)))
+             ;; A matching `org-element-paragraph-separate' is not
+             ;; necessarily the end of the paragraph.  In particular,
+             ;; drawers, blocks or LaTeX environments opening lines
+             ;; must be closed.  Moreover keywords with a secondary
+             ;; value must belong to "dual keywords".
+             (while (not
+                     (cond
+                      ((not (and (re-search-forward
+                                  org-element-paragraph-separate limit 'move)
+                                 (progn (beginning-of-line) t))))
+                      ((looking-at org-drawer-regexp)
+                       (save-excursion
+                         (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
+                      ((looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
+                       (save-excursion
+                         (re-search-forward
+                          (format "^[ \t]*#\\+END_%s[ \t]*$"
+                                  (regexp-quote (match-string 1)))
+                          limit t)))
+                      ((looking-at org-element--latex-begin-environment)
+                       (save-excursion
+                         (re-search-forward
+                          (format org-element--latex-end-environment
+                                  (regexp-quote (match-string 1)))
+                          limit t)))
+                      ((looking-at "[ \t]*#\\+\\(\\S-+\\)\\[.*\\]:")
+                       (member-ignore-case (match-string 1)
+                                           org-element-dual-keywords))
+                      ;; Everything else is unambiguous.
+                      (t)))
+               (end-of-line))
              (if (= (point) limit) limit
                (goto-char (line-beginning-position)))))
-          (contents-end (progn (skip-chars-backward " \r\t\n" contents-begin)
-                               (forward-line)
-                               (point)))
+          (contents-end (save-excursion
+                          (skip-chars-backward " \r\t\n" contents-begin)
+                          (line-beginning-position 2)))
           (end (progn (skip-chars-forward " \r\t\n" limit)
                       (if (eobp) (point) (line-beginning-position)))))
       (list 'paragraph
@@ -2213,8 +2306,8 @@ Assume point is at the beginning of the paragraph."
                   :post-affiliated contents-begin)
             (cdr affiliated))))))
 
-(defun org-element-paragraph-interpreter (paragraph contents)
-  "Interpret PARAGRAPH element as Org syntax.
+(defun org-element-paragraph-interpreter (_ contents)
+  "Interpret paragraph element as Org syntax.
 CONTENTS is the contents of the element."
   contents)
 
@@ -2227,8 +2320,8 @@ CONTENTS is the contents of the element."
 LIMIT bounds the search.
 
 Return a list whose CAR is `planning' and CDR is a plist
-containing `:closed', `:deadline', `:scheduled', `:begin', `:end'
-and `:post-blank' keywords."
+containing `:closed', `:deadline', `:scheduled', `:begin',
+`:end', `:post-blank' and `:post-affiliated' keywords."
   (save-excursion
     (let* ((case-fold-search nil)
           (begin (point))
@@ -2254,13 +2347,13 @@ and `:post-blank' keywords."
                  :scheduled scheduled
                  :begin begin
                  :end end
-                 :post-blank post-blank)))))
+                 :post-blank post-blank
+                 :post-affiliated begin)))))
 
-(defun org-element-planning-interpreter (planning contents)
-  "Interpret PLANNING element as Org syntax.
-CONTENTS is nil."
+(defun org-element-planning-interpreter (planning _)
+  "Interpret PLANNING element as Org syntax."
   (mapconcat
-   'identity
+   #'identity
    (delq nil
         (list (let ((deadline (org-element-property :deadline planning)))
                 (when deadline
@@ -2277,37 +2370,6 @@ CONTENTS is nil."
    " "))
 
 
-;;;; Quote Section
-
-(defun org-element-quote-section-parser (limit)
-  "Parse a quote section.
-
-LIMIT bounds the search.
-
-Return a list whose CAR is `quote-section' and CDR is a plist
-containing `:begin', `:end', `:value' and `:post-blank' keywords.
-
-Assume point is at beginning of the section."
-  (save-excursion
-    (let* ((begin (point))
-          (end (progn (org-with-limited-levels (outline-next-heading))
-                      (point)))
-          (pos-before-blank (progn (skip-chars-backward " \r\t\n")
-                                   (forward-line)
-                                   (point)))
-          (value (buffer-substring-no-properties begin pos-before-blank)))
-      (list 'quote-section
-           (list :begin begin
-                 :end end
-                 :value value
-                 :post-blank (count-lines pos-before-blank end))))))
-
-(defun org-element-quote-section-interpreter (quote-section contents)
-  "Interpret QUOTE-SECTION element as Org syntax.
-CONTENTS is nil."
-  (org-element-property :value quote-section))
-
-
 ;;;; Src Block
 
 (defun org-element-src-block-parser (limit affiliated)
@@ -2320,9 +2382,9 @@ their value.
 
 Return a list whose CAR is `src-block' and CDR is a plist
 containing `:language', `:switches', `:parameters', `:begin',
-`:end', `:hiddenp', `:number-lines', `:retain-labels',
-`:use-labels', `:label-fmt', `:preserve-indent', `:value',
-`:post-blank' and `:post-affiliated' keywords.
+`:end', `:number-lines', `:retain-labels', `:use-labels',
+`:label-fmt', `:preserve-indent', `:value', `:post-blank' and
+`:post-affiliated' keywords.
 
 Assume point is at the beginning of the block."
   (let ((case-fold-search t))
@@ -2338,23 +2400,30 @@ Assume point is at the beginning of the block."
                 (language
                  (progn
                    (looking-at
-                    (concat "^[ \t]*#\\+BEGIN_SRC"
-                            "\\(?: +\\(\\S-+\\)\\)?"
-                            "\\(\\(?: +\\(?:-l 
\".*?\"\\|[-+][A-Za-z]\\)\\)+\\)?"
-                            "\\(.*\\)[ \t]*$"))
-                   (org-match-string-no-properties 1)))
+                    "^[ \t]*#\\+BEGIN_SRC\
+\\(?: +\\(\\S-+\\)\\)?\
+\\(\\(?: +\\(?:-\\(?:l \".+\"\\|[ikr]\\)\\|[-+]n\\(?: *[0-9]+\\)?\\)\\)+\\)?\
+\\(.*\\)[ \t]*$")
+                   (match-string-no-properties 1)))
                 ;; Get switches.
-                (switches (org-match-string-no-properties 2))
+                (switches (match-string-no-properties 2))
                 ;; Get parameters.
-                (parameters (org-match-string-no-properties 3))
-                ;; Switches analysis
+                (parameters (match-string-no-properties 3))
+                ;; Switches analysis.
                 (number-lines
-                 (cond ((not switches) nil)
-                       ((string-match "-n\\>" switches) 'new)
-                       ((string-match "+n\\>" switches) 'continued)))
-                (preserve-indent (or org-src-preserve-indentation
-                                     (and switches
-                                          (string-match "-i\\>" switches))))
+                 (and switches
+                      (string-match "\\([-+]\\)n\\(?: *\\([0-9]+\\)\\)?\\>"
+                                    switches)
+                      (cons
+                       (if (equal (match-string 1 switches) "-")
+                           'new
+                         'continued)
+                       (if (not (match-end 2)) 0
+                         ;; Subtract 1 to give number of lines before
+                         ;; first line.
+                         (1- (string-to-number (match-string 2 switches)))))))
+                (preserve-indent (and switches
+                                      (string-match "-i\\>" switches)))
                 (label-fmt
                  (and switches
                       (string-match "-l +\"\\([^\"\n]+\\)\"" switches)
@@ -2371,16 +2440,10 @@ Assume point is at the beginning of the block."
                  (or (not switches)
                      (and retain-labels
                           (not (string-match "-k\\>" switches)))))
-                ;; Indentation.
-                (block-ind (progn (skip-chars-forward " \t") (current-column)))
-                ;; Get visibility status.
-                (hidden (progn (forward-line) (org-invisible-p2)))
                 ;; Retrieve code.
-                (value (org-element--remove-indentation
-                        (org-unescape-code-in-string
-                         (buffer-substring-no-properties
-                          (point) contents-end))
-                        (and preserve-indent block-ind)))
+                (value (org-unescape-code-in-string
+                        (buffer-substring-no-properties
+                         (line-beginning-position 2) contents-end)))
                 (pos-before-blank (progn (goto-char contents-end)
                                          (forward-line)
                                          (point)))
@@ -2401,32 +2464,33 @@ Assume point is at the beginning of the block."
                         :retain-labels retain-labels
                         :use-labels use-labels
                         :label-fmt label-fmt
-                        :hiddenp hidden
                         :value value
                         :post-blank (count-lines pos-before-blank end)
                         :post-affiliated post-affiliated)
                   (cdr affiliated)))))))))
 
-(defun org-element-src-block-interpreter (src-block contents)
-  "Interpret SRC-BLOCK element as Org syntax.
-CONTENTS is nil."
+(defun org-element-src-block-interpreter (src-block _)
+  "Interpret SRC-BLOCK element as Org syntax."
   (let ((lang (org-element-property :language src-block))
        (switches (org-element-property :switches src-block))
        (params (org-element-property :parameters src-block))
-       (value (let ((val (org-element-property :value src-block)))
-                (cond
-                 ((org-element-property :preserve-indent src-block) val)
-                 ((zerop org-edit-src-content-indentation) val)
-                 (t
-                  (let ((ind (make-string
-                              org-edit-src-content-indentation 32)))
-                    (replace-regexp-in-string
-                     "\\(^\\)[ \t]*\\S-" ind val nil nil 1)))))))
+       (value
+        (let ((val (org-element-property :value src-block)))
+          (cond
+           ((or org-src-preserve-indentation
+                (org-element-property :preserve-indent src-block))
+            val)
+           ((zerop org-edit-src-content-indentation)
+            (org-remove-indentation val))
+           (t
+            (let ((ind (make-string org-edit-src-content-indentation ?\s)))
+              (replace-regexp-in-string
+               "^" ind (org-remove-indentation val))))))))
     (concat (format "#+BEGIN_SRC%s\n"
                    (concat (and lang (concat " " lang))
                            (and switches (concat " " switches))
                            (and params (concat " " params))))
-           (org-escape-code-in-string value)
+           (org-element-normalize-string (org-escape-code-in-string value))
            "#+END_SRC")))
 
 
@@ -2449,15 +2513,17 @@ Assume point is at the beginning of the table."
   (save-excursion
     (let* ((case-fold-search t)
           (table-begin (point))
-          (type (if (org-at-table.el-p) 'table.el 'org))
+          (type (if (looking-at "[ \t]*|") 'org 'table.el))
+           (end-re (format "^[ \t]*\\($\\|[^| \t%s]\\)"
+                          (if (eq type 'org) "" "+")))
           (begin (car affiliated))
           (table-end
-           (if (re-search-forward org-table-any-border-regexp limit 'm)
+           (if (re-search-forward end-re limit 'move)
                (goto-char (match-beginning 0))
              (point)))
           (tblfm (let (acc)
                    (while (looking-at "[ \t]*#\\+TBLFM: +\\(.*\\)[ \t]*$")
-                     (push (org-match-string-no-properties 1) acc)
+                     (push (match-string-no-properties 1) acc)
                      (forward-line))
                    acc))
           (pos-before-blank (point))
@@ -2496,41 +2562,38 @@ CONTENTS is a string, if table's type is `org', or nil."
 
 ;;;; Table Row
 
-(defun org-element-table-row-parser (limit)
+(defun org-element-table-row-parser (_)
   "Parse table row at point.
 
-LIMIT bounds the search.
-
 Return a list whose CAR is `table-row' and CDR is a plist
 containing `:begin', `:end', `:contents-begin', `:contents-end',
-`:type' and `:post-blank' keywords."
+`:type', `:post-blank' and `:post-affiliated' keywords."
   (save-excursion
     (let* ((type (if (looking-at "^[ \t]*|-") 'rule 'standard))
           (begin (point))
           ;; A table rule has no contents.  In that case, ensure
           ;; CONTENTS-BEGIN matches CONTENTS-END.
-          (contents-begin (and (eq type 'standard)
-                               (search-forward "|")
-                               (point)))
+          (contents-begin (and (eq type 'standard) (search-forward "|")))
           (contents-end (and (eq type 'standard)
                              (progn
                                (end-of-line)
                                (skip-chars-backward " \t")
                                (point))))
-          (end (progn (forward-line) (point))))
+          (end (line-beginning-position 2)))
       (list 'table-row
            (list :type type
                  :begin begin
                  :end end
                  :contents-begin contents-begin
                  :contents-end contents-end
-                 :post-blank 0)))))
+                 :post-blank 0
+                 :post-affiliated begin)))))
 
 (defun org-element-table-row-interpreter (table-row contents)
   "Interpret TABLE-ROW element as Org syntax.
 CONTENTS is the contents of the table row."
   (if (eq (org-element-property :type table-row) 'rule) "|-"
-    (concat "| " contents)))
+    (concat "|" contents)))
 
 
 ;;;; Verse Block
@@ -2545,7 +2608,7 @@ their value.
 
 Return a list whose CAR is `verse-block' and CDR is a plist
 containing `:begin', `:end', `:contents-begin', `:contents-end',
-`:hiddenp', `:post-blank' and `:post-affiliated' keywords.
+`:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at beginning of the block."
   (let ((case-fold-search t))
@@ -2557,8 +2620,7 @@ Assume point is at beginning of the block."
        (save-excursion
          (let* ((begin (car affiliated))
                 (post-affiliated (point))
-                (hidden (progn (forward-line) (org-invisible-p2)))
-                (contents-begin (point))
+                (contents-begin (progn (forward-line) (point)))
                 (pos-before-blank (progn (goto-char contents-end)
                                          (forward-line)
                                          (point)))
@@ -2570,13 +2632,12 @@ Assume point is at beginning of the block."
                         :end end
                         :contents-begin contents-begin
                         :contents-end contents-end
-                        :hiddenp hidden
                         :post-blank (count-lines pos-before-blank end)
                         :post-affiliated post-affiliated)
                   (cdr affiliated)))))))))
 
-(defun org-element-verse-block-interpreter (verse-block contents)
-  "Interpret VERSE-BLOCK element as Org syntax.
+(defun org-element-verse-block-interpreter (_ contents)
+  "Interpret verse-block element as Org syntax.
 CONTENTS is verse block contents."
   (format "#+BEGIN_VERSE\n%s#+END_VERSE" contents))
 
@@ -2584,373 +2645,289 @@ CONTENTS is verse block contents."
 
 ;;; Objects
 ;;
-;; Unlike to elements, interstices can be found between objects.
-;; That's why, along with the parser, successor functions are provided
-;; for each object.  Some objects share the same successor (e.g.,
-;; `code' and `verbatim' objects).
-;;
-;; A successor must accept a single argument bounding the search.  It
-;; will return either a cons cell whose CAR is the object's type, as
-;; a symbol, and CDR the position of its next occurrence, or nil.
-;;
-;; Successors follow the naming convention:
-;; org-element-NAME-successor, where NAME is the name of the
-;; successor, as defined in `org-element-all-successors'.
+;; Unlike to elements, raw text can be found between objects.  Hence,
+;; `org-element--object-lex' is provided to find the next object in
+;; buffer.
 ;;
 ;; Some object types (e.g., `italic') are recursive.  Restrictions on
 ;; object types they can contain will be specified in
 ;; `org-element-object-restrictions'.
 ;;
-;; Adding a new type of object is simple.  Implement a successor,
-;; a parser, and an interpreter for it, all following the naming
-;; convention.  Register type in `org-element-all-objects' and
-;; successor in `org-element-all-successors'.  Maybe tweak
-;; restrictions about it, and that's it.
-
+;; Creating a new type of object requires to alter
+;; `org-element--object-regexp' and `org-element--object-lex', add the
+;; new type in `org-element-all-objects', and possibly add
+;; restrictions in `org-element-object-restrictions'.
 
 ;;;; Bold
 
 (defun org-element-bold-parser ()
-  "Parse bold object at point.
+  "Parse bold object at point, if any.
 
-Return a list whose CAR is `bold' and CDR is a plist with
-`:begin', `:end', `:contents-begin' and `:contents-end' and
-`:post-blank' keywords.
+When at a bold object, return a list whose car is `bold' and cdr
+is a plist with `:begin', `:end', `:contents-begin' and
+`:contents-end' and `:post-blank' keywords.  Otherwise, return
+nil.
 
 Assume point is at the first star marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (contents-begin (match-beginning 4))
-         (contents-end (match-end 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'bold
-           (list :begin begin
-                 :end end
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
-
-(defun org-element-bold-interpreter (bold contents)
-  "Interpret BOLD object as Org syntax.
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (contents-begin (match-beginning 4))
+           (contents-end (match-end 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'bold
+             (list :begin begin
+                   :end end
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
+
+(defun org-element-bold-interpreter (_ contents)
+  "Interpret bold object as Org syntax.
 CONTENTS is the contents of the object."
   (format "*%s*" contents))
 
-(defun org-element-text-markup-successor ()
-  "Search for the next text-markup object.
-
-Return value is a cons cell whose CAR is a symbol among `bold',
-`italic', `underline', `strike-through', `code' and `verbatim'
-and CDR is beginning position."
-  (save-excursion
-    (unless (bolp) (backward-char))
-    (when (re-search-forward org-emph-re nil t)
-      (let ((marker (match-string 3)))
-       (cons (cond
-              ((equal marker "*") 'bold)
-              ((equal marker "/") 'italic)
-              ((equal marker "_") 'underline)
-              ((equal marker "+") 'strike-through)
-              ((equal marker "~") 'code)
-              ((equal marker "=") 'verbatim)
-              (t (error "Unknown marker at %d" (match-beginning 3))))
-             (match-beginning 2))))))
-
 
 ;;;; Code
 
 (defun org-element-code-parser ()
-  "Parse code object at point.
+  "Parse code object at point, if any.
 
-Return a list whose CAR is `code' and CDR is a plist with
-`:value', `:begin', `:end' and `:post-blank' keywords.
+When at a code object, return a list whose car is `code' and cdr
+is a plist with `:value', `:begin', `:end' and `:post-blank'
+keywords.  Otherwise, return nil.
 
 Assume point is at the first tilde marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (value (org-match-string-no-properties 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'code
-           (list :value value
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-code-interpreter (code contents)
-  "Interpret CODE object as Org syntax.
-CONTENTS is nil."
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (value (match-string-no-properties 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'code
+             (list :value value
+                   :begin begin
+                   :end end
+                   :post-blank post-blank))))))
+
+(defun org-element-code-interpreter (code _)
+  "Interpret CODE object as Org syntax."
   (format "~%s~" (org-element-property :value code)))
 
 
 ;;;; Entity
 
 (defun org-element-entity-parser ()
-  "Parse entity at point.
+  "Parse entity at point, if any.
 
-Return a list whose CAR is `entity' and CDR a plist with
-`:begin', `:end', `:latex', `:latex-math-p', `:html', `:latin1',
-`:utf-8', `:ascii', `:use-brackets-p' and `:post-blank' as
-keywords.
+When at an entity, return a list whose car is `entity' and cdr
+a plist with `:begin', `:end', `:latex', `:latex-math-p',
+`:html', `:latin1', `:utf-8', `:ascii', `:use-brackets-p' and
+`:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the beginning of the entity."
-  (save-excursion
-    (looking-at 
"\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]]\\)")
-    (let* ((value (org-entity-get (match-string 1)))
-          (begin (match-beginning 0))
-          (bracketsp (string= (match-string 2) "{}"))
-          (post-blank (progn (goto-char (match-end 1))
-                             (when bracketsp (forward-char 2))
-                             (skip-chars-forward " \t")))
-          (end (point)))
-      (list 'entity
-           (list :name (car value)
-                 :latex (nth 1 value)
-                 :latex-math-p (nth 2 value)
-                 :html (nth 3 value)
-                 :ascii (nth 4 value)
-                 :latin1 (nth 5 value)
-                 :utf-8 (nth 6 value)
-                 :begin begin
-                 :end end
-                 :use-brackets-p bracketsp
-                 :post-blank post-blank)))))
-
-(defun org-element-entity-interpreter (entity contents)
-  "Interpret ENTITY object as Org syntax.
-CONTENTS is nil."
+  (catch 'no-object
+    (when (looking-at "\\\\\\(?:\\(?1:_ 
+\\)\\|\\(?1:there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\(?2:$\\|{}\\|[^[:alpha:]]\\)\\)")
+      (save-excursion
+       (let* ((value (or (org-entity-get (match-string 1))
+                         (throw 'no-object nil)))
+              (begin (match-beginning 0))
+              (bracketsp (string= (match-string 2) "{}"))
+              (post-blank (progn (goto-char (match-end 1))
+                                 (when bracketsp (forward-char 2))
+                                 (skip-chars-forward " \t")))
+              (end (point)))
+         (list 'entity
+               (list :name (car value)
+                     :latex (nth 1 value)
+                     :latex-math-p (nth 2 value)
+                     :html (nth 3 value)
+                     :ascii (nth 4 value)
+                     :latin1 (nth 5 value)
+                     :utf-8 (nth 6 value)
+                     :begin begin
+                     :end end
+                     :use-brackets-p bracketsp
+                     :post-blank post-blank)))))))
+
+(defun org-element-entity-interpreter (entity _)
+  "Interpret ENTITY object as Org syntax."
   (concat "\\"
          (org-element-property :name entity)
          (when (org-element-property :use-brackets-p entity) "{}")))
 
-(defun org-element-latex-or-entity-successor ()
-  "Search for the next latex-fragment or entity object.
-
-Return value is a cons cell whose CAR is `entity' or
-`latex-fragment' and CDR is beginning position."
-  (save-excursion
-    (unless (bolp) (backward-char))
-    (let ((matchers (cdr org-latex-regexps))
-         ;; ENTITY-RE matches both LaTeX commands and Org entities.
-         (entity-re
-          
"\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]]\\)"))
-      (when (re-search-forward
-            (concat (mapconcat #'cadr matchers "\\|") "\\|" entity-re) nil t)
-       (goto-char (match-beginning 0))
-       (if (looking-at entity-re)
-           ;; Determine if it's a real entity or a LaTeX command.
-           (cons (if (org-entity-get (match-string 1)) 'entity 'latex-fragment)
-                 (match-beginning 0))
-         ;; No entity nor command: point is at a LaTeX fragment.
-         ;; Determine its type to get the correct beginning position.
-         (cons 'latex-fragment
-               (catch 'return
-                 (dolist (e matchers)
-                   (when (looking-at (nth 1 e))
-                     (throw 'return (match-beginning (nth 2 e)))))
-                 (point))))))))
-
 
 ;;;; Export Snippet
 
 (defun org-element-export-snippet-parser ()
   "Parse export snippet at point.
 
-Return a list whose CAR is `export-snippet' and CDR a plist with
-`:begin', `:end', `:back-end', `:value' and `:post-blank' as
-keywords.
+When at an export snippet, return a list whose car is
+`export-snippet' and cdr a plist with `:begin', `:end',
+`:back-end', `:value' and `:post-blank' as keywords.  Otherwise,
+return nil.
 
 Assume point is at the beginning of the snippet."
   (save-excursion
-    (re-search-forward "@@\\([-A-Za-z0-9]+\\):" nil t)
-    (let* ((begin (match-beginning 0))
-          (back-end (org-match-string-no-properties 1))
-          (value (buffer-substring-no-properties
-                  (point)
-                  (progn (re-search-forward "@@" nil t) (match-beginning 0))))
-          (post-blank (skip-chars-forward " \t"))
-          (end (point)))
-      (list 'export-snippet
-           (list :back-end back-end
-                 :value value
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-export-snippet-interpreter (export-snippet contents)
-  "Interpret EXPORT-SNIPPET object as Org syntax.
-CONTENTS is nil."
+    (let (contents-end)
+      (when (and (looking-at "@@\\([-A-Za-z0-9]+\\):")
+                (setq contents-end
+                      (save-match-data (goto-char (match-end 0))
+                                       (re-search-forward "@@" nil t)
+                                       (match-beginning 0))))
+       (let* ((begin (match-beginning 0))
+              (back-end (match-string-no-properties 1))
+              (value (buffer-substring-no-properties
+                      (match-end 0) contents-end))
+              (post-blank (skip-chars-forward " \t"))
+              (end (point)))
+         (list 'export-snippet
+               (list :back-end back-end
+                     :value value
+                     :begin begin
+                     :end end
+                     :post-blank post-blank)))))))
+
+(defun org-element-export-snippet-interpreter (export-snippet _)
+  "Interpret EXPORT-SNIPPET object as Org syntax."
   (format "@@%s:%s@@"
          (org-element-property :back-end export-snippet)
          (org-element-property :value export-snippet)))
 
-(defun org-element-export-snippet-successor ()
-  "Search for the next export-snippet object.
-
-Return value is a cons cell whose CAR is `export-snippet' and CDR
-its beginning position."
-  (save-excursion
-    (let (beg)
-      (when (and (re-search-forward "@@[-A-Za-z0-9]+:" nil t)
-                (setq beg (match-beginning 0))
-                (search-forward "@@" nil t))
-       (cons 'export-snippet beg)))))
-
 
 ;;;; Footnote Reference
 
 (defun org-element-footnote-reference-parser ()
-  "Parse footnote reference at point.
-
-Return a list whose CAR is `footnote-reference' and CDR a plist
-with `:label', `:type', `:inline-definition', `:begin', `:end'
-and `:post-blank' as keywords."
-  (save-excursion
-    (looking-at org-footnote-re)
-    (let* ((begin (point))
-          (label (or (org-match-string-no-properties 2)
-                     (org-match-string-no-properties 3)
-                     (and (match-string 1)
-                          (concat "fn:" (org-match-string-no-properties 1)))))
-          (type (if (or (not label) (match-string 1)) 'inline 'standard))
-          (inner-begin (match-end 0))
-          (inner-end
-           (let ((count 1))
-             (forward-char)
-             (while (and (> count 0) (re-search-forward "[][]" nil t))
-               (if (equal (match-string 0) "[") (incf count) (decf count)))
-             (1- (point))))
-          (post-blank (progn (goto-char (1+ inner-end))
-                             (skip-chars-forward " \t")))
-          (end (point))
-          (footnote-reference
+  "Parse footnote reference at point, if any.
+
+When at a footnote reference, return a list whose car is
+`footnote-reference' and cdr a plist with `:label', `:type',
+`:begin', `:end', `:content-begin', `:contents-end' and
+`:post-blank' as keywords.  Otherwise, return nil."
+  (when (looking-at org-footnote-re)
+    (let ((closing (with-syntax-table org-element--pair-square-table
+                    (ignore-errors (scan-lists (point) 1 0)))))
+      (when closing
+       (save-excursion
+         (let* ((begin (point))
+                (label (match-string-no-properties 1))
+                (inner-begin (match-end 0))
+                (inner-end (1- closing))
+                (type (if (match-end 2) 'inline 'standard))
+                (post-blank (progn (goto-char closing)
+                                   (skip-chars-forward " \t")))
+                (end (point)))
            (list 'footnote-reference
                  (list :label label
                        :type type
                        :begin begin
                        :end end
-                       :post-blank post-blank))))
-      (org-element-put-property
-       footnote-reference :inline-definition
-       (and (eq type 'inline)
-           (org-element-parse-secondary-string
-            (buffer-substring inner-begin inner-end)
-            (org-element-restriction 'footnote-reference)
-            footnote-reference))))))
+                       :contents-begin (and (eq type 'inline) inner-begin)
+                       :contents-end (and (eq type 'inline) inner-end)
+                       :post-blank post-blank))))))))
 
 (defun org-element-footnote-reference-interpreter (footnote-reference contents)
   "Interpret FOOTNOTE-REFERENCE object as Org syntax.
-CONTENTS is nil."
-  (let ((label (or (org-element-property :label footnote-reference) "fn:"))
-       (def
-        (let ((inline-def
-               (org-element-property :inline-definition footnote-reference)))
-          (if (not inline-def) ""
-            (concat ":" (org-element-interpret-data inline-def))))))
-    (format "[%s]" (concat label def))))
-
-(defun org-element-footnote-reference-successor ()
-  "Search for the next footnote-reference object.
-
-Return value is a cons cell whose CAR is `footnote-reference' and
-CDR is beginning position."
-  (save-excursion
-    (catch 'exit
-      (while (re-search-forward org-footnote-re nil t)
-       (save-excursion
-         (let ((beg (match-beginning 0))
-               (count 1))
-           (backward-char)
-           (while (re-search-forward "[][]" nil t)
-             (if (equal (match-string 0) "[") (incf count) (decf count))
-             (when (zerop count)
-               (throw 'exit (cons 'footnote-reference beg))))))))))
+CONTENTS is its definition, when inline, or nil."
+  (format "[fn:%s%s]"
+         (or (org-element-property :label footnote-reference) "")
+         (if contents (concat ":" contents) "")))
 
 
 ;;;; Inline Babel Call
 
 (defun org-element-inline-babel-call-parser ()
-  "Parse inline babel call at point.
+  "Parse inline babel call at point, if any.
 
-Return a list whose CAR is `inline-babel-call' and CDR a plist
-with `:begin', `:end', `:info' and `:post-blank' as keywords.
+When at an inline babel call, return a list whose car is
+`inline-babel-call' and cdr a plist with `:call',
+`:inside-header', `:arguments', `:end-header', `:begin', `:end',
+`:value' and `:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the beginning of the babel call."
   (save-excursion
-    (unless (bolp) (backward-char))
-    (looking-at org-babel-inline-lob-one-liner-regexp)
-    (let ((info (save-match-data (org-babel-lob-get-info)))
-         (begin (match-end 1))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'inline-babel-call
-           (list :begin begin
-                 :end end
-                 :info info
-                 :post-blank post-blank)))))
-
-(defun org-element-inline-babel-call-interpreter (inline-babel-call contents)
-  "Interpret INLINE-BABEL-CALL object as Org syntax.
-CONTENTS is nil."
-  (let* ((babel-info (org-element-property :info inline-babel-call))
-        (main-source (car babel-info))
-        (post-options (nth 1 babel-info)))
-    (concat "call_"
-           (if (string-match "\\[\\(\\[.*?\\]\\)\\]" main-source)
-               ;; Remove redundant square brackets.
-               (replace-match
-                (match-string 1 main-source) nil nil main-source)
-             main-source)
-           (and post-options (format "[%s]" post-options)))))
-
-(defun org-element-inline-babel-call-successor ()
-  "Search for the next inline-babel-call object.
-
-Return value is a cons cell whose CAR is `inline-babel-call' and
-CDR is beginning position."
-  (save-excursion
-    (when (re-search-forward org-babel-inline-lob-one-liner-regexp nil t)
-      (cons 'inline-babel-call (match-end 1)))))
+    (catch :no-object
+      (when (let ((case-fold-search nil))
+             (looking-at "\\<call_\\([^ \t\n[(]+\\)[([]"))
+       (goto-char (match-end 1))
+       (let* ((begin (match-beginning 0))
+              (call (match-string-no-properties 1))
+              (inside-header
+               (let ((p (org-element--parse-paired-brackets ?\[)))
+                 (and (org-string-nw-p p)
+                      (replace-regexp-in-string "\n[ \t]*" " " (org-trim p)))))
+              (arguments (org-string-nw-p
+                          (or (org-element--parse-paired-brackets ?\()
+                              ;; Parenthesis are mandatory.
+                              (throw :no-object nil))))
+              (end-header
+               (let ((p (org-element--parse-paired-brackets ?\[)))
+                 (and (org-string-nw-p p)
+                      (replace-regexp-in-string "\n[ \t]*" " " (org-trim p)))))
+              (value (buffer-substring-no-properties begin (point)))
+              (post-blank (skip-chars-forward " \t"))
+              (end (point)))
+         (list 'inline-babel-call
+               (list :call call
+                     :inside-header inside-header
+                     :arguments arguments
+                     :end-header end-header
+                     :begin begin
+                     :end end
+                     :value value
+                     :post-blank post-blank)))))))
+
+(defun org-element-inline-babel-call-interpreter (inline-babel-call _)
+  "Interpret INLINE-BABEL-CALL object as Org syntax."
+  (concat "call_"
+         (org-element-property :call inline-babel-call)
+         (let ((h (org-element-property :inside-header inline-babel-call)))
+           (and h (format "[%s]" h)))
+         "(" (org-element-property :arguments inline-babel-call) ")"
+         (let ((h (org-element-property :end-header inline-babel-call)))
+           (and h (format "[%s]" h)))))
 
 
 ;;;; Inline Src Block
 
 (defun org-element-inline-src-block-parser ()
-  "Parse inline source block at point.
+  "Parse inline source block at point, if any.
 
-Return a list whose CAR is `inline-src-block' and CDR a plist
-with `:begin', `:end', `:language', `:value', `:parameters' and
-`:post-blank' as keywords.
+When at an inline source block, return a list whose car is
+`inline-src-block' and cdr a plist with `:begin', `:end',
+`:language', `:value', `:parameters' and `:post-blank' as
+keywords.  Otherwise, return nil.
 
 Assume point is at the beginning of the inline src block."
   (save-excursion
-    (unless (bolp) (backward-char))
-    (looking-at org-babel-inline-src-block-regexp)
-    (let ((begin (match-beginning 1))
-         (language (org-match-string-no-properties 2))
-         (parameters (org-match-string-no-properties 4))
-         (value (org-match-string-no-properties 5))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'inline-src-block
-           (list :language language
-                 :value value
-                 :parameters parameters
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-inline-src-block-interpreter (inline-src-block contents)
-  "Interpret INLINE-SRC-BLOCK object as Org syntax.
-CONTENTS is nil."
+    (catch :no-object
+      (when (let ((case-fold-search nil))
+             (looking-at "\\<src_\\([^ \t\n[{]+\\)[{[]"))
+       (goto-char (match-end 1))
+       (let ((begin (match-beginning 0))
+             (language (match-string-no-properties 1))
+             (parameters
+              (let ((p (org-element--parse-paired-brackets ?\[)))
+                (and (org-string-nw-p p)
+                     (replace-regexp-in-string "\n[ \t]*" " " (org-trim p)))))
+             (value (or (org-element--parse-paired-brackets ?\{)
+                        (throw :no-object nil)))
+             (post-blank (skip-chars-forward " \t")))
+         (list 'inline-src-block
+               (list :language language
+                     :value value
+                     :parameters parameters
+                     :begin begin
+                     :end (point)
+                     :post-blank post-blank)))))))
+
+(defun org-element-inline-src-block-interpreter (inline-src-block _)
+  "Interpret INLINE-SRC-BLOCK object as Org syntax."
   (let ((language (org-element-property :language inline-src-block))
        (arguments (org-element-property :parameters inline-src-block))
        (body (org-element-property :value inline-src-block)))
@@ -2959,44 +2936,35 @@ CONTENTS is nil."
            (if arguments (format "[%s]" arguments) "")
            body)))
 
-(defun org-element-inline-src-block-successor ()
-  "Search for the next inline-babel-call element.
-
-Return value is a cons cell whose CAR is `inline-babel-call' and
-CDR is beginning position."
-  (save-excursion
-    (unless (bolp) (backward-char))
-    (when (re-search-forward org-babel-inline-src-block-regexp nil t)
-      (cons 'inline-src-block (match-beginning 1)))))
-
 ;;;; Italic
 
 (defun org-element-italic-parser ()
-  "Parse italic object at point.
+  "Parse italic object at point, if any.
 
-Return a list whose CAR is `italic' and CDR is a plist with
-`:begin', `:end', `:contents-begin' and `:contents-end' and
-`:post-blank' keywords.
+When at an italic object, return a list whose car is `italic' and
+cdr is a plist with `:begin', `:end', `:contents-begin' and
+`:contents-end' and `:post-blank' keywords.  Otherwise, return
+nil.
 
 Assume point is at the first slash marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (contents-begin (match-beginning 4))
-         (contents-end (match-end 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'italic
-           (list :begin begin
-                 :end end
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
-
-(defun org-element-italic-interpreter (italic contents)
-  "Interpret ITALIC object as Org syntax.
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (contents-begin (match-beginning 4))
+           (contents-end (match-end 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'italic
+             (list :begin begin
+                   :end end
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
+
+(defun org-element-italic-interpreter (_ contents)
+  "Interpret italic object as Org syntax.
 CONTENTS is the contents of the object."
   (format "/%s/" contents))
 
@@ -3004,169 +2972,191 @@ CONTENTS is the contents of the object."
 ;;;; Latex Fragment
 
 (defun org-element-latex-fragment-parser ()
-  "Parse LaTeX fragment at point.
+  "Parse LaTeX fragment at point, if any.
 
-Return a list whose CAR is `latex-fragment' and CDR a plist with
-`:value', `:begin', `:end', and `:post-blank' as keywords.
+When at a LaTeX fragment, return a list whose car is
+`latex-fragment' and cdr a plist with `:value', `:begin', `:end',
+and `:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the beginning of the LaTeX fragment."
-  (save-excursion
-    (let* ((begin (point))
-          (substring-match
-           (catch 'exit
-             (dolist (e (cdr org-latex-regexps))
-               (let ((latex-regexp (nth 1 e)))
-                 (when (or (looking-at latex-regexp)
-                           (and (not (bobp))
-                                (save-excursion
-                                  (backward-char)
-                                  (looking-at latex-regexp))))
-                   (throw 'exit (nth 2 e)))))
-             ;; None found: it's a macro.
-             (looking-at 
"\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")
-             0))
-          (value (org-match-string-no-properties substring-match))
-          (post-blank (progn (goto-char (match-end substring-match))
-                             (skip-chars-forward " \t")))
-          (end (point)))
-      (list 'latex-fragment
-           (list :value value
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-latex-fragment-interpreter (latex-fragment contents)
-  "Interpret LATEX-FRAGMENT object as Org syntax.
-CONTENTS is nil."
+  (catch 'no-object
+    (save-excursion
+      (let* ((begin (point))
+            (after-fragment
+             (if (eq (char-after) ?$)
+                 (if (eq (char-after (1+ (point))) ?$)
+                     (search-forward "$$" nil t 2)
+                   (and (not (eq (char-before) ?$))
+                        (search-forward "$" nil t 2)
+                        (not (memq (char-before (match-beginning 0))
+                                   '(?\s ?\t ?\n ?, ?.)))
+                        (looking-at-p
+                         "\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|'\\|$\\)")
+                        (point)))
+               (pcase (char-after (1+ (point)))
+                 (?\( (search-forward "\\)" nil t))
+                 (?\[ (search-forward "\\]" nil t))
+                 (_
+                  ;; Macro.
+                  (and (looking-at "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\
+\\|\\({[^{}\n]*}\\)\\)*")
+                       (match-end 0))))))
+            (post-blank (if (not after-fragment) (throw 'no-object nil)
+                          (goto-char after-fragment)
+                          (skip-chars-forward " \t")))
+            (end (point)))
+       (list 'latex-fragment
+             (list :value (buffer-substring-no-properties begin after-fragment)
+                   :begin begin
+                   :end end
+                   :post-blank post-blank))))))
+
+(defun org-element-latex-fragment-interpreter (latex-fragment _)
+  "Interpret LATEX-FRAGMENT object as Org syntax."
   (org-element-property :value latex-fragment))
 
 ;;;; Line Break
 
 (defun org-element-line-break-parser ()
-  "Parse line break at point.
+  "Parse line break at point, if any.
 
-Return a list whose CAR is `line-break', and CDR a plist with
-`:begin', `:end' and `:post-blank' keywords.
+When at a line break, return a list whose car is `line-break',
+and cdr a plist with `:begin', `:end' and `:post-blank' keywords.
+Otherwise, return nil.
 
 Assume point is at the beginning of the line break."
-  (list 'line-break
-       (list :begin (point)
-             :end (progn (forward-line) (point))
-             :post-blank 0)))
+  (when (and (looking-at-p "\\\\\\\\[ \t]*$")
+            (not (eq (char-before) ?\\)))
+    (list 'line-break
+         (list :begin (point)
+               :end (line-beginning-position 2)
+               :post-blank 0))))
 
-(defun org-element-line-break-interpreter (line-break contents)
-  "Interpret LINE-BREAK object as Org syntax.
-CONTENTS is nil."
+(defun org-element-line-break-interpreter (&rest _)
+  "Interpret LINE-BREAK object as Org syntax."
   "\\\\\n")
 
-(defun org-element-line-break-successor ()
-  "Search for the next line-break object.
-
-Return value is a cons cell whose CAR is `line-break' and CDR is
-beginning position."
-  (save-excursion
-    (let ((beg (and (re-search-forward "[^\\\\]\\(\\\\\\\\\\)[ \t]*$" nil t)
-                   (goto-char (match-beginning 1)))))
-      ;; A line break can only happen on a non-empty line.
-      (when (and beg (re-search-backward "\\S-" (point-at-bol) t))
-       (cons 'line-break beg)))))
-
 
 ;;;; Link
 
 (defun org-element-link-parser ()
-  "Parse link at point.
+  "Parse link at point, if any.
 
-Return a list whose CAR is `link' and CDR a plist with `:type',
-`:path', `:raw-link', `:application', `:search-option', `:begin',
-`:end', `:contents-begin', `:contents-end' and `:post-blank' as
-keywords.
+When at a link, return a list whose car is `link' and cdr a plist
+with `:type', `:path', `:format', `:raw-link', `:application',
+`:search-option', `:begin', `:end', `:contents-begin',
+`:contents-end' and `:post-blank' as keywords.  Otherwise, return
+nil.
 
 Assume point is at the beginning of the link."
-  (save-excursion
+  (catch 'no-object
     (let ((begin (point))
-         end contents-begin contents-end link-end post-blank path type
-         raw-link link search-option application)
+         end contents-begin contents-end link-end post-blank path type format
+         raw-link search-option application)
       (cond
        ;; Type 1: Text targeted from a radio target.
-       ((and org-target-link-regexp (looking-at org-target-link-regexp))
-       (setq type "radio"
-             link-end (match-end 0)
-             path (org-match-string-no-properties 0)
-             contents-begin (match-beginning 0)
-             contents-end (match-end 0)))
+       ((and org-target-link-regexp
+            (save-excursion (or (bolp) (backward-char))
+                            (looking-at org-target-link-regexp)))
+       (setq type "radio")
+       (setq format 'plain)
+       (setq link-end (match-end 1))
+       (setq path (match-string-no-properties 1))
+       (setq contents-begin (match-beginning 1))
+       (setq contents-end (match-end 1)))
        ;; Type 2: Standard link, i.e. [[http://orgmode.org][homepage]]
        ((looking-at org-bracket-link-regexp)
-       (setq contents-begin (match-beginning 3)
-             contents-end (match-end 3)
-             link-end (match-end 0)
-             ;; RAW-LINK is the original link.  Expand any
-             ;; abbreviation in it.
-             raw-link (org-translate-link
-                       (org-link-expand-abbrev
-                        (org-match-string-no-properties 1))))
-       ;; Determine TYPE of link and set PATH accordingly.
+       (setq format 'bracket)
+       (setq contents-begin (match-beginning 3))
+       (setq contents-end (match-end 3))
+       (setq link-end (match-end 0))
+       ;; RAW-LINK is the original link.  Expand any
+       ;; abbreviation in it.
+       ;;
+       ;; Also treat any newline character and associated
+       ;; indentation as a single space character.  This is not
+       ;; compatible with RFC 3986, which requires to ignore
+       ;; them altogether.  However, doing so would require
+       ;; users to encode spaces on the fly when writing links
+       ;; (e.g., insert [[shell:ls%20*.org]] instead of
+       ;; [[shell:ls *.org]], which defeats Org's focus on
+       ;; simplicity.
+       (setq raw-link (org-link-expand-abbrev
+                       (replace-regexp-in-string
+                        "[ \t]*\n[ \t]*" " "
+                        (match-string-no-properties 1))))
+       ;; Determine TYPE of link and set PATH accordingly.  According
+       ;; to RFC 3986, remove whitespaces from URI in external links.
+       ;; In internal ones, treat indentation as a single space.
        (cond
         ;; File type.
         ((or (file-name-absolute-p raw-link)
              (string-match "\\`\\.\\.?/" raw-link))
-         (setq type "file" path raw-link))
-        ;; Explicit type (http, irc, bbdb...).  See `org-link-types'.
+         (setq type "file")
+         (setq path raw-link))
+        ;; Explicit type (http, irc, bbdb...).
         ((string-match org-link-types-re raw-link)
-         (setq type (match-string 1 raw-link)
-               ;; According to RFC 3986, extra whitespace should be
-               ;; ignored when a URI is extracted.
-               path (replace-regexp-in-string
-                     "[ \t]*\n[ \t]*" "" (substring raw-link (match-end 0)))))
-        ;; Id type: PATH is the id.
-        ((string-match "\\`id:\\([-a-f0-9]+\\)" raw-link)
-         (setq type "id" path (match-string 1 raw-link)))
+         (setq type (match-string 1 raw-link))
+         (setq path (substring raw-link (match-end 0))))
         ;; Code-ref type: PATH is the name of the reference.
-        ((string-match "\\`(\\(.*\\))\\'" raw-link)
-         (setq type "coderef" path (match-string 1 raw-link)))
+        ((and (string-match-p "\\`(" raw-link)
+              (string-match-p ")\\'" raw-link))
+         (setq type "coderef")
+         (setq path (substring raw-link 1 -1)))
         ;; Custom-id type: PATH is the name of the custom id.
-        ((= (aref raw-link 0) ?#)
-         (setq type "custom-id" path (substring raw-link 1)))
+        ((= (string-to-char raw-link) ?#)
+         (setq type "custom-id")
+         (setq path (substring raw-link 1)))
         ;; Fuzzy type: Internal link either matches a target, an
         ;; headline name or nothing.  PATH is the target or
         ;; headline's name.
-        (t (setq type "fuzzy" path raw-link))))
+        (t
+         (setq type "fuzzy")
+         (setq path raw-link))))
        ;; Type 3: Plain link, e.g., http://orgmode.org
        ((looking-at org-plain-link-re)
-       (setq raw-link (org-match-string-no-properties 0)
-             type (org-match-string-no-properties 1)
-             link-end (match-end 0)
-             path (org-match-string-no-properties 2)))
-       ;; Type 4: Angular link, e.g., <http://orgmode.org>
+       (setq format 'plain)
+       (setq raw-link (match-string-no-properties 0))
+       (setq type (match-string-no-properties 1))
+       (setq link-end (match-end 0))
+       (setq path (match-string-no-properties 2)))
+       ;; Type 4: Angular link, e.g., <http://orgmode.org>.  Unlike to
+       ;; bracket links, follow RFC 3986 and remove any extra
+       ;; whitespace in URI.
        ((looking-at org-angle-link-re)
-       (setq raw-link (buffer-substring-no-properties
-                       (match-beginning 1) (match-end 2))
-             type (org-match-string-no-properties 1)
-             link-end (match-end 0)
-             path (org-match-string-no-properties 2))))
+       (setq format 'angle)
+       (setq type (match-string-no-properties 1))
+       (setq link-end (match-end 0))
+       (setq raw-link
+             (buffer-substring-no-properties
+              (match-beginning 1) (match-end 2)))
+       (setq path (replace-regexp-in-string
+                   "[ \t]*\n[ \t]*" "" (match-string-no-properties 2))))
+       (t (throw 'no-object nil)))
       ;; In any case, deduce end point after trailing white space from
       ;; LINK-END variable.
-      (setq post-blank (progn (goto-char link-end) (skip-chars-forward " \t"))
-           end (point))
-      ;; Special "file" type link processing.
-      (when (member type org-element-link-type-is-file)
-       ;; Extract opening application and search option.
-       (cond ((string-match "^file\\+\\(.*\\)$" type)
-              (setq application (match-string 1 type)))
-             ((not (string-match "^file" type))
-              (setq application type)))
+      (save-excursion
+       (setq post-blank
+             (progn (goto-char link-end) (skip-chars-forward " \t")))
+       (setq end (point)))
+      ;; Special "file" type link processing.  Extract opening
+      ;; application and search option, if any.  Also normalize URI.
+      (when (string-match "\\`file\\(?:\\+\\(.+\\)\\)?\\'" type)
+       (setq application (match-string 1 type) type "file")
        (when (string-match "::\\(.*\\)\\'" path)
-         (setq search-option (match-string 1 path)
-               path (replace-match "" nil nil path)))
-       ;; Normalize URI.
-       (when (and (not (org-string-match-p "\\`//" path))
-                  (file-name-absolute-p path))
-         (setq path (concat "//" (expand-file-name path))))
-       ;; Make sure TYPE always reports "file".
-       (setq type "file"))
+         (setq search-option (match-string 1 path))
+         (setq path (replace-match "" nil nil path)))
+       (setq path (replace-regexp-in-string "\\`///*\\(.:\\)?/" "\\1/" path)))
+      ;; Translate link, if `org-link-translation-function' is set.
+      (let ((trans (and (functionp org-link-translation-function)
+                       (funcall org-link-translation-function type path))))
+       (when trans
+         (setq type (car trans))
+         (setq path (cdr trans))))
       (list 'link
            (list :type type
                  :path path
+                 :format format
                  :raw-link (or raw-link path)
                  :application application
                  :search-option search-option
@@ -3180,197 +3170,167 @@ Assume point is at the beginning of the link."
   "Interpret LINK object as Org syntax.
 CONTENTS is the contents of the object, or nil."
   (let ((type (org-element-property :type link))
-       (raw-link (org-element-property :raw-link link)))
-    (if (string= type "radio") raw-link
-      (format "[[%s]%s]"
-             raw-link
-             (if contents (format "[%s]" contents) "")))))
-
-(defun org-element-link-successor ()
-  "Search for the next link object.
-
-Return value is a cons cell whose CAR is `link' and CDR is
-beginning position."
-  (save-excursion
-    (let ((link-regexp
-          (if (not org-target-link-regexp) org-any-link-re
-            (concat org-any-link-re "\\|" org-target-link-regexp))))
-      (when (re-search-forward link-regexp nil t)
-       (cons 'link (match-beginning 0))))))
-
-(defun org-element-plain-link-successor ()
-  "Search for the next plain link object.
-
-Return value is a cons cell whose CAR is `link' and CDR is
-beginning position."
-  (and (save-excursion (re-search-forward org-plain-link-re nil t))
-       (cons 'link (match-beginning 0))))
+       (path (org-element-property :path link)))
+    (if (string= type "radio") path
+      (let ((fmt (pcase (org-element-property :format link)
+                  ;; Links with contents and internal links have to
+                  ;; use bracket syntax.  Ignore `:format' in these
+                  ;; cases.  This is also the default syntax when the
+                  ;; property is not defined, e.g., when the object
+                  ;; was crafted by the user.
+                  ((guard contents)
+                   (format "[[%%s][%s]]"
+                           ;; Since this is going to be used as
+                           ;; a format string, escape percent signs
+                           ;; in description.
+                           (replace-regexp-in-string "%" "%%" contents)))
+                  ((or `bracket
+                       `nil
+                       (guard (member type '("coderef" "custom-id" "fuzzy"))))
+                   "[[%s]]")
+                  ;; Otherwise, just obey to `:format'.
+                  (`angle "<%s>")
+                  (`plain "%s")
+                  (f (error "Wrong `:format' value: %s" f)))))
+       (format fmt
+               (pcase type
+                 ("coderef" (format "(%s)" path))
+                 ("custom-id" (concat "#" path))
+                 ("file"
+                  (let ((app (org-element-property :application link))
+                        (opt (org-element-property :search-option link)))
+                    (concat type (and app (concat "+" app)) ":"
+                            path
+                            (and opt (concat "::" opt)))))
+                 ("fuzzy" path)
+                 (_ (concat type ":" path))))))))
 
 
 ;;;; Macro
 
 (defun org-element-macro-parser ()
-  "Parse macro at point.
+  "Parse macro at point, if any.
 
-Return a list whose CAR is `macro' and CDR a plist with `:key',
-`:args', `:begin', `:end', `:value' and `:post-blank' as
-keywords.
+When at a macro, return a list whose car is `macro' and cdr
+a plist with `:key', `:args', `:begin', `:end', `:value' and
+`:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the macro."
   (save-excursion
-    (looking-at "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ 
\t\n]*\\([^\000]*?\\))\\)?}}}")
-    (let ((begin (point))
-         (key (downcase (org-match-string-no-properties 1)))
-         (value (org-match-string-no-properties 0))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point))
-         (args (let ((args (org-match-string-no-properties 3)))
-                 (when args
-                   ;; Do not use `org-split-string' since empty
-                   ;; strings are meaningful here.
-                   (split-string
-                    (replace-regexp-in-string
-                     "\\(\\\\*\\)\\(,\\)"
-                     (lambda (str)
-                       (let ((len (length (match-string 1 str))))
-                         (concat (make-string (/ len 2) ?\\)
-                                 (if (zerop (mod len 2)) "\000" ","))))
-                     args nil t)
-                    "\000")))))
-      (list 'macro
-           (list :key key
-                 :value value
-                 :args args
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-macro-interpreter (macro contents)
-  "Interpret MACRO object as Org syntax.
-CONTENTS is nil."
+    (when (looking-at "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ 
\t\n]*\\([^\000]*?\\))\\)?}}}")
+      (let ((begin (point))
+           (key (downcase (match-string-no-properties 1)))
+           (value (match-string-no-properties 0))
+           (post-blank (progn (goto-char (match-end 0))
+                              (skip-chars-forward " \t")))
+           (end (point))
+           (args (let ((args (match-string-no-properties 3)))
+                   (and args (org-macro-extract-arguments args)))))
+       (list 'macro
+             (list :key key
+                   :value value
+                   :args args
+                   :begin begin
+                   :end end
+                   :post-blank post-blank))))))
+
+(defun org-element-macro-interpreter (macro _)
+  "Interpret MACRO object as Org syntax."
   (org-element-property :value macro))
 
-(defun org-element-macro-successor ()
-  "Search for the next macro object.
-
-Return value is cons cell whose CAR is `macro' and CDR is
-beginning position."
-  (save-excursion
-    (when (re-search-forward
-          "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}"
-          nil t)
-      (cons 'macro (match-beginning 0)))))
-
 
 ;;;; Radio-target
 
 (defun org-element-radio-target-parser ()
-  "Parse radio target at point.
+  "Parse radio target at point, if any.
 
-Return a list whose CAR is `radio-target' and CDR a plist with
-`:begin', `:end', `:contents-begin', `:contents-end', `:value'
-and `:post-blank' as keywords.
+When at a radio target, return a list whose car is `radio-target'
+and cdr a plist with `:begin', `:end', `:contents-begin',
+`:contents-end', `:value' and `:post-blank' as keywords.
+Otherwise, return nil.
 
 Assume point is at the radio target."
   (save-excursion
-    (looking-at org-radio-target-regexp)
-    (let ((begin (point))
-         (contents-begin (match-beginning 1))
-         (contents-end (match-end 1))
-         (value (org-match-string-no-properties 1))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'radio-target
-           (list :begin begin
-                 :end end
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank
-                 :value value)))))
-
-(defun org-element-radio-target-interpreter (target contents)
-  "Interpret TARGET object as Org syntax.
+    (when (looking-at org-radio-target-regexp)
+      (let ((begin (point))
+           (contents-begin (match-beginning 1))
+           (contents-end (match-end 1))
+           (value (match-string-no-properties 1))
+           (post-blank (progn (goto-char (match-end 0))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'radio-target
+             (list :begin begin
+                   :end end
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank
+                   :value value))))))
+
+(defun org-element-radio-target-interpreter (_ contents)
+  "Interpret target object as Org syntax.
 CONTENTS is the contents of the object."
   (concat "<<<" contents ">>>"))
 
-(defun org-element-radio-target-successor ()
-  "Search for the next radio-target object.
-
-Return value is a cons cell whose CAR is `radio-target' and CDR
-is beginning position."
-  (save-excursion
-    (when (re-search-forward org-radio-target-regexp nil t)
-      (cons 'radio-target (match-beginning 0)))))
-
 
 ;;;; Statistics Cookie
 
 (defun org-element-statistics-cookie-parser ()
-  "Parse statistics cookie at point.
+  "Parse statistics cookie at point, if any.
 
-Return a list whose CAR is `statistics-cookie', and CDR a plist
-with `:begin', `:end', `:value' and `:post-blank' keywords.
+When at a statistics cookie, return a list whose car is
+`statistics-cookie', and cdr a plist with `:begin', `:end',
+`:value' and `:post-blank' keywords.  Otherwise, return nil.
 
 Assume point is at the beginning of the statistics-cookie."
   (save-excursion
-    (looking-at "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]")
-    (let* ((begin (point))
-          (value (buffer-substring-no-properties
-                  (match-beginning 0) (match-end 0)))
-          (post-blank (progn (goto-char (match-end 0))
-                             (skip-chars-forward " \t")))
-          (end (point)))
-      (list 'statistics-cookie
-           (list :begin begin
-                 :end end
-                 :value value
-                 :post-blank post-blank)))))
-
-(defun org-element-statistics-cookie-interpreter (statistics-cookie contents)
-  "Interpret STATISTICS-COOKIE object as Org syntax.
-CONTENTS is nil."
+    (when (looking-at "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]")
+      (let* ((begin (point))
+            (value (buffer-substring-no-properties
+                    (match-beginning 0) (match-end 0)))
+            (post-blank (progn (goto-char (match-end 0))
+                               (skip-chars-forward " \t")))
+            (end (point)))
+       (list 'statistics-cookie
+             (list :begin begin
+                   :end end
+                   :value value
+                   :post-blank post-blank))))))
+
+(defun org-element-statistics-cookie-interpreter (statistics-cookie _)
+  "Interpret STATISTICS-COOKIE object as Org syntax."
   (org-element-property :value statistics-cookie))
 
-(defun org-element-statistics-cookie-successor ()
-  "Search for the next statistics cookie object.
-
-Return value is a cons cell whose CAR is `statistics-cookie' and
-CDR is beginning position."
-  (save-excursion
-    (when (re-search-forward "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]" nil t)
-      (cons 'statistics-cookie (match-beginning 0)))))
-
 
 ;;;; Strike-Through
 
 (defun org-element-strike-through-parser ()
-  "Parse strike-through object at point.
+  "Parse strike-through object at point, if any.
 
-Return a list whose CAR is `strike-through' and CDR is a plist
-with `:begin', `:end', `:contents-begin' and `:contents-end' and
-`:post-blank' keywords.
+When at a strike-through object, return a list whose car is
+`strike-through' and cdr is a plist with `:begin', `:end',
+`:contents-begin' and `:contents-end' and `:post-blank' keywords.
+Otherwise, return nil.
 
 Assume point is at the first plus sign marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (contents-begin (match-beginning 4))
-         (contents-end (match-end 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'strike-through
-           (list :begin begin
-                 :end end
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
-
-(defun org-element-strike-through-interpreter (strike-through contents)
-  "Interpret STRIKE-THROUGH object as Org syntax.
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (contents-begin (match-beginning 4))
+           (contents-end (match-end 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'strike-through
+             (list :begin begin
+                   :end end
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
+
+(defun org-element-strike-through-interpreter (_ contents)
+  "Interpret strike-through object as Org syntax.
 CONTENTS is the contents of the object."
   (format "+%s+" contents))
 
@@ -3378,32 +3338,32 @@ CONTENTS is the contents of the object."
 ;;;; Subscript
 
 (defun org-element-subscript-parser ()
-  "Parse subscript at point.
+  "Parse subscript at point, if any.
 
-Return a list whose CAR is `subscript' and CDR a plist with
-`:begin', `:end', `:contents-begin', `:contents-end',
-`:use-brackets-p' and `:post-blank' as keywords.
+When at a subscript object, return a list whose car is
+`subscript' and cdr a plist with `:begin', `:end',
+`:contents-begin', `:contents-end', `:use-brackets-p' and
+`:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the underscore."
   (save-excursion
     (unless (bolp) (backward-char))
-    (let ((bracketsp (if (looking-at org-match-substring-with-braces-regexp)
-                        t
-                      (not (looking-at org-match-substring-regexp))))
-         (begin (match-beginning 2))
-         (contents-begin (or (match-beginning 5)
-                             (match-beginning 3)))
-         (contents-end (or (match-end 5) (match-end 3)))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'subscript
-           (list :begin begin
-                 :end end
-                 :use-brackets-p bracketsp
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
+    (when (looking-at org-match-substring-regexp)
+      (let ((bracketsp (match-beginning 4))
+           (begin (match-beginning 2))
+           (contents-begin (or (match-beginning 4)
+                               (match-beginning 3)))
+           (contents-end (or (match-end 4) (match-end 3)))
+           (post-blank (progn (goto-char (match-end 0))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'subscript
+             (list :begin begin
+                   :end end
+                   :use-brackets-p bracketsp
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
 
 (defun org-element-subscript-interpreter (subscript contents)
   "Interpret SUBSCRIPT object as Org syntax.
@@ -3412,46 +3372,36 @@ CONTENTS is the contents of the object."
    (if (org-element-property :use-brackets-p subscript) "_{%s}" "_%s")
    contents))
 
-(defun org-element-sub/superscript-successor ()
-  "Search for the next sub/superscript object.
-
-Return value is a cons cell whose CAR is either `subscript' or
-`superscript' and CDR is beginning position."
-  (save-excursion
-    (unless (bolp) (backward-char))
-    (when (re-search-forward org-match-substring-regexp nil t)
-      (cons (if (string= (match-string 2) "_") 'subscript 'superscript)
-           (match-beginning 2)))))
-
 
 ;;;; Superscript
 
 (defun org-element-superscript-parser ()
-  "Parse superscript at point.
+  "Parse superscript at point, if any.
 
-Return a list whose CAR is `superscript' and CDR a plist with
-`:begin', `:end', `:contents-begin', `:contents-end',
-`:use-brackets-p' and `:post-blank' as keywords.
+When at a superscript object, return a list whose car is
+`superscript' and cdr a plist with `:begin', `:end',
+`:contents-begin', `:contents-end', `:use-brackets-p' and
+`:post-blank' as keywords.  Otherwise, return nil.
 
 Assume point is at the caret."
   (save-excursion
     (unless (bolp) (backward-char))
-    (let ((bracketsp (if (looking-at org-match-substring-with-braces-regexp) t
-                      (not (looking-at org-match-substring-regexp))))
-         (begin (match-beginning 2))
-         (contents-begin (or (match-beginning 5)
-                             (match-beginning 3)))
-         (contents-end (or (match-end 5) (match-end 3)))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'superscript
-           (list :begin begin
-                 :end end
-                 :use-brackets-p bracketsp
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
+    (when (looking-at org-match-substring-regexp)
+      (let ((bracketsp (match-beginning 4))
+           (begin (match-beginning 2))
+           (contents-begin (or (match-beginning 4)
+                               (match-beginning 3)))
+           (contents-end (or (match-end 4) (match-end 3)))
+           (post-blank (progn (goto-char (match-end 0))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'superscript
+             (list :begin begin
+                   :end end
+                   :use-brackets-p bracketsp
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
 
 (defun org-element-superscript-interpreter (superscript contents)
   "Interpret SUPERSCRIPT object as Org syntax.
@@ -3465,8 +3415,7 @@ CONTENTS is the contents of the object."
 
 (defun org-element-table-cell-parser ()
   "Parse table cell at point.
-
-Return a list whose CAR is `table-cell' and CDR is a plist
+Return a list whose car is `table-cell' and cdr is a plist
 containing `:begin', `:end', `:contents-begin', `:contents-end'
 and `:post-blank' keywords."
   (looking-at "[ \t]*\\(.*?\\)[ \t]*\\(?:|\\|$\\)")
@@ -3481,299 +3430,275 @@ and `:post-blank' keywords."
                :contents-end contents-end
                :post-blank 0))))
 
-(defun org-element-table-cell-interpreter (table-cell contents)
-  "Interpret TABLE-CELL element as Org syntax.
+(defun org-element-table-cell-interpreter (_ contents)
+  "Interpret table-cell element as Org syntax.
 CONTENTS is the contents of the cell, or nil."
   (concat  " " contents " |"))
 
-(defun org-element-table-cell-successor ()
-  "Search for the next table-cell object.
-
-Return value is a cons cell whose CAR is `table-cell' and CDR is
-beginning position."
-  (when (looking-at "[ \t]*.*?[ \t]*\\(|\\|$\\)") (cons 'table-cell (point))))
-
 
 ;;;; Target
 
 (defun org-element-target-parser ()
-  "Parse target at point.
+  "Parse target at point, if any.
 
-Return a list whose CAR is `target' and CDR a plist with
-`:begin', `:end', `:value' and `:post-blank' as keywords.
+When at a target, return a list whose car is `target' and cdr
+a plist with `:begin', `:end', `:value' and `:post-blank' as
+keywords.  Otherwise, return nil.
 
 Assume point is at the target."
   (save-excursion
-    (looking-at org-target-regexp)
-    (let ((begin (point))
-         (value (org-match-string-no-properties 1))
-         (post-blank (progn (goto-char (match-end 0))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'target
-           (list :begin begin
-                 :end end
-                 :value value
-                 :post-blank post-blank)))))
-
-(defun org-element-target-interpreter (target contents)
-  "Interpret TARGET object as Org syntax.
-CONTENTS is nil."
+    (when (looking-at org-target-regexp)
+      (let ((begin (point))
+           (value (match-string-no-properties 1))
+           (post-blank (progn (goto-char (match-end 0))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'target
+             (list :begin begin
+                   :end end
+                   :value value
+                   :post-blank post-blank))))))
+
+(defun org-element-target-interpreter (target _)
+  "Interpret TARGET object as Org syntax."
   (format "<<%s>>" (org-element-property :value target)))
 
-(defun org-element-target-successor ()
-  "Search for the next target object.
-
-Return value is a cons cell whose CAR is `target' and CDR is
-beginning position."
-  (save-excursion
-    (when (re-search-forward org-target-regexp nil t)
-      (cons 'target (match-beginning 0)))))
-
 
 ;;;; Timestamp
 
+(defconst org-element--timestamp-regexp
+  (concat org-ts-regexp-both
+         "\\|"
+         "\\(?:<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
+         "\\|"
+         "\\(?:<%%\\(?:([^>\n]+)\\)>\\)")
+  "Regexp matching any timestamp type object.")
+
 (defun org-element-timestamp-parser ()
-  "Parse time stamp at point.
+  "Parse time stamp at point, if any.
 
-Return a list whose CAR is `timestamp', and CDR a plist with
-`:type', `:raw-value', `:year-start', `:month-start',
-`:day-start', `:hour-start', `:minute-start', `:year-end',
-`:month-end', `:day-end', `:hour-end', `:minute-end',
-`:repeater-type', `:repeater-value', `:repeater-unit',
-`:warning-type', `:warning-value', `:warning-unit', `:begin',
-`:end' and `:post-blank' keywords.
+When at a time stamp, return a list whose car is `timestamp', and
+cdr a plist with `:type', `:raw-value', `:year-start',
+`:month-start', `:day-start', `:hour-start', `:minute-start',
+`:year-end', `:month-end', `:day-end', `:hour-end',
+`:minute-end', `:repeater-type', `:repeater-value',
+`:repeater-unit', `:warning-type', `:warning-value',
+`:warning-unit', `:begin', `:end' and `:post-blank' keywords.
+Otherwise, return nil.
 
 Assume point is at the beginning of the timestamp."
-  (save-excursion
-    (let* ((begin (point))
-          (activep (eq (char-after) ?<))
-          (raw-value
-           (progn
-             (looking-at 
"\\([<[]\\(%%\\)?.*?\\)[]>]\\(?:--\\([<[].*?[]>]\\)\\)?")
-             (match-string-no-properties 0)))
-          (date-start (match-string-no-properties 1))
-          (date-end (match-string 3))
-          (diaryp (match-beginning 2))
-          (post-blank (progn (goto-char (match-end 0))
-                             (skip-chars-forward " \t")))
-          (end (point))
-          (time-range
-           (and (not diaryp)
-                (string-match
-                 
"[012]?[0-9]:[0-5][0-9]\\(-\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)"
-                 date-start)
-                (cons (string-to-number (match-string 2 date-start))
-                      (string-to-number (match-string 3 date-start)))))
-          (type (cond (diaryp 'diary)
-                      ((and activep (or date-end time-range)) 'active-range)
-                      (activep 'active)
-                      ((or date-end time-range) 'inactive-range)
-                      (t 'inactive)))
-          (repeater-props
-           (and (not diaryp)
-                (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)"
-                              raw-value)
-                (list
-                 :repeater-type
-                 (let ((type (match-string 1 raw-value)))
-                   (cond ((equal "++" type) 'catch-up)
-                         ((equal ".+" type) 'restart)
-                         (t 'cumulate)))
-                 :repeater-value (string-to-number (match-string 2 raw-value))
-                 :repeater-unit
-                 (case (string-to-char (match-string 3 raw-value))
-                   (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (t 'year)))))
-          (warning-props
-           (and (not diaryp)
-                (string-match "\\(-\\)?-\\([0-9]+\\)\\([hdwmy]\\)" raw-value)
-                (list
-                 :warning-type (if (match-string 1 raw-value) 'first 'all)
-                 :warning-value (string-to-number (match-string 2 raw-value))
-                 :warning-unit
-                 (case (string-to-char (match-string 3 raw-value))
-                   (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (t 'year)))))
-          year-start month-start day-start hour-start minute-start year-end
-          month-end day-end hour-end minute-end)
-      ;; Parse date-start.
-      (unless diaryp
-       (let ((date (org-parse-time-string date-start t)))
-         (setq year-start (nth 5 date)
-               month-start (nth 4 date)
-               day-start (nth 3 date)
-               hour-start (nth 2 date)
-               minute-start (nth 1 date))))
-      ;; Compute date-end.  It can be provided directly in time-stamp,
-      ;; or extracted from time range.  Otherwise, it defaults to the
-      ;; same values as date-start.
-      (unless diaryp
-       (let ((date (and date-end (org-parse-time-string date-end t))))
-         (setq year-end (or (nth 5 date) year-start)
-               month-end (or (nth 4 date) month-start)
-               day-end (or (nth 3 date) day-start)
-               hour-end (or (nth 2 date) (car time-range) hour-start)
-               minute-end (or (nth 1 date) (cdr time-range) minute-start))))
-      (list 'timestamp
-           (nconc (list :type type
-                        :raw-value raw-value
-                        :year-start year-start
-                        :month-start month-start
-                        :day-start day-start
-                        :hour-start hour-start
-                        :minute-start minute-start
-                        :year-end year-end
-                        :month-end month-end
-                        :day-end day-end
-                        :hour-end hour-end
-                        :minute-end minute-end
-                        :begin begin
-                        :end end
-                        :post-blank post-blank)
-                  repeater-props
-                  warning-props)))))
-
-(defun org-element-timestamp-interpreter (timestamp contents)
-  "Interpret TIMESTAMP object as Org syntax.
-CONTENTS is nil."
-  ;; Use `:raw-value' if specified.
-  (or (org-element-property :raw-value timestamp)
-      ;; Otherwise, build timestamp string.
-      (let* ((repeat-string
-             (concat
-              (case (org-element-property :repeater-type timestamp)
-                (cumulate "+") (catch-up "++") (restart ".+"))
-              (let ((val (org-element-property :repeater-value timestamp)))
-                (and val (number-to-string val)))
-              (case (org-element-property :repeater-unit timestamp)
-                (hour "h") (day "d") (week "w") (month "m") (year "y"))))
-            (warning-string
-             (concat
-              (case (org-element-property :warning-type timestamp)
-                (first "--")
-                (all "-"))
-              (let ((val (org-element-property :warning-value timestamp)))
-                (and val (number-to-string val)))
-              (case (org-element-property :warning-unit timestamp)
-                (hour "h") (day "d") (week "w") (month "m") (year "y"))))
-            (build-ts-string
-             ;; Build an Org timestamp string from TIME.  ACTIVEP is
-             ;; non-nil when time stamp is active.  If WITH-TIME-P is
-             ;; non-nil, add a time part.  HOUR-END and MINUTE-END
-             ;; specify a time range in the timestamp.  REPEAT-STRING
-             ;; is the repeater string, if any.
-             (lambda (time activep &optional with-time-p hour-end minute-end)
-               (let ((ts (format-time-string
-                          (funcall (if with-time-p 'cdr 'car)
-                                   org-time-stamp-formats)
-                          time)))
-                 (when (and hour-end minute-end)
-                   (string-match "[012]?[0-9]:[0-5][0-9]" ts)
-                   (setq ts
-                         (replace-match
-                          (format "\\&-%02d:%02d" hour-end minute-end)
-                          nil nil ts)))
-                 (unless activep (setq ts (format "[%s]" (substring ts 1 -1))))
-                 (dolist (s (list repeat-string warning-string))
-                   (when (org-string-nw-p s)
-                     (setq ts (concat (substring ts 0 -1)
-                                      " "
-                                      s
-                                      (substring ts -1)))))
-                 ;; Return value.
-                 ts)))
-            (type (org-element-property :type timestamp)))
-       (case type
-         ((active inactive)
-          (let* ((minute-start (org-element-property :minute-start timestamp))
-                 (minute-end (org-element-property :minute-end timestamp))
-                 (hour-start (org-element-property :hour-start timestamp))
-                 (hour-end (org-element-property :hour-end timestamp))
-                 (time-range-p (and hour-start hour-end minute-start minute-end
-                                    (or (/= hour-start hour-end)
-                                        (/= minute-start minute-end)))))
-            (funcall
-             build-ts-string
-             (encode-time 0
-                          (or minute-start 0)
-                          (or hour-start 0)
-                          (org-element-property :day-start timestamp)
-                          (org-element-property :month-start timestamp)
-                          (org-element-property :year-start timestamp))
-             (eq type 'active)
-             (and hour-start minute-start)
-             (and time-range-p hour-end)
-             (and time-range-p minute-end))))
-         ((active-range inactive-range)
-          (let ((minute-start (org-element-property :minute-start timestamp))
-                (minute-end (org-element-property :minute-end timestamp))
-                (hour-start (org-element-property :hour-start timestamp))
-                (hour-end (org-element-property :hour-end timestamp)))
-            (concat
-             (funcall
-              build-ts-string (encode-time
-                               0
-                               (or minute-start 0)
-                               (or hour-start 0)
-                               (org-element-property :day-start timestamp)
-                               (org-element-property :month-start timestamp)
-                               (org-element-property :year-start timestamp))
-              (eq type 'active-range)
-              (and hour-start minute-start))
-             "--"
-             (funcall build-ts-string
-                      (encode-time 0
-                                   (or minute-end 0)
-                                   (or hour-end 0)
-                                   (org-element-property :day-end timestamp)
-                                   (org-element-property :month-end timestamp)
-                                   (org-element-property :year-end timestamp))
-                      (eq type 'active-range)
-                      (and hour-end minute-end)))))))))
-
-(defun org-element-timestamp-successor ()
-  "Search for the next timestamp object.
-
-Return value is a cons cell whose CAR is `timestamp' and CDR is
-beginning position."
-  (save-excursion
-    (when (re-search-forward
-          (concat org-ts-regexp-both
-                  "\\|"
-                  "\\(?:<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
-                  "\\|"
-                  "\\(?:<%%\\(?:([^>\n]+)\\)>\\)")
-          nil t)
-      (cons 'timestamp (match-beginning 0)))))
+  (when (looking-at-p org-element--timestamp-regexp)
+    (save-excursion
+      (let* ((begin (point))
+            (activep (eq (char-after) ?<))
+            (raw-value
+             (progn
+               (looking-at 
"\\([<[]\\(%%\\)?.*?\\)[]>]\\(?:--\\([<[].*?[]>]\\)\\)?")
+               (match-string-no-properties 0)))
+            (date-start (match-string-no-properties 1))
+            (date-end (match-string 3))
+            (diaryp (match-beginning 2))
+            (post-blank (progn (goto-char (match-end 0))
+                               (skip-chars-forward " \t")))
+            (end (point))
+            (time-range
+             (and (not diaryp)
+                  (string-match
+                   
"[012]?[0-9]:[0-5][0-9]\\(-\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)"
+                   date-start)
+                  (cons (string-to-number (match-string 2 date-start))
+                        (string-to-number (match-string 3 date-start)))))
+            (type (cond (diaryp 'diary)
+                        ((and activep (or date-end time-range)) 'active-range)
+                        (activep 'active)
+                        ((or date-end time-range) 'inactive-range)
+                        (t 'inactive)))
+            (repeater-props
+             (and (not diaryp)
+                  (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)"
+                                raw-value)
+                  (list
+                   :repeater-type
+                   (let ((type (match-string 1 raw-value)))
+                     (cond ((equal "++" type) 'catch-up)
+                           ((equal ".+" type) 'restart)
+                           (t 'cumulate)))
+                   :repeater-value (string-to-number (match-string 2 
raw-value))
+                   :repeater-unit
+                   (pcase (string-to-char (match-string 3 raw-value))
+                     (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year)))))
+            (warning-props
+             (and (not diaryp)
+                  (string-match "\\(-\\)?-\\([0-9]+\\)\\([hdwmy]\\)" raw-value)
+                  (list
+                   :warning-type (if (match-string 1 raw-value) 'first 'all)
+                   :warning-value (string-to-number (match-string 2 raw-value))
+                   :warning-unit
+                   (pcase (string-to-char (match-string 3 raw-value))
+                     (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year)))))
+            year-start month-start day-start hour-start minute-start year-end
+            month-end day-end hour-end minute-end)
+       ;; Parse date-start.
+       (unless diaryp
+         (let ((date (org-parse-time-string date-start t)))
+           (setq year-start (nth 5 date)
+                 month-start (nth 4 date)
+                 day-start (nth 3 date)
+                 hour-start (nth 2 date)
+                 minute-start (nth 1 date))))
+       ;; Compute date-end.  It can be provided directly in time-stamp,
+       ;; or extracted from time range.  Otherwise, it defaults to the
+       ;; same values as date-start.
+       (unless diaryp
+         (let ((date (and date-end (org-parse-time-string date-end t))))
+           (setq year-end (or (nth 5 date) year-start)
+                 month-end (or (nth 4 date) month-start)
+                 day-end (or (nth 3 date) day-start)
+                 hour-end (or (nth 2 date) (car time-range) hour-start)
+                 minute-end (or (nth 1 date) (cdr time-range) minute-start))))
+       (list 'timestamp
+             (nconc (list :type type
+                          :raw-value raw-value
+                          :year-start year-start
+                          :month-start month-start
+                          :day-start day-start
+                          :hour-start hour-start
+                          :minute-start minute-start
+                          :year-end year-end
+                          :month-end month-end
+                          :day-end day-end
+                          :hour-end hour-end
+                          :minute-end minute-end
+                          :begin begin
+                          :end end
+                          :post-blank post-blank)
+                    repeater-props
+                    warning-props))))))
+
+(defun org-element-timestamp-interpreter (timestamp _)
+  "Interpret TIMESTAMP object as Org syntax."
+  (let* ((repeat-string
+         (concat
+          (pcase (org-element-property :repeater-type timestamp)
+            (`cumulate "+") (`catch-up "++") (`restart ".+"))
+          (let ((val (org-element-property :repeater-value timestamp)))
+            (and val (number-to-string val)))
+          (pcase (org-element-property :repeater-unit timestamp)
+            (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
+        (warning-string
+         (concat
+          (pcase (org-element-property :warning-type timestamp)
+            (`first "--") (`all "-"))
+          (let ((val (org-element-property :warning-value timestamp)))
+            (and val (number-to-string val)))
+          (pcase (org-element-property :warning-unit timestamp)
+            (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
+        (build-ts-string
+         ;; Build an Org timestamp string from TIME.  ACTIVEP is
+         ;; non-nil when time stamp is active.  If WITH-TIME-P is
+         ;; non-nil, add a time part.  HOUR-END and MINUTE-END
+         ;; specify a time range in the timestamp.  REPEAT-STRING is
+         ;; the repeater string, if any.
+         (lambda (time activep &optional with-time-p hour-end minute-end)
+           (let ((ts (format-time-string
+                      (funcall (if with-time-p #'cdr #'car)
+                               org-time-stamp-formats)
+                      time)))
+             (when (and hour-end minute-end)
+               (string-match "[012]?[0-9]:[0-5][0-9]" ts)
+               (setq ts
+                     (replace-match
+                      (format "\\&-%02d:%02d" hour-end minute-end)
+                      nil nil ts)))
+             (unless activep (setq ts (format "[%s]" (substring ts 1 -1))))
+             (dolist (s (list repeat-string warning-string))
+               (when (org-string-nw-p s)
+                 (setq ts (concat (substring ts 0 -1)
+                                  " "
+                                  s
+                                  (substring ts -1)))))
+             ;; Return value.
+             ts)))
+        (type (org-element-property :type timestamp)))
+    (pcase type
+      ((or `active `inactive)
+       (let* ((minute-start (org-element-property :minute-start timestamp))
+             (minute-end (org-element-property :minute-end timestamp))
+             (hour-start (org-element-property :hour-start timestamp))
+             (hour-end (org-element-property :hour-end timestamp))
+             (time-range-p (and hour-start hour-end minute-start minute-end
+                                (or (/= hour-start hour-end)
+                                    (/= minute-start minute-end)))))
+        (funcall
+         build-ts-string
+         (encode-time 0
+                      (or minute-start 0)
+                      (or hour-start 0)
+                      (org-element-property :day-start timestamp)
+                      (org-element-property :month-start timestamp)
+                      (org-element-property :year-start timestamp))
+         (eq type 'active)
+         (and hour-start minute-start)
+         (and time-range-p hour-end)
+         (and time-range-p minute-end))))
+      ((or `active-range `inactive-range)
+       (let ((minute-start (org-element-property :minute-start timestamp))
+            (minute-end (org-element-property :minute-end timestamp))
+            (hour-start (org-element-property :hour-start timestamp))
+            (hour-end (org-element-property :hour-end timestamp)))
+        (concat
+         (funcall
+          build-ts-string (encode-time
+                           0
+                           (or minute-start 0)
+                           (or hour-start 0)
+                           (org-element-property :day-start timestamp)
+                           (org-element-property :month-start timestamp)
+                           (org-element-property :year-start timestamp))
+          (eq type 'active-range)
+          (and hour-start minute-start))
+         "--"
+         (funcall build-ts-string
+                  (encode-time 0
+                               (or minute-end 0)
+                               (or hour-end 0)
+                               (org-element-property :day-end timestamp)
+                               (org-element-property :month-end timestamp)
+                               (org-element-property :year-end timestamp))
+                  (eq type 'active-range)
+                  (and hour-end minute-end)))))
+      (_ (org-element-property :raw-value timestamp)))))
 
 
 ;;;; Underline
 
 (defun org-element-underline-parser ()
-  "Parse underline object at point.
+  "Parse underline object at point, if any.
 
-Return a list whose CAR is `underline' and CDR is a plist with
-`:begin', `:end', `:contents-begin' and `:contents-end' and
-`:post-blank' keywords.
+When at an underline object, return a list whose car is
+`underline' and cdr is a plist with `:begin', `:end',
+`:contents-begin' and `:contents-end' and `:post-blank' keywords.
+Otherwise, return nil.
 
 Assume point is at the first underscore marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (contents-begin (match-beginning 4))
-         (contents-end (match-end 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'underline
-           (list :begin begin
-                 :end end
-                 :contents-begin contents-begin
-                 :contents-end contents-end
-                 :post-blank post-blank)))))
-
-(defun org-element-underline-interpreter (underline contents)
-  "Interpret UNDERLINE object as Org syntax.
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (contents-begin (match-beginning 4))
+           (contents-end (match-end 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'underline
+             (list :begin begin
+                   :end end
+                   :contents-begin contents-begin
+                   :contents-end contents-end
+                   :post-blank post-blank))))))
+
+(defun org-element-underline-interpreter (_ contents)
+  "Interpret underline object as Org syntax.
 CONTENTS is the contents of the object."
   (format "_%s_" contents))
 
@@ -3781,29 +3706,29 @@ CONTENTS is the contents of the object."
 ;;;; Verbatim
 
 (defun org-element-verbatim-parser ()
-  "Parse verbatim object at point.
+  "Parse verbatim object at point, if any.
 
-Return a list whose CAR is `verbatim' and CDR is a plist with
-`:value', `:begin', `:end' and `:post-blank' keywords.
+When at a verbatim object, return a list whose car is `verbatim'
+and cdr is a plist with `:value', `:begin', `:end' and
+`:post-blank' keywords.  Otherwise, return nil.
 
 Assume point is at the first equal sign marker."
   (save-excursion
     (unless (bolp) (backward-char 1))
-    (looking-at org-emph-re)
-    (let ((begin (match-beginning 2))
-         (value (org-match-string-no-properties 4))
-         (post-blank (progn (goto-char (match-end 2))
-                            (skip-chars-forward " \t")))
-         (end (point)))
-      (list 'verbatim
-           (list :value value
-                 :begin begin
-                 :end end
-                 :post-blank post-blank)))))
-
-(defun org-element-verbatim-interpreter (verbatim contents)
-  "Interpret VERBATIM object as Org syntax.
-CONTENTS is nil."
+    (when (looking-at org-emph-re)
+      (let ((begin (match-beginning 2))
+           (value (match-string-no-properties 4))
+           (post-blank (progn (goto-char (match-end 2))
+                              (skip-chars-forward " \t")))
+           (end (point)))
+       (list 'verbatim
+             (list :value value
+                   :begin begin
+                   :end end
+                   :post-blank post-blank))))))
+
+(defun org-element-verbatim-interpreter (verbatim _)
+  "Interpret VERBATIM object as Org syntax."
   (format "=%s=" (org-element-property :value verbatim)))
 
 
@@ -3818,10 +3743,9 @@ CONTENTS is nil."
 ;; are activated for fixed element chaining (e.g., `plain-list' >
 ;; `item') or fixed conditional element chaining (e.g., `headline' >
 ;; `section').  Special modes are: `first-section', `item',
-;; `node-property', `quote-section', `section' and `table-row'.
+;; `node-property', `section' and `table-row'.
 
-(defun org-element--current-element
-  (limit &optional granularity special structure)
+(defun org-element--current-element (limit &optional granularity mode 
structure)
   "Parse the element starting at point.
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
@@ -3838,12 +3762,12 @@ recursion.  Allowed values are `headline', 
`greater-element',
 nil), secondary values will not be parsed, since they only
 contain objects.
 
-Optional argument SPECIAL, when non-nil, can be either
-`first-section', `item', `node-property', `quote-section',
-`section', and `table-row'.
+Optional argument MODE, when non-nil, can be either
+`first-section', `section', `planning', `item', `node-property'
+and `table-row'.
 
-If STRUCTURE isn't provided but SPECIAL is set to `item', it will
-be computed.
+If STRUCTURE isn't provided but MODE is set to `item', it will be
+computed.
 
 This function assumes point is always at the beginning of the
 element it has to parse."
@@ -3855,30 +3779,37 @@ element it has to parse."
          (raw-secondary-p (and granularity (not (eq granularity 'object)))))
       (cond
        ;; Item.
-       ((eq special 'item)
+       ((eq mode 'item)
        (org-element-item-parser limit structure raw-secondary-p))
        ;; Table Row.
-       ((eq special 'table-row) (org-element-table-row-parser limit))
+       ((eq mode 'table-row) (org-element-table-row-parser limit))
        ;; Node Property.
-       ((eq special 'node-property) (org-element-node-property-parser limit))
+       ((eq mode 'node-property) (org-element-node-property-parser limit))
        ;; Headline.
        ((org-with-limited-levels (org-at-heading-p))
         (org-element-headline-parser limit raw-secondary-p))
        ;; Sections (must be checked after headline).
-       ((eq special 'section) (org-element-section-parser limit))
-       ((eq special 'quote-section) (org-element-quote-section-parser limit))
-       ((eq special 'first-section)
+       ((eq mode 'section) (org-element-section-parser limit))
+       ((eq mode 'first-section)
        (org-element-section-parser
         (or (save-excursion (org-with-limited-levels (outline-next-heading)))
             limit)))
+       ;; Planning.
+       ((and (eq mode 'planning)
+            (eq ?* (char-after (line-beginning-position 0)))
+            (looking-at org-planning-line-re))
+       (org-element-planning-parser limit))
+       ;; Property drawer.
+       ((and (memq mode '(planning property-drawer))
+            (eq ?* (char-after (line-beginning-position
+                                (if (eq mode 'planning) 0 -1))))
+            (looking-at org-property-drawer-re))
+       (org-element-property-drawer-parser limit))
        ;; When not at bol, point is at the beginning of an item or
        ;; a footnote definition: next item is always a paragraph.
        ((not (bolp)) (org-element-paragraph-parser limit (list (point))))
-       ;; Planning and Clock.
-       ((looking-at org-planning-or-clock-line-re)
-       (if (equal (match-string 1) org-clock-string)
-           (org-element-clock-parser limit)
-         (org-element-planning-parser limit)))
+       ;; Clock.
+       ((looking-at org-clock-line-re) (org-element-clock-parser limit))
        ;; Inlinetask.
        ((org-at-heading-p)
        (org-element-inlinetask-parser limit raw-secondary-p))
@@ -3891,13 +3822,11 @@ element it has to parse."
              (goto-char (car affiliated))
              (org-element-keyword-parser limit nil))
             ;; LaTeX Environment.
-            ((looking-at "[ 
\t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}\\(\\[.*?\\]\\|{.*?}\\)*[ \t]*$")
+            ((looking-at org-element--latex-begin-environment)
              (org-element-latex-environment-parser limit affiliated))
             ;; Drawer and Property Drawer.
             ((looking-at org-drawer-regexp)
-             (if (equal (match-string 1) "PROPERTIES")
-                 (org-element-property-drawer-parser limit affiliated)
-               (org-element-drawer-parser limit affiliated)))
+             (org-element-drawer-parser limit affiliated))
             ;; Fixed Width
             ((looking-at "[ \t]*:\\( \\|$\\)")
              (org-element-fixed-width-parser limit affiliated))
@@ -3905,27 +3834,35 @@ element it has to parse."
             ;; Keywords.
             ((looking-at "[ \t]*#")
              (goto-char (match-end 0))
-             (cond ((looking-at "\\(?: \\|$\\)")
-                    (beginning-of-line)
-                    (org-element-comment-parser limit affiliated))
-                   ((looking-at "\\+BEGIN_\\(\\S-+\\)")
-                    (beginning-of-line)
-                    (let ((parser (assoc (upcase (match-string 1))
-                                         org-element-block-name-alist)))
-                      (if parser (funcall (cdr parser) limit affiliated)
-                        (org-element-special-block-parser limit affiliated))))
-                   ((looking-at "\\+CALL:")
-                    (beginning-of-line)
-                    (org-element-babel-call-parser limit affiliated))
-                   ((looking-at "\\+BEGIN:? ")
-                    (beginning-of-line)
-                    (org-element-dynamic-block-parser limit affiliated))
-                   ((looking-at "\\+\\S-+:")
-                    (beginning-of-line)
-                    (org-element-keyword-parser limit affiliated))
-                   (t
-                    (beginning-of-line)
-                    (org-element-paragraph-parser limit affiliated))))
+             (cond
+              ((looking-at "\\(?: \\|$\\)")
+               (beginning-of-line)
+               (org-element-comment-parser limit affiliated))
+              ((looking-at "\\+BEGIN_\\(\\S-+\\)")
+               (beginning-of-line)
+               (funcall (pcase (upcase (match-string 1))
+                          ("CENTER"  #'org-element-center-block-parser)
+                          ("COMMENT" #'org-element-comment-block-parser)
+                          ("EXAMPLE" #'org-element-example-block-parser)
+                          ("EXPORT"  #'org-element-export-block-parser)
+                          ("QUOTE"   #'org-element-quote-block-parser)
+                          ("SRC"     #'org-element-src-block-parser)
+                          ("VERSE"   #'org-element-verse-block-parser)
+                          (_         #'org-element-special-block-parser))
+                        limit
+                        affiliated))
+              ((looking-at "\\+CALL:")
+               (beginning-of-line)
+               (org-element-babel-call-parser limit affiliated))
+              ((looking-at "\\+BEGIN:? ")
+               (beginning-of-line)
+               (org-element-dynamic-block-parser limit affiliated))
+              ((looking-at "\\+\\S-+:")
+               (beginning-of-line)
+               (org-element-keyword-parser limit affiliated))
+              (t
+               (beginning-of-line)
+               (org-element-paragraph-parser limit affiliated))))
             ;; Footnote Definition.
             ((looking-at org-footnote-definition-re)
              (org-element-footnote-definition-parser limit affiliated))
@@ -3936,7 +3873,8 @@ element it has to parse."
             ((looking-at "%%(")
              (org-element-diary-sexp-parser limit affiliated))
             ;; Table.
-            ((org-at-table-p t) (org-element-table-parser limit affiliated))
+            ((looking-at "[ \t]*\\(|\\|\\+\\(-+\\+\\)+[ \t]*$\\)")
+             (org-element-table-parser limit affiliated))
             ;; List.
             ((looking-at (org-item-re))
              (org-element-plain-list-parser
@@ -3980,7 +3918,7 @@ position of point and CDR is nil."
                (save-match-data
                  (org-trim
                   (buffer-substring-no-properties
-                   (match-end 0) (point-at-eol)))))
+                   (match-end 0) (line-end-position)))))
               ;; PARSEDP is non-nil when keyword should have its
               ;; value parsed.
               (parsedp (member kwd org-element-parsed-keywords))
@@ -3989,14 +3927,20 @@ position of point and CDR is nil."
               (dualp (member kwd org-element-dual-keywords))
               (dual-value
                (and dualp
-                    (let ((sec (org-match-string-no-properties 2)))
+                    (let ((sec (match-string-no-properties 2)))
                       (if (or (not sec) (not parsedp)) sec
-                        (org-element-parse-secondary-string sec restrict)))))
+                        (save-match-data
+                          (org-element--parse-objects
+                           (match-beginning 2) (match-end 2) nil restrict))))))
               ;; Attribute a property name to KWD.
               (kwd-sym (and kwd (intern (concat ":" (downcase kwd))))))
          ;; Now set final shape for VALUE.
          (when parsedp
-           (setq value (org-element-parse-secondary-string value restrict)))
+           (setq value
+                 (org-element--parse-objects
+                  (match-end 0)
+                  (progn (end-of-line) (skip-chars-backward " \t") (point))
+                  nil restrict)))
          (when dualp
            (setq value (and (or value dual-value) (cons value dual-value))))
          (when (or (member kwd org-element-multiple-keywords)
@@ -4037,7 +3981,7 @@ Optional argument GRANULARITY determines the depth of the
 recursion.  It can be set to the following symbols:
 
 `headline'          Only parse headlines.
-`greater-element'   Don't recurse into greater elements excepted
+`greater-element'   Don't recurse into greater elements except
                    headlines and sections.  Thus, elements
                    parsed are the top-level ones.
 `element'           Parse everything but objects and plain text.
@@ -4046,7 +3990,7 @@ recursion.  It can be set to the following symbols:
 When VISIBLE-ONLY is non-nil, don't parse contents of hidden
 elements.
 
-An element or an objects is represented as a list with the
+An element or object is represented as a list with the
 pattern (TYPE PROPERTIES CONTENTS), where :
 
   TYPE is a symbol describing the element or object.  See
@@ -4089,23 +4033,25 @@ looked after.
 
 Optional argument PARENT, when non-nil, is the element or object
 containing the secondary string.  It is used to set correctly
-`:parent' property within the string."
-  (let ((local-variables (buffer-local-variables)))
-    (with-temp-buffer
-      (dolist (v local-variables)
-       (ignore-errors
-         (if (symbolp v) (makunbound v)
-           (org-set-local (car v) (cdr v)))))
-      (insert string)
-      (restore-buffer-modified-p nil)
-      (let ((secondary (org-element--parse-objects
-                       (point-min) (point-max) nil restriction)))
-       (when parent
-         (dolist (o secondary) (org-element-put-property o :parent parent)))
-       secondary))))
+`:parent' property within the string.
+
+If STRING is the empty string or nil, return nil."
+  (cond
+   ((not string) nil)
+   ((equal string "") nil)
+   (t (let ((local-variables (buffer-local-variables)))
+       (with-temp-buffer
+         (dolist (v local-variables)
+           (ignore-errors
+             (if (symbolp v) (makunbound v)
+               (set (make-local-variable (car v)) (cdr v)))))
+         (insert string)
+         (restore-buffer-modified-p nil)
+         (org-element--parse-objects
+          (point-min) (point-max) nil restriction parent))))))
 
 (defun org-element-map
-  (data types fun &optional info first-match no-recursion with-affiliated)
+    (data types fun &optional info first-match no-recursion with-affiliated)
   "Map a function on selected elements or objects.
 
 DATA is a parse tree, an element, an object, a string, or a list
@@ -4141,7 +4087,7 @@ Assuming TREE is a variable containing an Org buffer 
parse tree,
 the following example will return a flat list of all `src-block'
 and `example-block' elements in it:
 
-  (org-element-map tree \\='(example-block src-block) \\='identity)
+  (org-element-map tree \\='(example-block src-block) #\\='identity)
 
 The following snippet will find the first headline with a level
 of 1 and a \"phone\" tag, and will return its beginning position:
@@ -4156,7 +4102,7 @@ of 1 and a \"phone\" tag, and will return its beginning 
position:
 The next example will return a flat list of all `plain-list' type
 elements in TREE that are not a sub-list themselves:
 
-  (org-element-map tree \\='plain-list \\='identity nil nil \\='plain-list)
+  (org-element-map tree \\='plain-list #\\='identity nil nil \\='plain-list)
 
 Eventually, this example will return a flat list of all `bold'
 type objects containing a `latex-snippet' type object, even
@@ -4164,116 +4110,101 @@ looking into captions:
 
   (org-element-map tree \\='bold
    (lambda (b)
-     (and (org-element-map b \\='latex-snippet \\='identity nil t) b))
+     (and (org-element-map b \\='latex-snippet #\\='identity nil t) b))
    nil nil nil t)"
   ;; Ensure TYPES and NO-RECURSION are a list, even of one element.
-  (unless (listp types) (setq types (list types)))
-  (unless (listp no-recursion) (setq no-recursion (list no-recursion)))
-  ;; Recursion depth is determined by --CATEGORY.
-  (let* ((--category
-         (catch 'found
-           (let ((category 'greater-elements))
-             (mapc (lambda (type)
-                     (cond ((or (memq type org-element-all-objects)
-                                (eq type 'plain-text))
-                            ;; If one object is found, the function
-                            ;; has to recurse into every object.
-                            (throw 'found 'objects))
-                           ((not (memq type org-element-greater-elements))
-                            ;; If one regular element is found, the
-                            ;; function has to recurse, at least,
-                            ;; into every element it encounters.
-                            (and (not (eq category 'elements))
-                                 (setq category 'elements)))))
-                   types)
-             category)))
-        ;; Compute properties for affiliated keywords if necessary.
-        (--affiliated-alist
-         (and with-affiliated
-              (mapcar (lambda (kwd)
-                        (cons kwd (intern (concat ":" (downcase kwd)))))
-                      org-element-affiliated-keywords)))
-        --acc
-        --walk-tree
-        (--walk-tree
-         (function
-          (lambda (--data)
-            ;; Recursively walk DATA.  INFO, if non-nil, is a plist
-            ;; holding contextual information.
-            (let ((--type (org-element-type --data)))
-              (cond
-               ((not --data))
-               ;; Ignored element in an export context.
-               ((and info (memq --data (plist-get info :ignore-list))))
-               ;; List of elements or objects.
-               ((not --type) (mapc --walk-tree --data))
-               ;; Unconditionally enter parse trees.
-               ((eq --type 'org-data)
-                (mapc --walk-tree (org-element-contents --data)))
-               (t
-                ;; Check if TYPE is matching among TYPES.  If so,
-                ;; apply FUN to --DATA and accumulate return value
-                ;; into --ACC (or exit if FIRST-MATCH is non-nil).
-                (when (memq --type types)
-                  (let ((result (funcall fun --data)))
-                    (cond ((not result))
-                          (first-match (throw '--map-first-match result))
-                          (t (push result --acc)))))
-                ;; If --DATA has a secondary string that can contain
-                ;; objects with their type among TYPES, look into it.
-                (when (and (eq --category 'objects) (not (stringp --data)))
-                  (let ((sec-prop
-                         (assq --type org-element-secondary-value-alist)))
-                    (when sec-prop
-                      (funcall --walk-tree
-                               (org-element-property (cdr sec-prop) --data)))))
-                ;; If --DATA has any affiliated keywords and
-                ;; WITH-AFFILIATED is non-nil, look for objects in
-                ;; them.
-                (when (and with-affiliated
-                           (eq --category 'objects)
-                           (memq --type org-element-all-elements))
-                  (mapc (lambda (kwd-pair)
-                          (let ((kwd (car kwd-pair))
-                                (value (org-element-property
-                                        (cdr kwd-pair) --data)))
-                            ;; Pay attention to the type of value.
-                            ;; Preserve order for multiple keywords.
-                            (cond
-                             ((not value))
-                             ((and (member kwd org-element-multiple-keywords)
-                                   (member kwd org-element-dual-keywords))
-                              (mapc (lambda (line)
-                                      (funcall --walk-tree (cdr line))
-                                      (funcall --walk-tree (car line)))
-                                    (reverse value)))
-                             ((member kwd org-element-multiple-keywords)
-                              (mapc (lambda (line) (funcall --walk-tree line))
-                                    (reverse value)))
-                             ((member kwd org-element-dual-keywords)
-                              (funcall --walk-tree (cdr value))
-                              (funcall --walk-tree (car value)))
-                             (t (funcall --walk-tree value)))))
-                        --affiliated-alist))
-                ;; Determine if a recursion into --DATA is possible.
-                (cond
-                 ;; --TYPE is explicitly removed from recursion.
-                 ((memq --type no-recursion))
-                 ;; --DATA has no contents.
-                 ((not (org-element-contents --data)))
-                 ;; Looking for greater elements but --DATA is simply
-                 ;; an element or an object.
-                 ((and (eq --category 'greater-elements)
-                       (not (memq --type org-element-greater-elements))))
-                 ;; Looking for elements but --DATA is an object.
-                 ((and (eq --category 'elements)
-                       (memq --type org-element-all-objects)))
-                 ;; In any other case, map contents.
-                 (t (mapc --walk-tree (org-element-contents --data)))))))))))
-    (catch '--map-first-match
-      (funcall --walk-tree data)
-      ;; Return value in a proper order.
-      (nreverse --acc))))
+  (let* ((types (if (listp types) types (list types)))
+        (no-recursion (if (listp no-recursion) no-recursion
+                        (list no-recursion)))
+        ;; Recursion depth is determined by --CATEGORY.
+        (--category
+         (catch :--found
+           (let ((category 'greater-elements)
+                 (all-objects (cons 'plain-text org-element-all-objects)))
+             (dolist (type types category)
+               (cond ((memq type all-objects)
+                      ;; If one object is found, the function has
+                      ;; to recurse into every object.
+                      (throw :--found 'objects))
+                     ((not (memq type org-element-greater-elements))
+                      ;; If one regular element is found, the
+                      ;; function has to recurse, at least, into
+                      ;; every element it encounters.
+                      (and (not (eq category 'elements))
+                           (setq category 'elements))))))))
+        --acc)
+    (letrec ((--walk-tree
+             (lambda (--data)
+               ;; Recursively walk DATA.  INFO, if non-nil, is a plist
+               ;; holding contextual information.
+               (let ((--type (org-element-type --data)))
+                 (cond
+                  ((not --data))
+                  ;; Ignored element in an export context.
+                  ((and info (memq --data (plist-get info :ignore-list))))
+                  ;; List of elements or objects.
+                  ((not --type) (mapc --walk-tree --data))
+                  ;; Unconditionally enter parse trees.
+                  ((eq --type 'org-data)
+                   (mapc --walk-tree (org-element-contents --data)))
+                  (t
+                   ;; Check if TYPE is matching among TYPES.  If so,
+                   ;; apply FUN to --DATA and accumulate return value
+                   ;; into --ACC (or exit if FIRST-MATCH is non-nil).
+                   (when (memq --type types)
+                     (let ((result (funcall fun --data)))
+                       (cond ((not result))
+                             (first-match (throw :--map-first-match result))
+                             (t (push result --acc)))))
+                   ;; If --DATA has a secondary string that can contain
+                   ;; objects with their type among TYPES, look inside.
+                   (when (and (eq --category 'objects) (not (stringp --data)))
+                     (dolist (p (cdr (assq --type
+                                           org-element-secondary-value-alist)))
+                       (funcall --walk-tree (org-element-property p --data))))
+                   ;; If --DATA has any parsed affiliated keywords and
+                   ;; WITH-AFFILIATED is non-nil, look for objects in
+                   ;; them.
+                   (when (and with-affiliated
+                              (eq --category 'objects)
+                              (eq (org-element-class --data) 'element))
+                     (dolist (kwd-pair org-element--parsed-properties-alist)
+                       (let ((kwd (car kwd-pair))
+                             (value (org-element-property (cdr kwd-pair) 
--data)))
+                         ;; Pay attention to the type of parsed
+                         ;; keyword.  In particular, preserve order for
+                         ;; multiple keywords.
+                         (cond
+                          ((not value))
+                          ((member kwd org-element-dual-keywords)
+                           (if (member kwd org-element-multiple-keywords)
+                               (dolist (line (reverse value))
+                                 (funcall --walk-tree (cdr line))
+                                 (funcall --walk-tree (car line)))
+                             (funcall --walk-tree (cdr value))
+                             (funcall --walk-tree (car value))))
+                          ((member kwd org-element-multiple-keywords)
+                           (mapc --walk-tree (reverse value)))
+                          (t (funcall --walk-tree value))))))
+                   ;; Determine if a recursion into --DATA is possible.
+                   (cond
+                    ;; --TYPE is explicitly removed from recursion.
+                    ((memq --type no-recursion))
+                    ;; --DATA has no contents.
+                    ((not (org-element-contents --data)))
+                    ;; Looking for greater elements but --DATA is
+                    ;; simply an element or an object.
+                    ((and (eq --category 'greater-elements)
+                          (not (memq --type org-element-greater-elements))))
+                    ;; Looking for elements but --DATA is an object.
+                    ((and (eq --category 'elements)
+                          (eq (org-element-class --data) 'object)))
+                    ;; In any other case, map contents.
+                    (t (mapc --walk-tree (org-element-contents --data))))))))))
+      (catch :--map-first-match
+       (funcall --walk-tree data)
+       ;; Return value in a proper order.
+       (nreverse --acc)))))
 (put 'org-element-map 'lisp-indent-function 2)
 
 ;; The following functions are internal parts of the parser.
@@ -4282,24 +4213,38 @@ looking into captions:
 ;; level.
 ;;
 ;; The second one, `org-element--parse-objects' applies on all objects
-;; of a paragraph or a secondary string.  It uses
-;; `org-element--get-next-object-candidates' to optimize the search of
-;; the next object in the buffer.
-;;
-;; More precisely, that function looks for every allowed object type
-;; first.  Then, it discards failed searches, keeps further matches,
-;; and searches again types matched behind point, for subsequent
-;; calls.  Thus, searching for a given type fails only once, and every
-;; object is searched only once at top level (but sometimes more for
-;; nested types).
+;; of a paragraph or a secondary string.  It calls
+;; `org-element--object-lex' to find the next object in the current
+;; container.
+
+(defsubst org-element--next-mode (type parentp)
+  "Return next special mode according to TYPE, or nil.
+TYPE is a symbol representing the type of an element or object
+containing next element if PARENTP is non-nil, or before it
+otherwise.  Modes can be either `first-section', `item',
+`node-property', `planning', `property-drawer', `section',
+`table-row' or nil."
+  (if parentp
+      (pcase type
+       (`headline 'section)
+       (`inlinetask 'planning)
+       (`plain-list 'item)
+       (`property-drawer 'node-property)
+       (`section 'planning)
+       (`table 'table-row))
+    (pcase type
+      (`item 'item)
+      (`node-property 'node-property)
+      (`planning 'property-drawer)
+      (`table-row 'table-row))))
 
 (defun org-element--parse-elements
-  (beg end special structure granularity visible-only acc)
+    (beg end mode structure granularity visible-only acc)
   "Parse elements between BEG and END positions.
 
-SPECIAL prioritize some elements over the others.  It can be set
-to `first-section', `quote-section', `section' `item' or
-`table-row'.
+MODE prioritizes some elements over the others.  It can be set to
+`first-section', `section', `planning', `item', `node-property'
+or `table-row'.
 
 When value is `item', STRUCTURE will be used as the current list
 structure.
@@ -4320,140 +4265,205 @@ Elements are accumulated into ACC."
     ;; When parsing only headlines, skip any text before first one.
     (when (and (eq granularity 'headline) (not (org-at-heading-p)))
       (org-with-limited-levels (outline-next-heading)))
-    ;; Main loop start.
-    (while (< (point) end)
-      ;; Find current element's type and parse it accordingly to
-      ;; its category.
-      (let* ((element (org-element--current-element
-                      end granularity special structure))
-            (type (org-element-type element))
-            (cbeg (org-element-property :contents-begin element)))
-       (goto-char (org-element-property :end element))
-       ;; Visible only: skip invisible parts between siblings.
-       (when (and visible-only (org-invisible-p2))
-         (goto-char (min (1+ (org-find-visible)) end)))
-       ;; Fill ELEMENT contents by side-effect.
-       (cond
-        ;; If element has no contents, don't modify it.
-        ((not cbeg))
-        ;; Greater element: parse it between `contents-begin' and
-        ;; `contents-end'.  Make sure GRANULARITY allows the
-        ;; recursion, or ELEMENT is a headline, in which case going
-        ;; inside is mandatory, in order to get sub-level headings.
-        ((and (memq type org-element-greater-elements)
-              (or (memq granularity '(element object nil))
-                  (and (eq granularity 'greater-element)
-                       (eq type 'section))
-                  (eq type 'headline)))
-         (org-element--parse-elements
-          cbeg (org-element-property :contents-end element)
-          ;; Possibly switch to a special mode.
-          (case type
-            (headline
-             (if (org-element-property :quotedp element) 'quote-section
-               'section))
-            (plain-list 'item)
-            (property-drawer 'node-property)
-            (table 'table-row))
-          (and (memq type '(item plain-list))
-               (org-element-property :structure element))
-          granularity visible-only element))
-        ;; ELEMENT has contents.  Parse objects inside, if
-        ;; GRANULARITY allows it.
-        ((memq granularity '(object nil))
-         (org-element--parse-objects
-          cbeg (org-element-property :contents-end element) element
-          (org-element-restriction type))))
-       (org-element-adopt-elements acc element)))
-    ;; Return result.
-    acc))
-
-(defun org-element--parse-objects (beg end acc restriction)
+    (let (elements)
+      (while (< (point) end)
+       ;; Find current element's type and parse it accordingly to
+       ;; its category.
+       (let* ((element (org-element--current-element
+                        end granularity mode structure))
+              (type (org-element-type element))
+              (cbeg (org-element-property :contents-begin element)))
+         (goto-char (org-element-property :end element))
+         ;; Visible only: skip invisible parts between siblings.
+         (when (and visible-only (org-invisible-p2))
+           (goto-char (min (1+ (org-find-visible)) end)))
+         ;; Fill ELEMENT contents by side-effect.
+         (cond
+          ;; If element has no contents, don't modify it.
+          ((not cbeg))
+          ;; Greater element: parse it between `contents-begin' and
+          ;; `contents-end'.  Make sure GRANULARITY allows the
+          ;; recursion, or ELEMENT is a headline, in which case going
+          ;; inside is mandatory, in order to get sub-level headings.
+          ((and (memq type org-element-greater-elements)
+                (or (memq granularity '(element object nil))
+                    (and (eq granularity 'greater-element)
+                         (eq type 'section))
+                    (eq type 'headline)))
+           (org-element--parse-elements
+            cbeg (org-element-property :contents-end element)
+            ;; Possibly switch to a special mode.
+            (org-element--next-mode type t)
+            (and (memq type '(item plain-list))
+                 (org-element-property :structure element))
+            granularity visible-only element))
+          ;; ELEMENT has contents.  Parse objects inside, if
+          ;; GRANULARITY allows it.
+          ((memq granularity '(object nil))
+           (org-element--parse-objects
+            cbeg (org-element-property :contents-end element) element
+            (org-element-restriction type))))
+         (push (org-element-put-property element :parent acc) elements)
+         ;; Update mode.
+         (setq mode (org-element--next-mode type nil))))
+      ;; Return result.
+      (apply #'org-element-set-contents acc (nreverse elements)))))
+
+(defun org-element--object-lex (restriction)
+  "Return next object in current buffer or nil.
+RESTRICTION is a list of object types, as symbols, that should be
+looked after.  This function assumes that the buffer is narrowed
+to an appropriate container (e.g., a paragraph)."
+  (if (memq 'table-cell restriction) (org-element-table-cell-parser)
+    (let* ((start (point))
+          (limit
+           ;; Object regexp sometimes needs to have a peek at
+           ;; a character ahead.  Therefore, when there is a hard
+           ;; limit, make it one more than the true beginning of the
+           ;; radio target.
+           (save-excursion
+             (cond ((not org-target-link-regexp) nil)
+                   ((not (memq 'link restriction)) nil)
+                   ((progn
+                      (unless (bolp) (forward-char -1))
+                      (not (re-search-forward org-target-link-regexp nil t)))
+                    nil)
+                   ;; Since we moved backward, we do not want to
+                   ;; match again an hypothetical 1-character long
+                   ;; radio link before us.  Realizing that this can
+                   ;; only happen if such a radio link starts at
+                   ;; beginning of line, we prevent this here.
+                   ((and (= start (1+ (line-beginning-position)))
+                         (= start (match-end 1)))
+                    (and (re-search-forward org-target-link-regexp nil t)
+                         (1+ (match-beginning 1))))
+                   (t (1+ (match-beginning 1))))))
+          found)
+      (save-excursion
+       (while (and (not found)
+                   (re-search-forward org-element--object-regexp limit 'move))
+         (goto-char (match-beginning 0))
+         (let ((result (match-string 0)))
+           (setq found
+                 (cond
+                  ((string-prefix-p "call_" result t)
+                   (and (memq 'inline-babel-call restriction)
+                        (org-element-inline-babel-call-parser)))
+                  ((string-prefix-p "src_" result t)
+                   (and (memq 'inline-src-block restriction)
+                        (org-element-inline-src-block-parser)))
+                  (t
+                   (pcase (char-after)
+                     (?^ (and (memq 'superscript restriction)
+                              (org-element-superscript-parser)))
+                     (?_ (or (and (memq 'subscript restriction)
+                                  (org-element-subscript-parser))
+                             (and (memq 'underline restriction)
+                                  (org-element-underline-parser))))
+                     (?* (and (memq 'bold restriction)
+                              (org-element-bold-parser)))
+                     (?/ (and (memq 'italic restriction)
+                              (org-element-italic-parser)))
+                     (?~ (and (memq 'code restriction)
+                              (org-element-code-parser)))
+                     (?= (and (memq 'verbatim restriction)
+                              (org-element-verbatim-parser)))
+                     (?+ (and (memq 'strike-through restriction)
+                              (org-element-strike-through-parser)))
+                     (?@ (and (memq 'export-snippet restriction)
+                              (org-element-export-snippet-parser)))
+                     (?{ (and (memq 'macro restriction)
+                              (org-element-macro-parser)))
+                     (?$ (and (memq 'latex-fragment restriction)
+                              (org-element-latex-fragment-parser)))
+                     (?<
+                      (if (eq (aref result 1) ?<)
+                          (or (and (memq 'radio-target restriction)
+                                   (org-element-radio-target-parser))
+                              (and (memq 'target restriction)
+                                   (org-element-target-parser)))
+                        (or (and (memq 'timestamp restriction)
+                                 (org-element-timestamp-parser))
+                            (and (or (memq 'link restriction)
+                                     (memq 'simple-link restriction))
+                                 (org-element-link-parser)))))
+                     (?\\
+                      (if (eq (aref result 1) ?\\)
+                          (and (memq 'line-break restriction)
+                               (org-element-line-break-parser))
+                        (or (and (memq 'entity restriction)
+                                 (org-element-entity-parser))
+                            (and (memq 'latex-fragment restriction)
+                                 (org-element-latex-fragment-parser)))))
+                     (?\[
+                      (if (eq (aref result 1) ?\[)
+                          (and (memq 'link restriction)
+                               (org-element-link-parser))
+                        (or (and (memq 'footnote-reference restriction)
+                                 (org-element-footnote-reference-parser))
+                            (and (memq 'timestamp restriction)
+                                 (org-element-timestamp-parser))
+                            (and (memq 'statistics-cookie restriction)
+                                 (org-element-statistics-cookie-parser)))))
+                     ;; This is probably a plain link.
+                     (_ (and (or (memq 'link restriction)
+                                 (memq 'simple-link restriction))
+                             (org-element-link-parser)))))))
+           (or (eobp) (forward-char))))
+       (cond (found)
+             (limit (forward-char -1)
+                    (org-element-link-parser)) ;radio link
+             (t nil))))))
+
+(defun org-element--parse-objects (beg end acc restriction &optional parent)
   "Parse objects between BEG and END and return recursive structure.
 
-Objects are accumulated in ACC.
+Objects are accumulated in ACC.  RESTRICTION is a list of object
+successors which are allowed in the current object.
 
-RESTRICTION is a list of object successors which are allowed in
-the current object."
-  (let ((candidates 'initial))
-    (save-excursion
-      (save-restriction
-       (narrow-to-region beg end)
-       (goto-char (point-min))
+ACC becomes the parent for all parsed objects.  However, if ACC
+is nil (i.e., a secondary string is being parsed) and optional
+argument PARENT is non-nil, use it as the parent for all objects.
+Eventually, if both ACC and PARENT are nil, the common parent is
+the list of objects itself."
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (goto-char (point-min))
+      (let (next-object contents)
        (while (and (not (eobp))
-                   (setq candidates
-                         (org-element--get-next-object-candidates
-                          restriction candidates)))
-         (let ((next-object
-                (let ((pos (apply 'min (mapcar 'cdr candidates))))
-                  (save-excursion
-                    (goto-char pos)
-                    (funcall (intern (format "org-element-%s-parser"
-                                             (car (rassq pos 
candidates)))))))))
-           ;; 1. Text before any object.  Untabify it.
-           (let ((obj-beg (org-element-property :begin next-object)))
-             (unless (= (point) obj-beg)
-               (setq acc
-                     (org-element-adopt-elements
-                      acc
-                      (replace-regexp-in-string
-                       "\t" (make-string tab-width ? )
-                       (buffer-substring-no-properties (point) obj-beg))))))
-           ;; 2. Object...
-           (let ((obj-end (org-element-property :end next-object))
-                 (cont-beg (org-element-property :contents-begin next-object)))
-             ;; Fill contents of NEXT-OBJECT by side-effect, if it has
-             ;; a recursive type.
-             (when (and cont-beg
-                        (memq (car next-object) org-element-recursive-objects))
-               (org-element--parse-objects
-                cont-beg (org-element-property :contents-end next-object)
-                next-object (org-element-restriction next-object)))
-             (setq acc (org-element-adopt-elements acc next-object))
-             (goto-char obj-end))))
-       ;; 3. Text after last object.  Untabify it.
+                   (setq next-object (org-element--object-lex restriction)))
+         ;; Text before any object.
+         (let ((obj-beg (org-element-property :begin next-object)))
+           (unless (= (point) obj-beg)
+             (let ((text (buffer-substring-no-properties (point) obj-beg)))
+               (push (if acc (org-element-put-property text :parent acc) text)
+                     contents))))
+         ;; Object...
+         (let ((obj-end (org-element-property :end next-object))
+               (cont-beg (org-element-property :contents-begin next-object)))
+           (when acc (org-element-put-property next-object :parent acc))
+           (push (if cont-beg
+                     ;; Fill contents of NEXT-OBJECT if possible.
+                     (org-element--parse-objects
+                      cont-beg
+                      (org-element-property :contents-end next-object)
+                      next-object
+                      (org-element-restriction next-object))
+                   next-object)
+                 contents)
+           (goto-char obj-end)))
+       ;; Text after last object.
        (unless (eobp)
-         (setq acc
-               (org-element-adopt-elements
-                acc
-                (replace-regexp-in-string
-                 "\t" (make-string tab-width ? )
-                 (buffer-substring-no-properties (point) end)))))
-       ;; Result.
-       acc))))
-
-(defun org-element--get-next-object-candidates (restriction objects)
-  "Return an alist of candidates for the next object.
-
-RESTRICTION is a list of object types, as symbols.  Only
-candidates with such types are looked after.
-
-OBJECTS is the previous candidates alist.  If it is set to
-`initial', no search has been done before, and all symbols in
-RESTRICTION should be looked after.
-
-Return value is an alist whose CAR is the object type and CDR its
-beginning position."
-  (delq
-   nil
-   (if (eq objects 'initial)
-       ;; When searching for the first time, look for every successor
-       ;; allowed in RESTRICTION.
-       (mapcar
-       (lambda (res)
-         (funcall (intern (format "org-element-%s-successor" res))))
-       restriction)
-     ;; Focus on objects returned during last search.  Keep those
-     ;; still after point.  Search again objects before it.
-     (mapcar
-      (lambda (obj)
-       (if (>= (cdr obj) (point)) obj
-         (let* ((type (car obj))
-                (succ (or (cdr (assq type org-element-object-successor-alist))
-                          type)))
-           (and succ
-                (funcall (intern (format "org-element-%s-successor" succ)))))))
-      objects))))
+         (let ((text (buffer-substring-no-properties (point) end)))
+           (push (if acc (org-element-put-property text :parent acc) text)
+                 contents)))
+       ;; Result.  Set appropriate parent.
+       (if acc (apply #'org-element-set-contents acc (nreverse contents))
+         (let* ((contents (nreverse contents))
+                (parent (or parent contents)))
+           (dolist (datum contents contents)
+             (org-element-put-property datum :parent parent))))))))
 
 
 
@@ -4468,71 +4478,74 @@ beginning position."
 ;; `org-element--interpret-affiliated-keywords'.
 
 ;;;###autoload
-(defun org-element-interpret-data (data &optional parent)
+(defun org-element-interpret-data (data)
   "Interpret DATA as Org syntax.
-
 DATA is a parse tree, an element, an object or a secondary string
-to interpret.
-
-Optional argument PARENT is used for recursive calls.  It contains
-the element or object containing data, or nil.
-
-Return Org syntax as a string."
-  (let* ((type (org-element-type data))
-        (results
-         (cond
-          ;; Secondary string.
-          ((not type)
-           (mapconcat
-            (lambda (obj) (org-element-interpret-data obj parent))
-            data ""))
-          ;; Full Org document.
-          ((eq type 'org-data)
-           (mapconcat
-            (lambda (obj) (org-element-interpret-data obj parent))
-            (org-element-contents data) ""))
-          ;; Plain text: return it.
-          ((stringp data) data)
-          ;; Element/Object without contents.
-          ((not (org-element-contents data))
-           (funcall (intern (format "org-element-%s-interpreter" type))
-                    data nil))
-          ;; Element/Object with contents.
-          (t
-           (let* ((greaterp (memq type org-element-greater-elements))
-                  (objectp (and (not greaterp)
-                                (memq type org-element-recursive-objects)))
-                  (contents
-                   (mapconcat
-                    (lambda (obj) (org-element-interpret-data obj data))
-                    (org-element-contents
-                     (if (or greaterp objectp) data
-                       ;; Elements directly containing objects must
-                       ;; have their indentation normalized first.
-                       (org-element-normalize-contents
+to interpret.  Return Org syntax as a string."
+  (letrec ((fun
+           (lambda (data parent)
+             (let* ((type (org-element-type data))
+                    ;; Find interpreter for current object or
+                    ;; element.  If it doesn't exist (e.g. this is
+                    ;; a pseudo object or element), return contents,
+                    ;; if any.
+                    (interpret
+                     (let ((fun (intern
+                                 (format "org-element-%s-interpreter" type))))
+                       (if (fboundp fun) fun (lambda (_ contents) contents))))
+                    (results
+                     (cond
+                      ;; Secondary string.
+                      ((not type)
+                       (mapconcat (lambda (obj) (funcall fun obj parent))
+                                  data
+                                  ""))
+                      ;; Full Org document.
+                      ((eq type 'org-data)
+                       (mapconcat (lambda (obj) (funcall fun obj parent))
+                                  (org-element-contents data)
+                                  ""))
+                      ;; Plain text: return it.
+                      ((stringp data) data)
+                      ;; Element or object without contents.
+                      ((not (org-element-contents data))
+                       (funcall interpret data nil))
+                      ;; Element or object with contents.
+                      (t
+                       (funcall
+                        interpret
                         data
-                        ;; When normalizing first paragraph of an
-                        ;; item or a footnote-definition, ignore
-                        ;; first line's indentation.
-                        (and (eq type 'paragraph)
-                             (equal data (car (org-element-contents parent)))
-                             (memq (org-element-type parent)
-                                   '(footnote-definition item))))))
-                    "")))
-             (funcall (intern (format "org-element-%s-interpreter" type))
-                      data
-                      (if greaterp (org-element-normalize-contents contents)
-                        contents)))))))
-    (if (memq type '(org-data plain-text nil)) results
-      ;; Build white spaces.  If no `:post-blank' property is
-      ;; specified, assume its value is 0.
-      (let ((post-blank (or (org-element-property :post-blank data) 0)))
-       (if (memq type org-element-all-objects)
-           (concat results (make-string post-blank 32))
-         (concat
-          (org-element--interpret-affiliated-keywords data)
-          (org-element-normalize-string results)
-          (make-string post-blank 10)))))))
+                        ;; Recursively interpret contents.
+                        (mapconcat
+                         (lambda (datum) (funcall fun datum data))
+                         (org-element-contents
+                          (if (not (memq type '(paragraph verse-block)))
+                              data
+                            ;; Fix indentation of elements containing
+                            ;; objects.  We ignore `table-row'
+                            ;; elements as they are one line long
+                            ;; anyway.
+                            (org-element-normalize-contents
+                             data
+                             ;; When normalizing first paragraph of
+                             ;; an item or a footnote-definition,
+                             ;; ignore first line's indentation.
+                             (and (eq type 'paragraph)
+                                  (memq (org-element-type parent)
+                                        '(footnote-definition item))
+                                  (eq data
+                                      (car (org-element-contents parent)))))))
+                         ""))))))
+               (if (memq type '(org-data plain-text nil)) results
+                 ;; Build white spaces.  If no `:post-blank' property
+                 ;; is specified, assume its value is 0.
+                 (let ((blank (or (org-element-property :post-blank data) 0)))
+                   (if (eq (org-element-class data parent) 'object)
+                       (concat results (make-string blank ?\s))
+                     (concat (org-element--interpret-affiliated-keywords data)
+                             (org-element-normalize-string results)
+                             (make-string blank ?\n)))))))))
+    (funcall fun data nil)))
 
 (defun org-element--interpret-affiliated-keywords (element)
   "Return ELEMENT's affiliated keywords as Org syntax.
@@ -4566,14 +4579,14 @@ If there is no affiliated keyword, return the empty 
string."
      ;; List all ELEMENT's properties matching an attribute line or an
      ;; affiliated keyword, but ignore translated keywords since they
      ;; cannot belong to the property list.
-     (loop for prop in (nth 1 element) by 'cddr
-          when (let ((keyword (upcase (substring (symbol-name prop) 1))))
-                 (or (string-match "^ATTR_" keyword)
-                     (and
-                      (member keyword org-element-affiliated-keywords)
-                      (not (assoc keyword
-                                  org-element-keyword-translation-alist)))))
-          collect prop)
+     (cl-loop for prop in (nth 1 element) by 'cddr
+             when (let ((keyword (upcase (substring (symbol-name prop) 1))))
+                    (or (string-match "^ATTR_" keyword)
+                        (and
+                         (member keyword org-element-affiliated-keywords)
+                         (not (assoc keyword
+                                     org-element-keyword-translation-alist)))))
+             collect prop)
      "")))
 
 ;; Because interpretation of the parse tree must return the same
@@ -4609,67 +4622,1109 @@ If optional argument IGNORE-FIRST is non-nil, ignore 
first line's
 indentation to compute maximal common indentation.
 
 Return the normalized element that is element with global
-indentation removed from its contents.  The function assumes that
-indentation is not done with TAB characters."
-  (let* ((min-ind most-positive-fixnum)
-        find-min-ind                   ; For byte-compiler.
-        (find-min-ind
-         ;; Return minimal common indentation within BLOB.  This is
-         ;; done by walking recursively BLOB and updating MIN-IND
-         ;; along the way.  FIRST-FLAG is non-nil when the first
-         ;; string hasn't been seen yet.  It is required as this
-         ;; string is the only one whose indentation doesn't happen
-         ;; after a newline character.
-         (lambda (blob first-flag)
-           (dolist (object (org-element-contents blob))
-             (when (and first-flag (stringp object))
-               (setq first-flag nil)
-               (string-match "\\` *" object)
-               (let ((len (match-end 0)))
-                 ;; An indentation of zero means no string will be
-                 ;; modified.  Quit the process.
-                 (if (zerop len) (throw 'zero (setq min-ind 0))
-                   (setq min-ind (min len min-ind)))))
-             (cond
-              ((stringp object)
-               (dolist (line (cdr (org-split-string object " *\n")))
-                 (unless (string= line "")
-                   (setq min-ind (min (org-get-indentation line) min-ind)))))
-              ((memq (org-element-type object) org-element-recursive-objects)
-               (funcall find-min-ind object first-flag)))))))
-    ;; Find minimal indentation in ELEMENT.
-    (catch 'zero (funcall find-min-ind element (not ignore-first)))
+indentation removed from its contents."
+  (letrec ((find-min-ind
+           ;; Return minimal common indentation within BLOB.  This is
+           ;; done by walking recursively BLOB and updating MIN-IND
+           ;; along the way.  FIRST-FLAG is non-nil when the next
+           ;; object is expected to be a string that doesn't start
+           ;; with a newline character.  It happens for strings at
+           ;; the beginnings of the contents or right after a line
+           ;; break.
+           (lambda (blob first-flag min-ind)
+             (dolist (datum (org-element-contents blob) min-ind)
+               (when first-flag
+                 (setq first-flag nil)
+                 (cond
+                  ;; Objects cannot start with spaces: in this
+                  ;; case, indentation is 0.
+                  ((not (stringp datum)) (throw :zero 0))
+                  ((not (string-match
+                         "\\`\\([ \t]+\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum))
+                   (throw :zero 0))
+                  ((equal (match-string 2 datum) "\n")
+                   (put-text-property
+                    (match-beginning 1) (match-end 1) 'org-ind 'empty datum))
+                  (t
+                   (let ((i (string-width (match-string 1 datum))))
+                     (put-text-property
+                      (match-beginning 1) (match-end 1) 'org-ind i datum)
+                     (setq min-ind (min i min-ind))))))
+               (cond
+                ((stringp datum)
+                 (let ((s 0))
+                   (while (string-match
+                           "\n\\([ \t]*\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum s)
+                     (setq s (match-end 1))
+                     (cond
+                      ((equal (match-string 1 datum) "")
+                       (unless (member (match-string 2 datum) '("" "\n"))
+                         (throw :zero 0)))
+                      ((equal (match-string 2 datum) "\n")
+                       (put-text-property (match-beginning 1) (match-end 1)
+                                          'org-ind 'empty datum))
+                      (t
+                       (let ((i (string-width (match-string 1 datum))))
+                         (put-text-property (match-beginning 1) (match-end 1)
+                                            'org-ind i datum)
+                         (setq min-ind (min i min-ind))))))))
+                ((eq (org-element-type datum) 'line-break)
+                 (setq first-flag t))
+                ((memq (org-element-type datum) org-element-recursive-objects)
+                 (setq min-ind
+                       (funcall find-min-ind datum first-flag min-ind)))))))
+          (min-ind
+           (catch :zero
+             (funcall find-min-ind
+                      element (not ignore-first) most-positive-fixnum))))
     (if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element
       ;; Build ELEMENT back, replacing each string with the same
       ;; string minus common indentation.
-      (let* (build                     ; For byte compiler.
-            (build
-             (function
-              (lambda (blob first-flag)
-                ;; Return BLOB with all its strings indentation
-                ;; shortened from MIN-IND white spaces.  FIRST-FLAG
-                ;; is non-nil when the first string hasn't been seen
-                ;; yet.
-                (setcdr (cdr blob)
-                        (mapcar
-                         #'(lambda (object)
-                             (when (and first-flag (stringp object))
-                               (setq first-flag nil)
-                               (setq object
-                                     (replace-regexp-in-string
-                                      (format "\\` \\{%d\\}" min-ind)
-                                      "" object)))
-                             (cond
-                              ((stringp object)
-                               (replace-regexp-in-string
-                                (format "\n \\{%d\\}" min-ind) "\n" object))
-                              ((memq (org-element-type object)
-                                     org-element-recursive-objects)
-                               (funcall build object first-flag))
-                              (t object)))
-                         (org-element-contents blob)))
-                blob))))
-       (funcall build element (not ignore-first))))))
+      (letrec ((build
+               (lambda (datum)
+                 ;; Return DATUM with all its strings indentation
+                 ;; shortened from MIN-IND white spaces.
+                 (setcdr
+                  (cdr datum)
+                  (mapcar
+                   (lambda (object)
+                     (cond
+                      ((stringp object)
+                       (with-temp-buffer
+                         (insert object)
+                         (let ((s (point-min)))
+                           (while (setq s (text-property-not-all
+                                           s (point-max) 'org-ind nil))
+                             (goto-char s)
+                             (let ((i (get-text-property s 'org-ind)))
+                               (delete-region s (progn
+                                                  (skip-chars-forward " \t")
+                                                  (point)))
+                               (when (integerp i) (indent-to (- i min-ind))))))
+                         (buffer-string)))
+                      ((memq (org-element-type object)
+                             org-element-recursive-objects)
+                       (funcall build object))
+                      (t object)))
+                   (org-element-contents datum)))
+                 datum)))
+       (funcall build element)))))
+
+
+
+;;; Cache
+;;
+;; Implement a caching mechanism for `org-element-at-point' and
+;; `org-element-context', which see.
+;;
+;; A single public function is provided: `org-element-cache-reset'.
+;;
+;; Cache is enabled by default, but can be disabled globally with
+;; `org-element-use-cache'.  `org-element-cache-sync-idle-time',
+;; org-element-cache-sync-duration' and `org-element-cache-sync-break'
+;; can be tweaked to control caching behaviour.
+;;
+;; Internally, parsed elements are stored in an AVL tree,
+;; `org-element--cache'.  This tree is updated lazily: whenever
+;; a change happens to the buffer, a synchronization request is
+;; registered in `org-element--cache-sync-requests' (see
+;; `org-element--cache-submit-request').  During idle time, requests
+;; are processed by `org-element--cache-sync'.  Synchronization also
+;; happens when an element is required from the cache.  In this case,
+;; the process stops as soon as the needed element is up-to-date.
+;;
+;; A synchronization request can only apply on a synchronized part of
+;; the cache.  Therefore, the cache is updated at least to the
+;; location where the new request applies.  Thus, requests are ordered
+;; from left to right and all elements starting before the first
+;; request are correct.  This property is used by functions like
+;; `org-element--cache-find' to retrieve elements in the part of the
+;; cache that can be trusted.
+;;
+;; A request applies to every element, starting from its original
+;; location (or key, see below).  When a request is processed, it
+;; moves forward and may collide the next one.  In this case, both
+;; requests are merged into a new one that starts from that element.
+;; As a consequence, the whole synchronization complexity does not
+;; depend on the number of pending requests, but on the number of
+;; elements the very first request will be applied on.
+;;
+;; Elements cannot be accessed through their beginning position, which
+;; may or may not be up-to-date.  Instead, each element in the tree is
+;; associated to a key, obtained with `org-element--cache-key'.  This
+;; mechanism is robust enough to preserve total order among elements
+;; even when the tree is only partially synchronized.
+;;
+;; Objects contained in an element are stored in a hash table,
+;; `org-element--cache-objects'.
+
+
+(defvar org-element-use-cache nil
+  "Non-nil when Org parser should cache its results.
+
+WARNING: for the time being, using cache sometimes triggers
+freezes.  Therefore, it is disabled by default.  Activate it if
+you want to help debugging the issue.")
+
+(defvar org-element-cache-sync-idle-time 0.6
+  "Length, in seconds, of idle time before syncing cache.")
+
+(defvar org-element-cache-sync-duration (seconds-to-time 0.04)
+  "Maximum duration, as a time value, for a cache synchronization.
+If the synchronization is not over after this delay, the process
+pauses and resumes after `org-element-cache-sync-break'
+seconds.")
+
+(defvar org-element-cache-sync-break (seconds-to-time 0.3)
+  "Duration, as a time value, of the pause between synchronizations.
+See `org-element-cache-sync-duration' for more information.")
+
+
+;;;; Data Structure
+
+(defvar org-element--cache nil
+  "AVL tree used to cache elements.
+Each node of the tree contains an element.  Comparison is done
+with `org-element--cache-compare'.  This cache is used in
+`org-element-at-point'.")
+
+(defvar org-element--cache-objects nil
+  "Hash table used as to cache objects.
+Key is an element, as returned by `org-element-at-point', and
+value is an alist where each association is:
+
+  (PARENT COMPLETEP . OBJECTS)
+
+where PARENT is an element or object, COMPLETEP is a boolean,
+non-nil when all direct children of parent are already cached and
+OBJECTS is a list of such children, as objects, from farthest to
+closest.
+
+In the following example, \\alpha, bold object and \\beta are
+contained within a paragraph
+
+  \\alpha *\\beta*
+
+If the paragraph is completely parsed, OBJECTS-DATA will be
+
+  ((PARAGRAPH t BOLD-OBJECT ENTITY-OBJECT)
+   (BOLD-OBJECT t ENTITY-OBJECT))
+
+whereas in a partially parsed paragraph, it could be
+
+  ((PARAGRAPH nil ENTITY-OBJECT))
+
+This cache is used in `org-element-context'.")
+
+(defvar org-element--cache-sync-requests nil
+  "List of pending synchronization requests.
+
+A request is a vector with the following pattern:
+
+ \[NEXT BEG END OFFSET PARENT PHASE]
+
+Processing a synchronization request consists of three phases:
+
+  0. Delete modified elements,
+  1. Fill missing area in cache,
+  2. Shift positions and re-parent elements after the changes.
+
+During phase 0, NEXT is the key of the first element to be
+removed, BEG and END is buffer position delimiting the
+modifications.  Elements starting between them (inclusive) are
+removed.  So are elements whose parent is removed.  PARENT, when
+non-nil, is the parent of the first element to be removed.
+
+During phase 1, NEXT is the key of the next known element in
+cache and BEG its beginning position.  Parse buffer between that
+element and the one before it in order to determine the parent of
+the next element.  Set PARENT to the element containing NEXT.
+
+During phase 2, NEXT is the key of the next element to shift in
+the parse tree.  All elements starting from this one have their
+properties relatives to buffer positions shifted by integer
+OFFSET and, if they belong to element PARENT, are adopted by it.
+
+PHASE specifies the phase number, as an integer.")
+
+(defvar org-element--cache-sync-timer nil
+  "Timer used for cache synchronization.")
+
+(defvar org-element--cache-sync-keys nil
+  "Hash table used to store keys during synchronization.
+See `org-element--cache-key' for more information.")
+
+(defsubst org-element--cache-key (element)
+  "Return a unique key for ELEMENT in cache tree.
+
+Keys are used to keep a total order among elements in the cache.
+Comparison is done with `org-element--cache-key-less-p'.
+
+When no synchronization is taking place, a key is simply the
+beginning position of the element, or that position plus one in
+the case of an first item (respectively row) in
+a list (respectively a table).
+
+During a synchronization, the key is the one the element had when
+the cache was synchronized for the last time.  Elements added to
+cache during the synchronization get a new key generated with
+`org-element--cache-generate-key'.
+
+Such keys are stored in `org-element--cache-sync-keys'.  The hash
+table is cleared once the synchronization is complete."
+  (or (gethash element org-element--cache-sync-keys)
+      (let* ((begin (org-element-property :begin element))
+            ;; Increase beginning position of items (respectively
+            ;; table rows) by one, so the first item can get
+            ;; a different key from its parent list (respectively
+            ;; table).
+            (key (if (memq (org-element-type element) '(item table-row))
+                     (1+ begin)
+                   begin)))
+       (if org-element--cache-sync-requests
+           (puthash element key org-element--cache-sync-keys)
+         key))))
+
+(defun org-element--cache-generate-key (lower upper)
+  "Generate a key between LOWER and UPPER.
+
+LOWER and UPPER are integers or lists, possibly empty.
+
+If LOWER and UPPER are equals, return LOWER.  Otherwise, return
+a unique key, as an integer or a list of integers, according to
+the following rules:
+
+  - LOWER and UPPER are compared level-wise until values differ.
+
+  - If, at a given level, LOWER and UPPER differ from more than
+    2, the new key shares all the levels above with LOWER and
+    gets a new level.  Its value is the mean between LOWER and
+    UPPER:
+
+      (1 2) + (1 4) --> (1 3)
+
+  - If LOWER has no value to compare with, it is assumed that its
+    value is `most-negative-fixnum'.  E.g.,
+
+      (1 1) + (1 1 2)
+
+    is equivalent to
+
+      (1 1 m) + (1 1 2)
+
+    where m is `most-negative-fixnum'.  Likewise, if UPPER is
+    short of levels, the current value is `most-positive-fixnum'.
+
+  - If they differ from only one, the new key inherits from
+    current LOWER level and fork it at the next level.  E.g.,
+
+      (2 1) + (3 3)
+
+    is equivalent to
+
+      (2 1) + (2 M)
+
+    where M is `most-positive-fixnum'.
+
+  - If the key is only one level long, it is returned as an
+    integer:
+
+      (1 2) + (3 2) --> 2
+
+When they are not equals, the function assumes that LOWER is
+lesser than UPPER, per `org-element--cache-key-less-p'."
+  (if (equal lower upper) lower
+    (let ((lower (if (integerp lower) (list lower) lower))
+         (upper (if (integerp upper) (list upper) upper))
+          skip-upper key)
+      (catch 'exit
+       (while t
+         (let ((min (or (car lower) most-negative-fixnum))
+               (max (cond (skip-upper most-positive-fixnum)
+                           ((car upper))
+                           (t most-positive-fixnum))))
+            (if (< (1+ min) max)
+               (let ((mean (+ (ash min -1) (ash max -1) (logand min max 1))))
+                 (throw 'exit (if key (nreverse (cons mean key)) mean)))
+             (when (and (< min max) (not skip-upper))
+               ;; When at a given level, LOWER and UPPER differ from
+               ;; 1, ignore UPPER altogether.  Instead create a key
+               ;; between LOWER and the greatest key with the same
+               ;; prefix as LOWER so far.
+               (setq skip-upper t))
+             (push min key)
+             (setq lower (cdr lower) upper (cdr upper)))))))))
+
+(defsubst org-element--cache-key-less-p (a b)
+  "Non-nil if key A is less than key B.
+A and B are either integers or lists of integers, as returned by
+`org-element--cache-key'."
+  (if (integerp a) (if (integerp b) (< a b) (<= a (car b)))
+    (if (integerp b) (< (car a) b)
+      (catch 'exit
+       (while (and a b)
+         (cond ((car-less-than-car a b) (throw 'exit t))
+               ((car-less-than-car b a) (throw 'exit nil))
+               (t (setq a (cdr a) b (cdr b)))))
+       ;; If A is empty, either keys are equal (B is also empty) and
+       ;; we return nil, or A is lesser than B (B is longer) and we
+       ;; return a non-nil value.
+       ;;
+       ;; If A is not empty, B is necessarily empty and A is greater
+       ;; than B (A is longer).  Therefore, return nil.
+       (and (null a) b)))))
+
+(defun org-element--cache-compare (a b)
+  "Non-nil when element A is located before element B."
+  (org-element--cache-key-less-p (org-element--cache-key a)
+                                (org-element--cache-key b)))
+
+(defsubst org-element--cache-root ()
+  "Return root value in cache.
+This function assumes `org-element--cache' is a valid AVL tree."
+  (avl-tree--node-left (avl-tree--dummyroot org-element--cache)))
+
+
+;;;; Tools
+
+(defsubst org-element--cache-active-p ()
+  "Non-nil when cache is active in current buffer."
+  (and org-element-use-cache
+       org-element--cache
+       (derived-mode-p 'org-mode)))
+
+(defun org-element--cache-find (pos &optional side)
+  "Find element in cache starting at POS or before.
+
+POS refers to a buffer position.
+
+When optional argument SIDE is non-nil, the function checks for
+elements starting at or past POS instead.  If SIDE is `both', the
+function returns a cons cell where car is the first element
+starting at or before POS and cdr the first element starting
+after POS.
+
+The function can only find elements in the synchronized part of
+the cache."
+  (let ((limit (and org-element--cache-sync-requests
+                   (aref (car org-element--cache-sync-requests) 0)))
+       (node (org-element--cache-root))
+       lower upper)
+    (while node
+      (let* ((element (avl-tree--node-data node))
+            (begin (org-element-property :begin element)))
+       (cond
+        ((and limit
+              (not (org-element--cache-key-less-p
+                    (org-element--cache-key element) limit)))
+         (setq node (avl-tree--node-left node)))
+        ((> begin pos)
+         (setq upper element
+               node (avl-tree--node-left node)))
+        ((< begin pos)
+         (setq lower element
+               node (avl-tree--node-right node)))
+        ;; We found an element in cache starting at POS.  If `side'
+        ;; is `both' we also want the next one in order to generate
+        ;; a key in-between.
+        ;;
+        ;; If the element is the first row or item in a table or
+        ;; a plain list, we always return the table or the plain
+        ;; list.
+        ;;
+        ;; In any other case, we return the element found.
+        ((eq side 'both)
+         (setq lower element)
+         (setq node (avl-tree--node-right node)))
+        ((and (memq (org-element-type element) '(item table-row))
+              (let ((parent (org-element-property :parent element)))
+                (and (= (org-element-property :begin element)
+                        (org-element-property :contents-begin parent))
+                     (setq node nil
+                           lower parent
+                           upper parent)))))
+        (t
+         (setq node nil
+               lower element
+               upper element)))))
+    (pcase side
+      (`both (cons lower upper))
+      (`nil lower)
+      (_ upper))))
+
+(defun org-element--cache-put (element &optional data)
+  "Store ELEMENT in current buffer's cache, if allowed.
+When optional argument DATA is non-nil, assume is it object data
+relative to ELEMENT and store it in the objects cache."
+  (cond ((not (org-element--cache-active-p)) nil)
+       ((not data)
+        (when org-element--cache-sync-requests
+          ;; During synchronization, first build an appropriate key
+          ;; for the new element so `avl-tree-enter' can insert it at
+          ;; the right spot in the cache.
+          (let ((keys (org-element--cache-find
+                       (org-element-property :begin element) 'both)))
+            (puthash element
+                     (org-element--cache-generate-key
+                      (and (car keys) (org-element--cache-key (car keys)))
+                      (cond ((cdr keys) (org-element--cache-key (cdr keys)))
+                            (org-element--cache-sync-requests
+                             (aref (car org-element--cache-sync-requests) 0))))
+                     org-element--cache-sync-keys)))
+        (avl-tree-enter org-element--cache element))
+       ;; Headlines are not stored in cache, so objects in titles are
+       ;; not stored either.
+       ((eq (org-element-type element) 'headline) nil)
+       (t (puthash element data org-element--cache-objects))))
+
+(defsubst org-element--cache-remove (element)
+  "Remove ELEMENT from cache.
+Assume ELEMENT belongs to cache and that a cache is active."
+  (avl-tree-delete org-element--cache element)
+  (remhash element org-element--cache-objects))
+
+
+;;;; Synchronization
+
+(defsubst org-element--cache-set-timer (buffer)
+  "Set idle timer for cache synchronization in BUFFER."
+  (when org-element--cache-sync-timer
+    (cancel-timer org-element--cache-sync-timer))
+  (setq org-element--cache-sync-timer
+       (run-with-idle-timer
+        (let ((idle (current-idle-time)))
+          (if idle (time-add idle org-element-cache-sync-break)
+            org-element-cache-sync-idle-time))
+        nil
+        #'org-element--cache-sync
+        buffer)))
+
+(defsubst org-element--cache-interrupt-p (time-limit)
+  "Non-nil when synchronization process should be interrupted.
+TIME-LIMIT is a time value or nil."
+  (and time-limit
+       (or (input-pending-p)
+          (time-less-p time-limit (current-time)))))
+
+(defsubst org-element--cache-shift-positions (element offset &optional props)
+  "Shift ELEMENT properties relative to buffer positions by OFFSET.
+
+Properties containing buffer positions are `:begin', `:end',
+`:contents-begin', `:contents-end' and `:structure'.  When
+optional argument PROPS is a list of keywords, only shift
+properties provided in that list.
+
+Properties are modified by side-effect."
+  (let ((properties (nth 1 element)))
+    ;; Shift `:structure' property for the first plain list only: it
+    ;; is the only one that really matters and it prevents from
+    ;; shifting it more than once.
+    (when (and (or (not props) (memq :structure props))
+              (eq (org-element-type element) 'plain-list)
+              (not (eq (org-element-type (plist-get properties :parent))
+                       'item)))
+      (dolist (item (plist-get properties :structure))
+       (cl-incf (car item) offset)
+       (cl-incf (nth 6 item) offset)))
+    (dolist (key '(:begin :contents-begin :contents-end :end :post-affiliated))
+      (let ((value (and (or (not props) (memq key props))
+                       (plist-get properties key))))
+       (and value (plist-put properties key (+ offset value)))))))
+
+(defun org-element--cache-sync (buffer &optional threshold future-change)
+  "Synchronize cache with recent modification in BUFFER.
+
+When optional argument THRESHOLD is non-nil, do the
+synchronization for all elements starting before or at threshold,
+then exit.  Otherwise, synchronize cache for as long as
+`org-element-cache-sync-duration' or until Emacs leaves idle
+state.
+
+FUTURE-CHANGE, when non-nil, is a buffer position where changes
+not registered yet in the cache are going to happen.  It is used
+in `org-element--cache-submit-request', where cache is partially
+updated before current modification are actually submitted."
+  (when (buffer-live-p buffer)
+    (with-current-buffer buffer
+      (let ((inhibit-quit t) request next)
+       (when org-element--cache-sync-timer
+         (cancel-timer org-element--cache-sync-timer))
+       (catch 'interrupt
+         (while org-element--cache-sync-requests
+           (setq request (car org-element--cache-sync-requests)
+                 next (nth 1 org-element--cache-sync-requests))
+           (org-element--cache-process-request
+            request
+            (and next (aref next 0))
+            threshold
+            (and (not threshold)
+                 (time-add (current-time)
+                           org-element-cache-sync-duration))
+            future-change)
+           ;; Request processed.  Merge current and next offsets and
+           ;; transfer ending position.
+           (when next
+             (cl-incf (aref next 3) (aref request 3))
+             (aset next 2 (aref request 2)))
+           (setq org-element--cache-sync-requests
+                 (cdr org-element--cache-sync-requests))))
+       ;; If more requests are awaiting, set idle timer accordingly.
+       ;; Otherwise, reset keys.
+       (if org-element--cache-sync-requests
+           (org-element--cache-set-timer buffer)
+         (clrhash org-element--cache-sync-keys))))))
+
+(defun org-element--cache-process-request
+    (request next threshold time-limit future-change)
+  "Process synchronization REQUEST for all entries before NEXT.
+
+REQUEST is a vector, built by `org-element--cache-submit-request'.
+
+NEXT is a cache key, as returned by `org-element--cache-key'.
+
+When non-nil, THRESHOLD is a buffer position.  Synchronization
+stops as soon as a shifted element begins after it.
+
+When non-nil, TIME-LIMIT is a time value.  Synchronization stops
+after this time or when Emacs exits idle state.
+
+When non-nil, FUTURE-CHANGE is a buffer position where changes
+not registered yet in the cache are going to happen.  See
+`org-element--cache-submit-request' for more information.
+
+Throw `interrupt' if the process stops before completing the
+request."
+  (catch 'quit
+    (when (= (aref request 5) 0)
+      ;; Phase 0.
+      ;;
+      ;; Delete all elements starting after BEG, but not after buffer
+      ;; position END or past element with key NEXT.  Also delete
+      ;; elements contained within a previously removed element
+      ;; (stored in `last-container').
+      ;;
+      ;; At each iteration, we start again at tree root since
+      ;; a deletion modifies structure of the balanced tree.
+      (catch 'end-phase
+        (while t
+         (when (org-element--cache-interrupt-p time-limit)
+           (throw 'interrupt nil))
+         ;; Find first element in cache with key BEG or after it.
+         (let ((beg (aref request 0))
+               (end (aref request 2))
+               (node (org-element--cache-root))
+               data data-key last-container)
+           (while node
+             (let* ((element (avl-tree--node-data node))
+                    (key (org-element--cache-key element)))
+               (cond
+                ((org-element--cache-key-less-p key beg)
+                 (setq node (avl-tree--node-right node)))
+                ((org-element--cache-key-less-p beg key)
+                 (setq data element
+                       data-key key
+                       node (avl-tree--node-left node)))
+                (t (setq data element
+                         data-key key
+                         node nil)))))
+           (if data
+               (let ((pos (org-element-property :begin data)))
+                 (if (if (or (not next)
+                             (org-element--cache-key-less-p data-key next))
+                         (<= pos end)
+                       (and last-container
+                            (let ((up data))
+                              (while (and up (not (eq up last-container)))
+                                (setq up (org-element-property :parent up)))
+                              up)))
+                     (progn (when (and (not last-container)
+                                       (> (org-element-property :end data)
+                                          end))
+                              (setq last-container data))
+                            (org-element--cache-remove data))
+                   (aset request 0 data-key)
+                   (aset request 1 pos)
+                   (aset request 5 1)
+                   (throw 'end-phase nil)))
+             ;; No element starting after modifications left in
+             ;; cache: further processing is futile.
+             (throw 'quit t))))))
+    (when (= (aref request 5) 1)
+      ;; Phase 1.
+      ;;
+      ;; Phase 0 left a hole in the cache.  Some elements after it
+      ;; could have parents within.  For example, in the following
+      ;; buffer:
+      ;;
+      ;;   - item
+      ;;
+      ;;
+      ;;     Paragraph1
+      ;;
+      ;;     Paragraph2
+      ;;
+      ;; if we remove a blank line between "item" and "Paragraph1",
+      ;; everything down to "Paragraph2" is removed from cache.  But
+      ;; the paragraph now belongs to the list, and its `:parent'
+      ;; property no longer is accurate.
+      ;;
+      ;; Therefore we need to parse again elements in the hole, or at
+      ;; least in its last section, so that we can re-parent
+      ;; subsequent elements, during phase 2.
+      ;;
+      ;; Note that we only need to get the parent from the first
+      ;; element in cache after the hole.
+      ;;
+      ;; When next key is lesser or equal to the current one, delegate
+      ;; phase 1 processing to next request in order to preserve key
+      ;; order among requests.
+      (let ((key (aref request 0)))
+       (when (and next (not (org-element--cache-key-less-p key next)))
+         (let ((next-request (nth 1 org-element--cache-sync-requests)))
+           (aset next-request 0 key)
+           (aset next-request 1 (aref request 1))
+           (aset next-request 5 1))
+         (throw 'quit t)))
+      ;; Next element will start at its beginning position plus
+      ;; offset, since it hasn't been shifted yet.  Therefore, LIMIT
+      ;; contains the real beginning position of the first element to
+      ;; shift and re-parent.
+      (let ((limit (+ (aref request 1) (aref request 3))))
+       (cond ((and threshold (> limit threshold)) (throw 'interrupt nil))
+             ((and future-change (>= limit future-change))
+              ;; Changes are going to happen around this element and
+              ;; they will trigger another phase 1 request.  Skip the
+              ;; current one.
+              (aset request 5 2))
+             (t
+              (let ((parent (org-element--parse-to limit t time-limit)))
+                (aset request 4 parent)
+                (aset request 5 2))))))
+    ;; Phase 2.
+    ;;
+    ;; Shift all elements starting from key START, but before NEXT, by
+    ;; OFFSET, and re-parent them when appropriate.
+    ;;
+    ;; Elements are modified by side-effect so the tree structure
+    ;; remains intact.
+    ;;
+    ;; Once THRESHOLD, if any, is reached, or once there is an input
+    ;; pending, exit.  Before leaving, the current synchronization
+    ;; request is updated.
+    (let ((start (aref request 0))
+         (offset (aref request 3))
+         (parent (aref request 4))
+         (node (org-element--cache-root))
+         (stack (list nil))
+         (leftp t)
+         exit-flag)
+      ;; No re-parenting nor shifting planned: request is over.
+      (when (and (not parent) (zerop offset)) (throw 'quit t))
+      (while node
+       (let* ((data (avl-tree--node-data node))
+              (key (org-element--cache-key data)))
+         (if (and leftp (avl-tree--node-left node)
+                  (not (org-element--cache-key-less-p key start)))
+             (progn (push node stack)
+                    (setq node (avl-tree--node-left node)))
+           (unless (org-element--cache-key-less-p key start)
+             ;; We reached NEXT.  Request is complete.
+             (when (equal key next) (throw 'quit t))
+             ;; Handle interruption request.  Update current request.
+             (when (or exit-flag (org-element--cache-interrupt-p time-limit))
+               (aset request 0 key)
+               (aset request 4 parent)
+               (throw 'interrupt nil))
+             ;; Shift element.
+             (unless (zerop offset)
+               (org-element--cache-shift-positions data offset)
+               ;; Shift associated objects data, if any.
+               (dolist (object-data (gethash data org-element--cache-objects))
+                 (dolist (object (cddr object-data))
+                   (org-element--cache-shift-positions object offset))))
+             (let ((begin (org-element-property :begin data)))
+               ;; Update PARENT and re-parent DATA, only when
+               ;; necessary.  Propagate new structures for lists.
+               (while (and parent
+                           (<= (org-element-property :end parent) begin))
+                 (setq parent (org-element-property :parent parent)))
+               (cond ((and (not parent) (zerop offset)) (throw 'quit nil))
+                     ((and parent
+                           (let ((p (org-element-property :parent data)))
+                             (or (not p)
+                                 (< (org-element-property :begin p)
+                                    (org-element-property :begin parent)))))
+                      (org-element-put-property data :parent parent)
+                      (let ((s (org-element-property :structure parent)))
+                        (when (and s (org-element-property :structure data))
+                          (org-element-put-property data :structure s)))))
+               ;; Cache is up-to-date past THRESHOLD.  Request
+               ;; interruption.
+               (when (and threshold (> begin threshold)) (setq exit-flag t))))
+           (setq node (if (setq leftp (avl-tree--node-right node))
+                          (avl-tree--node-right node)
+                        (pop stack))))))
+      ;; We reached end of tree: synchronization complete.
+      t)))
+
+(defun org-element--parse-to (pos &optional syncp time-limit)
+  "Parse elements in current section, down to POS.
+
+Start parsing from the closest between the last known element in
+cache or headline above.  Return the smallest element containing
+POS.
+
+When optional argument SYNCP is non-nil, return the parent of the
+element containing POS instead.  In that case, it is also
+possible to provide TIME-LIMIT, which is a time value specifying
+when the parsing should stop.  The function throws `interrupt' if
+the process stopped before finding the expected result."
+  (catch 'exit
+    (org-with-wide-buffer
+     (goto-char pos)
+     (let* ((cached (and (org-element--cache-active-p)
+                        (org-element--cache-find pos nil)))
+            (begin (org-element-property :begin cached))
+            element next mode)
+       (cond
+        ;; Nothing in cache before point: start parsing from first
+        ;; element following headline above, or first element in
+        ;; buffer.
+        ((not cached)
+         (when (org-with-limited-levels (outline-previous-heading))
+           (setq mode 'planning)
+          (forward-line))
+         (skip-chars-forward " \r\t\n")
+         (beginning-of-line))
+        ;; Cache returned exact match: return it.
+        ((= pos begin)
+        (throw 'exit (if syncp (org-element-property :parent cached) cached)))
+        ;; There's a headline between cached value and POS: cached
+        ;; value is invalid.  Start parsing from first element
+        ;; following the headline.
+        ((re-search-backward
+          (org-with-limited-levels org-outline-regexp-bol) begin t)
+         (forward-line)
+         (skip-chars-forward " \r\t\n")
+         (beginning-of-line)
+        (setq mode 'planning))
+        ;; Check if CACHED or any of its ancestors contain point.
+        ;;
+        ;; If there is such an element, we inspect it in order to know
+        ;; if we return it or if we need to parse its contents.
+        ;; Otherwise, we just start parsing from current location,
+        ;; which is right after the top-most element containing
+        ;; CACHED.
+        ;;
+        ;; As a special case, if POS is at the end of the buffer, we
+        ;; want to return the innermost element ending there.
+        ;;
+        ;; Also, if we find an ancestor and discover that we need to
+        ;; parse its contents, make sure we don't start from
+        ;; `:contents-begin', as we would otherwise go past CACHED
+        ;; again.  Instead, in that situation, we will resume parsing
+        ;; from NEXT, which is located after CACHED or its higher
+        ;; ancestor not containing point.
+        (t
+         (let ((up cached)
+               (pos (if (= (point-max) pos) (1- pos) pos)))
+           (goto-char (or (org-element-property :contents-begin cached) begin))
+           (while (let ((end (org-element-property :end up)))
+                    (and (<= end pos)
+                         (goto-char end)
+                         (setq up (org-element-property :parent up)))))
+           (cond ((not up))
+                 ((eobp) (setq element up))
+                 (t (setq element up next (point)))))))
+       ;; Parse successively each element until we reach POS.
+       (let ((end (or (org-element-property :end element)
+                     (save-excursion
+                       (org-with-limited-levels (outline-next-heading))
+                       (point))))
+            (parent element))
+        (while t
+          (when syncp
+            (cond ((= (point) pos) (throw 'exit parent))
+                  ((org-element--cache-interrupt-p time-limit)
+                   (throw 'interrupt nil))))
+          (unless element
+            (setq element (org-element--current-element
+                           end 'element mode
+                           (org-element-property :structure parent)))
+            (org-element-put-property element :parent parent)
+            (org-element--cache-put element))
+          (let ((elem-end (org-element-property :end element))
+                (type (org-element-type element)))
+            (cond
+             ;; Skip any element ending before point.  Also skip
+             ;; element ending at point (unless it is also the end of
+             ;; buffer) since we're sure that another element begins
+             ;; after it.
+             ((and (<= elem-end pos) (/= (point-max) elem-end))
+              (goto-char elem-end)
+              (setq mode (org-element--next-mode type nil)))
+             ;; A non-greater element contains point: return it.
+             ((not (memq type org-element-greater-elements))
+              (throw 'exit element))
+             ;; Otherwise, we have to decide if ELEMENT really
+             ;; contains POS.  In that case we start parsing from
+             ;; contents' beginning.
+             ;;
+             ;; If POS is at contents' beginning but it is also at
+             ;; the beginning of the first item in a list or a table.
+             ;; In that case, we need to create an anchor for that
+             ;; list or table, so return it.
+             ;;
+             ;; Also, if POS is at the end of the buffer, no element
+             ;; can start after it, but more than one may end there.
+             ;; Arbitrarily, we choose to return the innermost of
+             ;; such elements.
+             ((let ((cbeg (org-element-property :contents-begin element))
+                    (cend (org-element-property :contents-end element)))
+                (when (or syncp
+                          (and cbeg cend
+                               (or (< cbeg pos)
+                                   (and (= cbeg pos)
+                                        (not (memq type '(plain-list table)))))
+                               (or (> cend pos)
+                                   (and (= cend pos) (= (point-max) pos)))))
+                  (goto-char (or next cbeg))
+                  (setq next nil
+                        mode (org-element--next-mode type t)
+                        parent element
+                        end cend))))
+             ;; Otherwise, return ELEMENT as it is the smallest
+             ;; element containing POS.
+             (t (throw 'exit element))))
+          (setq element nil)))))))
+
+
+;;;; Staging Buffer Changes
+
+(defconst org-element--cache-sensitive-re
+  (concat
+   org-outline-regexp-bol "\\|"
+   "\\\\end{[A-Za-z0-9*]+}[ \t]*$" "\\|"
+   "^[ \t]*\\(?:"
+   "#\\+\\(?:BEGIN[:_]\\|END\\(?:_\\|:?[ \t]*$\\)\\)" "\\|"
+   "\\\\begin{[A-Za-z0-9*]+}" "\\|"
+   ":\\(?:\\w\\|[-_]\\)+:[ \t]*$"
+   "\\)")
+  "Regexp matching a sensitive line, structure wise.
+A sensitive line is a headline, inlinetask, block, drawer, or
+latex-environment boundary.  When such a line is modified,
+structure changes in the document may propagate in the whole
+section, possibly making cache invalid.")
+
+(defvar org-element--cache-change-warning nil
+  "Non-nil when a sensitive line is about to be changed.
+It is a symbol among nil, t and `headline'.")
+
+(defun org-element--cache-before-change (beg end)
+  "Request extension of area going to be modified if needed.
+BEG and END are the beginning and end of the range of changed
+text.  See `before-change-functions' for more information."
+  (when (org-element--cache-active-p)
+    (org-with-wide-buffer
+     (goto-char beg)
+     (beginning-of-line)
+     (let ((bottom (save-excursion (goto-char end) (line-end-position))))
+       (setq org-element--cache-change-warning
+            (save-match-data
+              (if (and (org-with-limited-levels (org-at-heading-p))
+                       (= (line-end-position) bottom))
+                  'headline
+                (let ((case-fold-search t))
+                  (re-search-forward
+                   org-element--cache-sensitive-re bottom t)))))))))
+
+(defun org-element--cache-after-change (beg end pre)
+  "Update buffer modifications for current buffer.
+BEG and END are the beginning and end of the range of changed
+text, and the length in bytes of the pre-change text replaced by
+that range.  See `after-change-functions' for more information."
+  (when (org-element--cache-active-p)
+    (org-with-wide-buffer
+     (goto-char beg)
+     (beginning-of-line)
+     (save-match-data
+       (let ((top (point))
+            (bottom (save-excursion (goto-char end) (line-end-position))))
+        ;; Determine if modified area needs to be extended, according
+        ;; to both previous and current state.  We make a special
+        ;; case for headline editing: if a headline is modified but
+        ;; not removed, do not extend.
+        (when (pcase org-element--cache-change-warning
+                (`t t)
+                (`headline
+                 (not (and (org-with-limited-levels (org-at-heading-p))
+                           (= (line-end-position) bottom))))
+                (_
+                 (let ((case-fold-search t))
+                   (re-search-forward
+                    org-element--cache-sensitive-re bottom t))))
+          ;; Effectively extend modified area.
+          (org-with-limited-levels
+           (setq top (progn (goto-char top)
+                            (when (outline-previous-heading) (forward-line))
+                            (point)))
+           (setq bottom (progn (goto-char bottom)
+                               (if (outline-next-heading) (1- (point))
+                                 (point))))))
+        ;; Store synchronization request.
+        (let ((offset (- end beg pre)))
+          (org-element--cache-submit-request top (- bottom offset) offset)))))
+    ;; Activate a timer to process the request during idle time.
+    (org-element--cache-set-timer (current-buffer))))
+
+(defun org-element--cache-for-removal (beg end offset)
+  "Return first element to remove from cache.
+
+BEG and END are buffer positions delimiting buffer modifications.
+OFFSET is the size of the changes.
+
+Returned element is usually the first element in cache containing
+any position between BEG and END.  As an exception, greater
+elements around the changes that are robust to contents
+modifications are preserved and updated according to the
+changes."
+  (let* ((elements (org-element--cache-find (1- beg) 'both))
+        (before (car elements))
+        (after (cdr elements)))
+    (if (not before) after
+      (let ((up before)
+           (robust-flag t))
+       (while up
+         (if (let ((type (org-element-type up)))
+               (and (or (memq type '(center-block dynamic-block quote-block
+                                                  special-block))
+                        ;; Drawers named "PROPERTIES" are probably
+                        ;; a properties drawer being edited.  Force
+                        ;; parsing to check if editing is over.
+                        (and (eq type 'drawer)
+                             (not (string=
+                                   (org-element-property :drawer-name up)
+                                   "PROPERTIES"))))
+                    (let ((cbeg (org-element-property :contents-begin up)))
+                      (and cbeg
+                           (<= cbeg beg)
+                           (> (org-element-property :contents-end up) end)))))
+             ;; UP is a robust greater element containing changes.
+             ;; We only need to extend its ending boundaries.
+             (org-element--cache-shift-positions
+              up offset '(:contents-end :end))
+           (setq before up)
+           (when robust-flag (setq robust-flag nil)))
+         (setq up (org-element-property :parent up)))
+       ;; We're at top level element containing ELEMENT: if it's
+       ;; altered by buffer modifications, it is first element in
+       ;; cache to be removed.  Otherwise, that first element is the
+       ;; following one.
+       ;;
+       ;; As a special case, do not remove BEFORE if it is a robust
+       ;; container for current changes.
+       (if (or (< (org-element-property :end before) beg) robust-flag) after
+         before)))))
+
+(defun org-element--cache-submit-request (beg end offset)
+  "Submit a new cache synchronization request for current buffer.
+BEG and END are buffer positions delimiting the minimal area
+where cache data should be removed.  OFFSET is the size of the
+change, as an integer."
+  (let ((next (car org-element--cache-sync-requests))
+       delete-to delete-from)
+    (if (and next
+            (zerop (aref next 5))
+            (> (setq delete-to (+ (aref next 2) (aref next 3))) end)
+            (<= (setq delete-from (aref next 1)) end))
+       ;; Current changes can be merged with first sync request: we
+       ;; can save a partial cache synchronization.
+       (progn
+         (cl-incf (aref next 3) offset)
+         ;; If last change happened within area to be removed, extend
+         ;; boundaries of robust parents, if any.  Otherwise, find
+         ;; first element to remove and update request accordingly.
+         (if (> beg delete-from)
+             (let ((up (aref next 4)))
+               (while up
+                 (org-element--cache-shift-positions
+                  up offset '(:contents-end :end))
+                 (setq up (org-element-property :parent up))))
+           (let ((first (org-element--cache-for-removal beg delete-to offset)))
+             (when first
+               (aset next 0 (org-element--cache-key first))
+               (aset next 1 (org-element-property :begin first))
+               (aset next 4 (org-element-property :parent first))))))
+      ;; Ensure cache is correct up to END.  Also make sure that NEXT,
+      ;; if any, is no longer a 0-phase request, thus ensuring that
+      ;; phases are properly ordered.  We need to provide OFFSET as
+      ;; optional parameter since current modifications are not known
+      ;; yet to the otherwise correct part of the cache (i.e, before
+      ;; the first request).
+      (when next (org-element--cache-sync (current-buffer) end beg))
+      (let ((first (org-element--cache-for-removal beg end offset)))
+       (if first
+           (push (let ((beg (org-element-property :begin first))
+                       (key (org-element--cache-key first)))
+                   (cond
+                    ;; When changes happen before the first known
+                    ;; element, re-parent and shift the rest of the
+                    ;; cache.
+                    ((> beg end) (vector key beg nil offset nil 1))
+                    ;; Otherwise, we find the first non robust
+                    ;; element containing END.  All elements between
+                    ;; FIRST and this one are to be removed.
+                    ((let ((first-end (org-element-property :end first)))
+                       (and (> first-end end)
+                            (vector key beg first-end offset first 0))))
+                    (t
+                     (let* ((element (org-element--cache-find end))
+                            (end (org-element-property :end element))
+                            (up element))
+                       (while (and (setq up (org-element-property :parent up))
+                                   (>= (org-element-property :begin up) beg))
+                         (setq end (org-element-property :end up)
+                               element up))
+                       (vector key beg end offset element 0)))))
+                 org-element--cache-sync-requests)
+         ;; No element to remove.  No need to re-parent either.
+         ;; Simply shift additional elements, if any, by OFFSET.
+         (when org-element--cache-sync-requests
+           (cl-incf (aref (car org-element--cache-sync-requests) 3)
+                    offset)))))))
+
+
+;;;; Public Functions
+
+;;;###autoload
+(defun org-element-cache-reset (&optional all)
+  "Reset cache in current buffer.
+When optional argument ALL is non-nil, reset cache in all Org
+buffers."
+  (interactive "P")
+  (dolist (buffer (if all (buffer-list) (list (current-buffer))))
+    (with-current-buffer buffer
+      (when (and org-element-use-cache (derived-mode-p 'org-mode))
+       (setq-local org-element--cache
+                   (avl-tree-create #'org-element--cache-compare))
+       (setq-local org-element--cache-objects (make-hash-table :test #'eq))
+       (setq-local org-element--cache-sync-keys
+                   (make-hash-table :weakness 'key :test #'eq))
+       (setq-local org-element--cache-change-warning nil)
+       (setq-local org-element--cache-sync-requests nil)
+       (setq-local org-element--cache-sync-timer nil)
+       (add-hook 'before-change-functions
+                 #'org-element--cache-before-change nil t)
+       (add-hook 'after-change-functions
+                 #'org-element--cache-after-change nil t)))))
+
+;;;###autoload
+(defun org-element-cache-refresh (pos)
+  "Refresh cache at position POS."
+  (when (org-element--cache-active-p)
+    (org-element--cache-sync (current-buffer) pos)
+    (org-element--cache-submit-request pos pos 0)
+    (org-element--cache-set-timer (current-buffer))))
 
 
 
@@ -4678,7 +5733,7 @@ indentation is not done with TAB characters."
 ;; The first move is to implement a way to obtain the smallest element
 ;; containing point.  This is the job of `org-element-at-point'.  It
 ;; basically jumps back to the beginning of section containing point
-;; and moves, element after element, with
+;; and proceed, one element after the other, with
 ;; `org-element--current-element' until the container is found.  Note:
 ;; When using `org-element-at-point', secondary values are never
 ;; parsed since the function focuses on elements, not on objects.
@@ -4689,8 +5744,9 @@ indentation is not done with TAB characters."
 ;; `org-element-nested-p' and `org-element-swap-A-B' may be used
 ;; internally by navigation and manipulation tools.
 
+
 ;;;###autoload
-(defun org-element-at-point (&optional keep-trail)
+(defun org-element-at-point ()
   "Determine closest element around point.
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
@@ -4701,118 +5757,36 @@ Possible types are defined in 
`org-element-all-elements'.
 Properties depend on element or object type, but always include
 `:begin', `:end', `:parent' and `:post-blank' properties.
 
-As a special case, if point is at the very beginning of a list or
-sub-list, returned element will be that list instead of the first
-item.  In the same way, if point is at the beginning of the first
-row of a table, returned element will be the table instead of the
-first row.
-
-If optional argument KEEP-TRAIL is non-nil, the function returns
-a list of elements leading to element at point.  The list's CAR
-is always the element at point.  The following positions contain
-element's siblings, then parents, siblings of parents, until the
-first element of current section."
+As a special case, if point is at the very beginning of the first
+item in a list or sub-list, returned element will be that list
+instead of the item.  Likewise, if point is at the beginning of
+the first row of a table, returned element will be the table
+instead of the first row.
+
+When point is at the end of the buffer, return the innermost
+element ending there."
   (org-with-wide-buffer
-   ;; If at a headline, parse it.  It is the sole element that
-   ;; doesn't require to know about context.  Be sure to disallow
-   ;; secondary string parsing, though.
-   (if (org-with-limited-levels (org-at-heading-p))
-       (progn
-        (beginning-of-line)
-        (if (not keep-trail) (org-element-headline-parser (point-max) t)
-          (list (org-element-headline-parser (point-max) t))))
-     ;; Otherwise move at the beginning of the section containing
-     ;; point.
-     (catch 'exit
-       (let ((origin (point))
-            (end (save-excursion
-                   (org-with-limited-levels (outline-next-heading)) (point)))
-            element type special-flag trail struct prevs parent)
-        (org-with-limited-levels
-         (if (org-before-first-heading-p)
-             ;; In empty lines at buffer's beginning, return nil.
-             (progn (goto-char (point-min))
-                    (org-skip-whitespace)
-                    (when (or (eobp) (> (line-beginning-position) origin))
-                      (throw 'exit nil)))
-           (org-back-to-heading)
-           (forward-line)
-           (org-skip-whitespace)
-           (when (or (eobp) (> (line-beginning-position) origin))
-             ;; In blank lines just after the headline, point still
-             ;; belongs to the headline.
-             (throw 'exit
-                    (progn (skip-chars-backward " \r\t\n")
-                           (beginning-of-line)
-                           (if (not keep-trail)
-                               (org-element-headline-parser (point-max) t)
-                             (list (org-element-headline-parser
-                                    (point-max) t))))))))
-        (beginning-of-line)
-        ;; Parse successively each element, skipping those ending
-        ;; before original position.
-        (while t
-          (setq element
-                (org-element--current-element end 'element special-flag struct)
-                type (car element))
-          (org-element-put-property element :parent parent)
-          (when keep-trail (push element trail))
-          (cond
-           ;; 1. Skip any element ending before point.  Also skip
-           ;;    element ending at point when we're sure that another
-           ;;    element has started.
-           ((let ((elem-end (org-element-property :end element)))
-              (when (or (< elem-end origin)
-                        (and (= elem-end origin) (/= elem-end end)))
-                (goto-char elem-end))))
-           ;; 2. An element containing point is always the element at
-           ;;    point.
-           ((not (memq type org-element-greater-elements))
-            (throw 'exit (if keep-trail trail element)))
-           ;; 3. At any other greater element type, if point is
-           ;;    within contents, move into it.
-           (t
-            (let ((cbeg (org-element-property :contents-begin element))
-                  (cend (org-element-property :contents-end element)))
-              (if (or (not cbeg) (not cend) (> cbeg origin) (< cend origin)
-                      ;; Create an anchor for tables and plain lists:
-                      ;; when point is at the very beginning of these
-                      ;; elements, ignoring affiliated keywords,
-                      ;; target them instead of their contents.
-                      (and (= cbeg origin) (memq type '(plain-list table)))
-                      ;; When point is at contents end, do not move
-                      ;; into elements with an explicit ending, but
-                      ;; return that element instead.
-                      (and (= cend origin)
-                           (or (memq type
-                                     '(center-block
-                                       drawer dynamic-block inlinetask
-                                       property-drawer quote-block
-                                       special-block))
-                               ;; Corner case: if a list ends at the
-                               ;; end of a buffer without a final new
-                               ;; line, return last element in last
-                               ;; item instead.
-                               (and (memq type '(item plain-list))
-                                    (progn (goto-char cend)
-                                           (or (bolp) (not (eobp))))))))
-                  (throw 'exit (if keep-trail trail element))
-                (setq parent element)
-                (case type
-                  (plain-list
-                   (setq special-flag 'item
-                         struct (org-element-property :structure element)))
-                  (item (setq special-flag nil))
-                  (property-drawer
-                   (setq special-flag 'node-property struct nil))
-                  (table (setq special-flag 'table-row struct nil))
-                  (otherwise (setq special-flag nil struct nil)))
-                (setq end cend)
-                (goto-char cbeg)))))))))))
+   (let ((origin (point)))
+     (end-of-line)
+     (skip-chars-backward " \r\t\n")
+     (cond
+      ;; Within blank lines at the beginning of buffer, return nil.
+      ((bobp) nil)
+      ;; Within blank lines right after a headline, return that
+      ;; headline.
+      ((org-with-limited-levels (org-at-heading-p))
+       (beginning-of-line)
+       (org-element-headline-parser (point-max) t))
+      ;; Otherwise parse until we find element containing ORIGIN.
+      (t
+       (when (org-element--cache-active-p)
+        (if (not org-element--cache) (org-element-cache-reset)
+          (org-element--cache-sync (current-buffer) origin)))
+       (org-element--parse-to origin))))))
 
 ;;;###autoload
 (defun org-element-context (&optional element)
-  "Return closest element or object around point.
+  "Return smallest element or object around point.
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
 of the element or object and PROPS a plist of properties
@@ -4823,34 +5797,36 @@ Possible types are defined in 
`org-element-all-elements' and
 object type, but always include `:begin', `:end', `:parent' and
 `:post-blank'.
 
+As a special case, if point is right after an object and not at
+the beginning of any other object, return that object.
+
 Optional argument ELEMENT, when non-nil, is the closest element
 containing point, as returned by `org-element-at-point'.
 Providing it allows for quicker computation."
   (catch 'objects-forbidden
     (org-with-wide-buffer
-     (let* ((origin (point))
-            (element (or element (org-element-at-point)))
-            (type (org-element-type element))
-            context)
-       ;; Check if point is inside an element containing objects or at
-       ;; a secondary string.  In that case, narrow buffer to the
-       ;; containing area.  Otherwise, return ELEMENT.
+     (let* ((pos (point))
+           (element (or element (org-element-at-point)))
+           (type (org-element-type element))
+           (post (org-element-property :post-affiliated element)))
+       ;; If point is inside an element containing objects or
+       ;; a secondary string, narrow buffer to the container and
+       ;; proceed with parsing.  Otherwise, return ELEMENT.
        (cond
        ;; At a parsed affiliated keyword, check if we're inside main
        ;; or dual value.
-       ((let ((post (org-element-property :post-affiliated element)))
-          (and post (< origin post)))
+       ((and post (< pos post))
         (beginning-of-line)
         (let ((case-fold-search t)) (looking-at org-element--affiliated-re))
         (cond
          ((not (member-ignore-case (match-string 1)
                                    org-element-parsed-keywords))
           (throw 'objects-forbidden element))
-         ((< (match-end 0) origin)
+         ((< (match-end 0) pos)
           (narrow-to-region (match-end 0) (line-end-position)))
          ((and (match-beginning 2)
-               (>= origin (match-beginning 2))
-               (< origin (match-end 2)))
+               (>= pos (match-beginning 2))
+               (< pos (match-end 2)))
           (narrow-to-region (match-beginning 2) (match-end 2)))
          (t (throw 'objects-forbidden element)))
         ;; Also change type to retrieve correct restrictions.
@@ -4858,88 +5834,168 @@ Providing it allows for quicker computation."
        ;; At an item, objects can only be located within tag, if any.
        ((eq type 'item)
         (let ((tag (org-element-property :tag element)))
-          (if (not tag) (throw 'objects-forbidden element)
+          (if (or (not tag) (/= (line-beginning-position) post))
+              (throw 'objects-forbidden element)
             (beginning-of-line)
             (search-forward tag (line-end-position))
             (goto-char (match-beginning 0))
-            (if (and (>= origin (point)) (< origin (match-end 0)))
+            (if (and (>= pos (point)) (< pos (match-end 0)))
                 (narrow-to-region (point) (match-end 0))
               (throw 'objects-forbidden element)))))
-       ;; At an headline or inlinetask, objects are located within
-       ;; their title.
+       ;; At an headline or inlinetask, objects are in title.
        ((memq type '(headline inlinetask))
-        (goto-char (org-element-property :begin element))
-        (skip-chars-forward "*")
-        (if (and (> origin (point)) (< origin (line-end-position)))
-            (narrow-to-region (point) (line-end-position))
-          (throw 'objects-forbidden element)))
+        (let ((case-fold-search nil))
+          (goto-char (org-element-property :begin element))
+          (looking-at org-complex-heading-regexp)
+          (let ((end (match-end 4)))
+            (if (not end) (throw 'objects-forbidden element)
+              (goto-char (match-beginning 4))
+              (when (looking-at org-comment-string)
+                (goto-char (match-end 0)))
+              (if (>= (point) end) (throw 'objects-forbidden element)
+                (narrow-to-region (point) end))))))
        ;; At a paragraph, a table-row or a verse block, objects are
        ;; located within their contents.
        ((memq type '(paragraph table-row verse-block))
         (let ((cbeg (org-element-property :contents-begin element))
               (cend (org-element-property :contents-end element)))
           ;; CBEG is nil for table rules.
-          (if (and cbeg cend (>= origin cbeg) (< origin cend))
+          (if (and cbeg cend (>= pos cbeg)
+                   (or (< pos cend) (and (= pos cend) (eobp))))
               (narrow-to-region cbeg cend)
             (throw 'objects-forbidden element))))
-       ;; At a parsed keyword, objects are located within value.
-       ((eq type 'keyword)
-        (if (not (member (org-element-property :key element)
-                         org-element-document-properties))
-            (throw 'objects-forbidden element)
-          (beginning-of-line)
-          (search-forward ":")
-          (if (and (>= origin (point)) (< origin (line-end-position)))
-              (narrow-to-region (point) (line-end-position))
-            (throw 'objects-forbidden element))))
        ;; At a planning line, if point is at a timestamp, return it,
        ;; otherwise, return element.
        ((eq type 'planning)
         (dolist (p '(:closed :deadline :scheduled))
           (let ((timestamp (org-element-property p element)))
             (when (and timestamp
-                       (<= (org-element-property :begin timestamp) origin)
-                       (> (org-element-property :end timestamp) origin))
+                       (<= (org-element-property :begin timestamp) pos)
+                       (> (org-element-property :end timestamp) pos))
               (throw 'objects-forbidden timestamp))))
+        ;; All other locations cannot contain objects: bail out.
         (throw 'objects-forbidden element))
        (t (throw 'objects-forbidden element)))
        (goto-char (point-min))
        (let ((restriction (org-element-restriction type))
-             (parent element)
-             (candidates 'initial))
-         (catch 'exit
-           (while (setq candidates
-                       (org-element--get-next-object-candidates
-                        restriction candidates))
-             (let ((closest-cand (rassq (apply 'min (mapcar 'cdr candidates))
-                                        candidates)))
-               ;; If ORIGIN is before next object in element, there's
-               ;; no point in looking further.
-               (if (> (cdr closest-cand) origin) (throw 'exit parent)
-                 (let* ((object
-                         (progn (goto-char (cdr closest-cand))
-                                (funcall (intern (format 
"org-element-%s-parser"
-                                                         (car 
closest-cand))))))
-                        (cbeg (org-element-property :contents-begin object))
-                        (cend (org-element-property :contents-end object))
-                        (obj-end (org-element-property :end object)))
-                   (cond
-                    ;; ORIGIN is after OBJECT, so skip it.
-                    ((<= obj-end origin) (goto-char obj-end))
-                    ;; ORIGIN is within a non-recursive object or at
-                    ;; an object boundaries: Return that object.
-                    ((or (not cbeg) (< origin cbeg) (>= origin cend))
-                     (throw 'exit
-                            (org-element-put-property object :parent parent)))
-                    ;; Otherwise, move within current object and
-                    ;; restrict search to the end of its contents.
-                    (t (goto-char cbeg)
-                       (narrow-to-region (point) cend)
-                       (org-element-put-property object :parent parent)
-                       (setq parent object
-                             restriction (org-element-restriction object)
-                             candidates 'initial)))))))
-           parent))))))
+            (parent element)
+            (cache (cond ((not (org-element--cache-active-p)) nil)
+                         (org-element--cache-objects
+                          (gethash element org-element--cache-objects))
+                         (t (org-element-cache-reset) nil)))
+            next object-data last)
+        (prog1
+            (catch 'exit
+              (while t
+                ;; When entering PARENT for the first time, get list
+                ;; of objects within known so far.  Store it in
+                ;; OBJECT-DATA.
+                (unless next
+                  (let ((data (assq parent cache)))
+                    (if data (setq object-data data)
+                      (push (setq object-data (list parent nil)) cache))))
+                ;; Find NEXT object for analysis.
+                (catch 'found
+                  ;; If NEXT is non-nil, we already exhausted the
+                  ;; cache so we can parse buffer to find the object
+                  ;; after it.
+                  (if next (setq next (org-element--object-lex restriction))
+                    ;; Otherwise, check if cache can help us.
+                    (let ((objects (cddr object-data))
+                          (completep (nth 1 object-data)))
+                      (cond
+                       ((and (not objects) completep) (throw 'exit parent))
+                       ((not objects)
+                        (setq next (org-element--object-lex restriction)))
+                       (t
+                        (let ((cache-limit
+                               (org-element-property :end (car objects))))
+                          (if (>= cache-limit pos)
+                              ;; Cache contains the information needed.
+                              (dolist (object objects (throw 'exit parent))
+                                (when (<= (org-element-property :begin object)
+                                          pos)
+                                  (if (>= (org-element-property :end object)
+                                          pos)
+                                      (throw 'found (setq next object))
+                                    (throw 'exit parent))))
+                            (goto-char cache-limit)
+                            (setq next
+                                  (org-element--object-lex restriction))))))))
+                  ;; If we have a new object to analyze, store it in
+                  ;; cache.  Otherwise record that there is nothing
+                  ;; more to parse in this element at this depth.
+                  (if next
+                      (progn (org-element-put-property next :parent parent)
+                             (push next (cddr object-data)))
+                    (setcar (cdr object-data) t)))
+                ;; Process NEXT, if any, in order to know if we need
+                ;; to skip it, return it or move into it.
+                (if (or (not next) (> (org-element-property :begin next) pos))
+                    (throw 'exit (or last parent))
+                  (let ((end (org-element-property :end next))
+                        (cbeg (org-element-property :contents-begin next))
+                        (cend (org-element-property :contents-end next)))
+                    (cond
+                     ;; Skip objects ending before point.  Also skip
+                     ;; objects ending at point unless it is also the
+                     ;; end of buffer, since we want to return the
+                     ;; innermost object.
+                     ((and (<= end pos) (/= (point-max) end))
+                      (goto-char end)
+                      ;; For convenience, when object ends at POS,
+                      ;; without any space, store it in LAST, as we
+                      ;; will return it if no object starts here.
+                      (when (and (= end pos)
+                                 (not (memq (char-before) '(?\s ?\t))))
+                        (setq last next)))
+                     ;; If POS is within a container object, move
+                     ;; into that object.
+                     ((and cbeg cend
+                           (>= pos cbeg)
+                           (or (< pos cend)
+                               ;; At contents' end, if there is no
+                               ;; space before point, also move into
+                               ;; object, for consistency with
+                               ;; convenience feature above.
+                               (and (= pos cend)
+                                    (or (= (point-max) pos)
+                                        (not (memq (char-before pos)
+                                                   '(?\s ?\t)))))))
+                      (goto-char cbeg)
+                      (narrow-to-region (point) cend)
+                      (setq parent next
+                            restriction (org-element-restriction next)
+                            next nil
+                            object-data nil))
+                     ;; Otherwise, return NEXT.
+                     (t (throw 'exit next)))))))
+          ;; Store results in cache, if applicable.
+          (org-element--cache-put element cache)))))))
+
+(defun org-element-lineage (blob &optional types with-self)
+  "List all ancestors of a given element or object.
+
+BLOB is an object or element.
+
+When optional argument TYPES is a list of symbols, return the
+first element or object in the lineage whose type belongs to that
+list.
+
+When optional argument WITH-SELF is non-nil, lineage includes
+BLOB itself as the first element, and TYPES, if provided, also
+apply to it.
+
+When BLOB is obtained through `org-element-context' or
+`org-element-at-point', only ancestors from its section can be
+found.  There is no such limitation when BLOB belongs to a full
+parse tree."
+  (let ((up (if with-self blob (org-element-property :parent blob)))
+       ancestors)
+    (while (and up (not (memq (org-element-type up) types)))
+      (unless types (push up ancestors))
+      (setq up (org-element-property :parent up)))
+    (if types up (nreverse ancestors))))
 
 (defun org-element-nested-p (elem-A elem-B)
   "Non-nil when elements ELEM-A and ELEM-B are nested."
@@ -4982,39 +6038,44 @@ end of ELEM-A."
                    (goto-char (org-element-property :end elem-B))
                    (skip-chars-backward " \r\t\n")
                    (point-at-eol)))
-          ;; Store overlays responsible for visibility status.  We
-          ;; also need to store their boundaries as they will be
+          ;; Store inner overlays responsible for visibility status.
+          ;; We also need to store their boundaries as they will be
           ;; removed from buffer.
           (overlays
            (cons
-            (mapcar (lambda (ov) (list ov (overlay-start ov) (overlay-end ov)))
-                    (overlays-in beg-A end-A))
-            (mapcar (lambda (ov) (list ov (overlay-start ov) (overlay-end ov)))
-                    (overlays-in beg-B end-B))))
+            (delq nil
+                  (mapcar (lambda (o)
+                            (and (>= (overlay-start o) beg-A)
+                                 (<= (overlay-end o) end-A)
+                                 (list o (overlay-start o) (overlay-end o))))
+                          (overlays-in beg-A end-A)))
+            (delq nil
+                  (mapcar (lambda (o)
+                            (and (>= (overlay-start o) beg-B)
+                                 (<= (overlay-end o) end-B)
+                                 (list o (overlay-start o) (overlay-end o))))
+                          (overlays-in beg-B end-B)))))
           ;; Get contents.
           (body-A (buffer-substring beg-A end-A))
           (body-B (delete-and-extract-region beg-B end-B)))
       (goto-char beg-B)
       (when specialp
        (setq body-B (replace-regexp-in-string "\\`[ \t]*" "" body-B))
-       (org-indent-to-column ind-B))
+       (indent-to-column ind-B))
       (insert body-A)
       ;; Restore ex ELEM-A overlays.
       (let ((offset (- beg-B beg-A)))
-       (mapc (lambda (ov)
-               (move-overlay
-                (car ov) (+ (nth 1 ov) offset) (+ (nth 2 ov) offset)))
-             (car overlays))
+       (dolist (o (car overlays))
+         (move-overlay (car o) (+ (nth 1 o) offset) (+ (nth 2 o) offset)))
        (goto-char beg-A)
        (delete-region beg-A end-A)
        (insert body-B)
        ;; Restore ex ELEM-B overlays.
-       (mapc (lambda (ov)
-               (move-overlay
-                (car ov) (- (nth 1 ov) offset) (- (nth 2 ov) offset)))
-             (cdr overlays)))
+       (dolist (o (cdr overlays))
+         (move-overlay (car o) (- (nth 1 o) offset) (- (nth 2 o) offset))))
       (goto-char (org-element-property :end elem-B)))))
 
+
 (provide 'org-element)
 
 ;; Local variables:
diff --git a/lisp/org/org-entities.el b/lisp/org/org-entities.el
index 3ca2cce..05ccf0c 100644
--- a/lisp/org/org-entities.el
+++ b/lisp/org/org-entities.el
@@ -1,4 +1,4 @@
-;;; org-entities.el --- Support for special entities in Org-mode
+;;; org-entities.el --- Support for Special Entities -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -30,38 +30,36 @@
 (declare-function org-toggle-pretty-entities "org"       ())
 (declare-function org-table-align            "org-table" ())
 
-(eval-when-compile
-  (require 'cl))
-
 (defgroup org-entities nil
-  "Options concerning entities in Org-mode."
+  "Options concerning entities in Org mode."
   :tag "Org Entities"
   :group 'org)
 
-(defcustom org-entities-ascii-explanatory nil
-  "Non-nil means replace special entities in ASCII.
-For example, this will replace \"\\nsup\" with \"[not a superset of]\"
-in backends where the corresponding character is not available."
-  :group 'org-entities
-  :version "24.1"
-  :type 'boolean)
+(defun org-entities--user-safe-p (v)
+  "Non-nil if V is a safe value for `org-entities-user'."
+  (pcase v
+    (`nil t)
+    (`(,(and (pred stringp)
+            (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
+       ,(pred stringp) ,(pred booleanp) ,(pred stringp)
+       ,(pred stringp) ,(pred stringp) ,(pred stringp))
+     t)
+    (_ nil)))
 
 (defcustom org-entities-user nil
-  "User-defined entities used in Org-mode to produce special characters.
+  "User-defined entities used in Org to produce special characters.
 Each entry in this list is a list of strings.  It associates the name
 of the entity that can be inserted into an Org file as \\name with the
 appropriate replacements for the different export backends.  The order
 of the fields is the following
 
-name                 As a string, without the leading backslash
-LaTeX replacement    In ready LaTeX, no further processing will take place
-LaTeX mathp          A Boolean, either t or nil.  t if this entity needs
-                     to be in math mode.
+name                 As a string, without the leading backslash.
+LaTeX replacement    In ready LaTeX, no further processing will take place.
+LaTeX mathp          Either t or nil.  When t this entity needs to be in
+                     math mode.
 HTML replacement     In ready HTML, no further processing will take place.
                      Usually this will be an &...; entity.
-ASCII replacement    Plain ASCII, no extensions.  Symbols that cannot be
-                     represented will be left as they are, but see the.
-                     variable `org-entities-ascii-explanatory'.
+ASCII replacement    Plain ASCII, no extensions.
 Latin1 replacement   Use the special characters available in latin1.
 utf-8 replacement    Use the special characters available in utf-8.
 
@@ -77,439 +75,454 @@ packages to be loaded, add these packages to 
`org-latex-packages-alist'."
           (string :tag "HTML  ")
           (string :tag "ASCII ")
           (string :tag "Latin1")
-          (string :tag "utf-8 "))))
+          (string :tag "utf-8 ")))
+  :safe #'org-entities--user-safe-p)
 
 (defconst org-entities
-  '(
-    "* Letters"
-    "** Latin"
-    ("Agrave" "\\`{A}" nil "&Agrave;" "A" "À" "À")
-    ("agrave" "\\`{a}" nil "&agrave;" "a" "à" "à")
-    ("Aacute" "\\'{A}" nil "&Aacute;" "A" "Á" "Á")
-    ("aacute" "\\'{a}" nil "&aacute;" "a" "á" "á")
-    ("Acirc" "\\^{A}" nil "&Acirc;" "A" "Â" "Â")
-    ("acirc" "\\^{a}" nil "&acirc;" "a" "â" "â")
-    ("Atilde" "\\~{A}" nil "&Atilde;" "A" "Ã" "Ã")
-    ("atilde" "\\~{a}" nil "&atilde;" "a" "ã" "ã")
-    ("Auml" "\\\"{A}" nil "&Auml;" "Ae" "Ä" "Ä")
-    ("auml" "\\\"{a}" nil "&auml;" "ae" "ä" "ä")
-    ("Aring" "\\AA{}" nil "&Aring;" "A" "Å" "Å")
-    ("AA" "\\AA{}" nil "&Aring;" "A" "Å" "Å")
-    ("aring" "\\aa{}" nil "&aring;" "a" "å" "å")
-    ("AElig" "\\AE{}" nil "&AElig;" "AE" "Æ" "Æ")
-    ("aelig" "\\ae{}" nil "&aelig;" "ae" "æ" "æ")
-    ("Ccedil" "\\c{C}" nil "&Ccedil;" "C" "Ç" "Ç")
-    ("ccedil" "\\c{c}" nil "&ccedil;" "c" "ç" "ç")
-    ("Egrave" "\\`{E}" nil "&Egrave;" "E" "È" "È")
-    ("egrave" "\\`{e}" nil "&egrave;" "e" "è" "è")
-    ("Eacute" "\\'{E}" nil "&Eacute;" "E" "É" "É")
-    ("eacute" "\\'{e}" nil "&eacute;" "e" "é" "é")
-    ("Ecirc" "\\^{E}" nil "&Ecirc;" "E" "Ê" "Ê")
-    ("ecirc" "\\^{e}" nil "&ecirc;" "e" "ê" "ê")
-    ("Euml" "\\\"{E}" nil "&Euml;" "E" "Ë" "Ë")
-    ("euml" "\\\"{e}" nil "&euml;" "e" "ë" "ë")
-    ("Igrave" "\\`{I}" nil "&Igrave;" "I" "Ì" "Ì")
-    ("igrave" "\\`{i}" nil "&igrave;" "i" "ì" "ì")
-    ("Iacute" "\\'{I}" nil "&Iacute;" "I" "Í" "Í")
-    ("iacute" "\\'{i}" nil "&iacute;" "i" "í" "í")
-    ("Icirc" "\\^{I}" nil "&Icirc;" "I" "Î" "Î")
-    ("icirc" "\\^{i}" nil "&icirc;" "i" "î" "î")
-    ("Iuml" "\\\"{I}" nil "&Iuml;" "I" "Ï" "Ï")
-    ("iuml" "\\\"{i}" nil "&iuml;" "i" "ï" "ï")
-    ("Ntilde" "\\~{N}" nil "&Ntilde;" "N" "Ñ" "Ñ")
-    ("ntilde" "\\~{n}" nil "&ntilde;" "n" "ñ" "ñ")
-    ("Ograve" "\\`{O}" nil "&Ograve;" "O" "Ò" "Ò")
-    ("ograve" "\\`{o}" nil "&ograve;" "o" "ò" "ò")
-    ("Oacute" "\\'{O}" nil "&Oacute;" "O" "Ó" "Ó")
-    ("oacute" "\\'{o}" nil "&oacute;" "o" "ó" "ó")
-    ("Ocirc" "\\^{O}" nil "&Ocirc;" "O" "Ô" "Ô")
-    ("ocirc" "\\^{o}" nil "&ocirc;" "o" "ô" "ô")
-    ("Otilde" "\\~{O}" nil "&Otilde;" "O" "Õ" "Õ")
-    ("otilde" "\\~{o}" nil "&otilde;" "o" "õ" "õ")
-    ("Ouml" "\\\"{O}" nil "&Ouml;" "Oe" "Ö" "Ö")
-    ("ouml" "\\\"{o}" nil "&ouml;" "oe" "ö" "ö")
-    ("Oslash" "\\O" nil "&Oslash;" "O" "Ø" "Ø")
-    ("oslash" "\\o{}" nil "&oslash;" "o" "ø" "ø")
-    ("OElig" "\\OE{}" nil "&OElig;" "OE" "OE" "Œ")
-    ("oelig" "\\oe{}" nil "&oelig;" "oe" "oe" "œ")
-    ("Scaron" "\\v{S}" nil "&Scaron;" "S" "S" "Š")
-    ("scaron" "\\v{s}" nil "&scaron;" "s" "s" "š")
-    ("szlig" "\\ss{}" nil "&szlig;" "ss" "ß" "ß")
-    ("Ugrave" "\\`{U}" nil "&Ugrave;" "U" "Ù" "Ù")
-    ("ugrave" "\\`{u}" nil "&ugrave;" "u" "ù" "ù")
-    ("Uacute" "\\'{U}" nil "&Uacute;" "U" "Ú" "Ú")
-    ("uacute" "\\'{u}" nil "&uacute;" "u" "ú" "ú")
-    ("Ucirc" "\\^{U}" nil "&Ucirc;" "U" "Û" "Û")
-    ("ucirc" "\\^{u}" nil "&ucirc;" "u" "û" "û")
-    ("Uuml" "\\\"{U}" nil "&Uuml;" "Ue" "Ü" "Ü")
-    ("uuml" "\\\"{u}" nil "&uuml;" "ue" "ü" "ü")
-    ("Yacute" "\\'{Y}" nil "&Yacute;" "Y" "Ý" "Ý")
-    ("yacute" "\\'{y}" nil "&yacute;" "y" "ý" "ý")
-    ("Yuml" "\\\"{Y}" nil "&Yuml;" "Y" "Y" "Ÿ")
-    ("yuml" "\\\"{y}" nil "&yuml;" "y" "ÿ" "ÿ")
-
-    "** Latin (special face)"
-    ("fnof" "\\textit{f}" nil "&fnof;" "f" "f" "ƒ")
-    ("real" "\\Re" t "&real;" "R" "R" "ℜ")
-    ("image" "\\Im" t "&image;" "I" "I" "ℑ")
-    ("weierp" "\\wp" t "&weierp;" "P" "P" "℘")
-    ("ell" "\\ell" t "&ell;" "ell" "ell" "ℓ")
-    ("imath" "\\imath" t "&imath;" "[dotless i]" "dotless i" "ı")
-    ("jmath" "\\jmath" t "&jmath;" "[dotless j]" "dotless j" "ȷ")
-
-    "** Greek"
-    ("Alpha" "A" nil "&Alpha;" "Alpha" "Alpha" "Α")
-    ("alpha" "\\alpha" t "&alpha;" "alpha" "alpha" "α")
-    ("Beta" "B" nil "&Beta;" "Beta" "Beta" "Β")
-    ("beta" "\\beta" t "&beta;" "beta" "beta" "β")
-    ("Gamma" "\\Gamma" t "&Gamma;" "Gamma" "Gamma" "Γ")
-    ("gamma" "\\gamma" t "&gamma;" "gamma" "gamma" "γ")
-    ("Delta" "\\Delta" t "&Delta;" "Delta" "Gamma" "Δ")
-    ("delta" "\\delta" t "&delta;" "delta" "delta" "δ")
-    ("Epsilon" "E" nil "&Epsilon;" "Epsilon" "Epsilon" "Ε")
-    ("epsilon" "\\epsilon" t "&epsilon;" "epsilon" "epsilon" "ε")
-    ("varepsilon" "\\varepsilon" t "&epsilon;" "varepsilon" "varepsilon" "ε")
-    ("Zeta" "Z" nil "&Zeta;" "Zeta" "Zeta" "Ζ")
-    ("zeta" "\\zeta" t "&zeta;" "zeta" "zeta" "ζ")
-    ("Eta" "H" nil "&Eta;" "Eta" "Eta" "Η")
-    ("eta" "\\eta" t "&eta;" "eta" "eta" "η")
-    ("Theta" "\\Theta" t "&Theta;" "Theta" "Theta" "Θ")
-    ("theta" "\\theta" t "&theta;" "theta" "theta" "θ")
-    ("thetasym" "\\vartheta" t "&thetasym;" "theta" "theta" "ϑ")
-    ("vartheta" "\\vartheta" t "&thetasym;" "theta" "theta" "ϑ")
-    ("Iota" "I" nil "&Iota;" "Iota" "Iota" "Ι")
-    ("iota" "\\iota" t "&iota;" "iota" "iota" "ι")
-    ("Kappa" "K" nil "&Kappa;" "Kappa" "Kappa" "Κ")
-    ("kappa" "\\kappa" t "&kappa;" "kappa" "kappa" "κ")
-    ("Lambda" "\\Lambda" t "&Lambda;" "Lambda" "Lambda" "Λ")
-    ("lambda" "\\lambda" t "&lambda;" "lambda" "lambda" "λ")
-    ("Mu" "M" nil "&Mu;" "Mu" "Mu" "Μ")
-    ("mu" "\\mu" t "&mu;" "mu" "mu" "μ")
-    ("nu" "\\nu" t "&nu;" "nu" "nu" "ν")
-    ("Nu" "N" nil "&Nu;" "Nu" "Nu" "Ν")
-    ("Xi" "\\Xi" t "&Xi;" "Xi" "Xi" "Ξ")
-    ("xi" "\\xi" t "&xi;" "xi" "xi" "ξ")
-    ("Omicron" "O" nil "&Omicron;" "Omicron" "Omicron" "Ο")
-    ("omicron" "\\textit{o}" nil "&omicron;" "omicron" "omicron" "ο")
-    ("Pi" "\\Pi" t "&Pi;" "Pi" "Pi" "Π")
-    ("pi" "\\pi" t "&pi;" "pi" "pi" "π")
-    ("Rho" "P" nil "&Rho;" "Rho" "Rho" "Ρ")
-    ("rho" "\\rho" t "&rho;" "rho" "rho" "ρ")
-    ("Sigma" "\\Sigma" t "&Sigma;" "Sigma" "Sigma" "Σ")
-    ("sigma" "\\sigma" t "&sigma;" "sigma" "sigma" "σ")
-    ("sigmaf" "\\varsigma" t "&sigmaf;" "sigmaf" "sigmaf" "ς")
-    ("varsigma" "\\varsigma" t "&sigmaf;" "varsigma" "varsigma" "ς")
-    ("Tau" "T" nil "&Tau;" "Tau" "Tau" "Τ")
-    ("Upsilon" "\\Upsilon" t "&Upsilon;" "Upsilon" "Upsilon" "Υ")
-    ("upsih" "\\Upsilon" t "&upsih;" "upsilon" "upsilon" "ϒ")
-    ("upsilon" "\\upsilon" t "&upsilon;" "upsilon" "upsilon" "υ")
-    ("Phi" "\\Phi" t "&Phi;" "Phi" "Phi" "Φ")
-    ("phi" "\\phi" t "&phi;" "phi" "phi" "φ")
-    ("varphi" "\\varphi" t "&varphi;" "varphi" "varphi" "ɸ")
-    ("Chi" "X" nil "&Chi;" "Chi" "Chi" "Χ")
-    ("chi" "\\chi" t "&chi;" "chi" "chi" "χ")
-    ("acutex" "\\acute x" t "&acute;x" "'x" "'x" "𝑥́")
-    ("Psi" "\\Psi" t "&Psi;" "Psi" "Psi" "Ψ")
-    ("psi" "\\psi" t "&psi;" "psi" "psi" "ψ")
-    ("tau" "\\tau" t "&tau;" "tau" "tau" "τ")
-    ("Omega" "\\Omega" t "&Omega;" "Omega" "Omega" "Ω")
-    ("omega" "\\omega" t "&omega;" "omega" "omega" "ω")
-    ("piv" "\\varpi" t "&piv;" "omega-pi" "omega-pi" "ϖ")
-    ("varpi" "\\varpi" t "&piv;" "omega-pi" "omega-pi" "ϖ")
-    ("partial" "\\partial" t "&part;" "[partial differential]" "[partial 
differential]" "∂")
-
-    "** Hebrew"
-    ("alefsym" "\\aleph" t "&alefsym;" "aleph" "aleph" "ℵ")
-    ("aleph" "\\aleph" t "&aleph;" "aleph" "aleph" "ℵ")
-    ("gimel" "\\gimel" t "&gimel;" "gimel" "gimel" "ℷ")
-    ("beth" "\\beth" t "&beth;" "beth" "beth" "ב")
-    ("dalet" "\\daleth" t "&daleth;" "dalet" "dalet" "ד")
-
-    "** Dead languages"
-    ("ETH" "\\DH{}" nil "&ETH;" "D" "Ð" "Ð")
-    ("eth" "\\dh{}" nil "&eth;" "dh" "ð" "ð")
-    ("THORN" "\\TH{}" nil "&THORN;" "TH" "Þ" "Þ")
-    ("thorn" "\\th{}" nil "&thorn;" "th" "þ" "þ")
-
-    "* Punctuation"
-    "** Dots and Marks"
-    ("dots" "\\dots{}" nil "&hellip;" "..." "..." "…")
-    ("cdots" "\\cdots{}" t "&ctdot;" "..." "..." "⋯")
-    ("hellip" "\\dots{}" nil "&hellip;" "..." "..." "…")
-    ("middot" "\\textperiodcentered{}" nil "&middot;" "." "·" "·")
-    ("iexcl" "!`" nil "&iexcl;" "!" "¡" "¡")
-    ("iquest" "?`" nil "&iquest;" "?" "¿" "¿")
-
-    "** Dash-like"
-    ("shy" "\\-" nil "&shy;" "" "" "")
-    ("ndash" "--" nil "&ndash;" "-" "-" "–")
-    ("mdash" "---" nil "&mdash;" "--" "--" "—")
-
-    "** Quotations"
-    ("quot" "\\textquotedbl{}" nil "&quot;" "\"" "\"" "\"")
-    ("acute" "\\textasciiacute{}" nil "&acute;" "'" "´" "´")
-    ("ldquo" "\\textquotedblleft{}" nil "&ldquo;" "\"" "\"" "“")
-    ("rdquo" "\\textquotedblright{}" nil "&rdquo;" "\"" "\"" "”")
-    ("bdquo" "\\quotedblbase{}" nil "&bdquo;" "\"" "\"" "„")
-    ("lsquo" "\\textquoteleft{}" nil "&lsquo;" "`" "`" "‘")
-    ("rsquo" "\\textquoteright{}" nil "&rsquo;" "'" "'" "’")
-    ("sbquo" "\\quotesinglbase{}" nil "&sbquo;" "," "," "‚")
-    ("laquo" "\\guillemotleft{}" nil "&laquo;" "<<" "«" "«")
-    ("raquo" "\\guillemotright{}" nil "&raquo;" ">>" "»" "»")
-    ("lsaquo" "\\guilsinglleft{}" nil "&lsaquo;" "<" "<" "‹")
-    ("rsaquo" "\\guilsinglright{}" nil "&rsaquo;" ">" ">" "›")
-
-    "* Other"
-    "** Misc. (often used)"
-    ("circ" "\\^{}" nil "&circ;" "^" "^" "ˆ")
-    ("vert" "\\vert{}" t "&vert;" "|" "|" "|")
-    ("brvbar" "\\textbrokenbar{}" nil "&brvbar;" "|" "¦" "¦")
-    ("S" "\\S" nil "&sect;" "paragraph" "§" "§")
-    ("sect" "\\S" nil "&sect;" "paragraph" "§" "§")
-    ("amp" "\\&" nil "&amp;" "&" "&" "&")
-    ("lt" "\\textless{}" nil "&lt;" "<" "<" "<")
-    ("gt" "\\textgreater{}" nil "&gt;" ">" ">" ">")
-    ("tilde" "\\textasciitilde{}" nil "~" "~" "~" "~")
-    ("slash" "/" nil "/" "/" "/" "/")
-    ("plus" "+" nil "+" "+" "+" "+")
-    ("under" "\\_" nil "_" "_" "_" "_")
-    ("equal" "=" nil "=" "=" "=" "=")
-    ("asciicirc" "\\textasciicircum{}" nil "^" "^" "^" "^")
-    ("dagger" "\\textdagger{}" nil "&dagger;" "[dagger]" "[dagger]" "†")
-    ("dag" "\\dag{}" nil "&dagger;" "[dagger]" "[dagger]" "†")
-    ("Dagger" "\\textdaggerdbl{}" nil "&Dagger;" "[doubledagger]" 
"[doubledagger]" "‡")
-    ("ddag" "\\ddag{}" nil "&Dagger;" "[doubledagger]" "[doubledagger]" "‡")
-
-    "** Whitespace"
-    ("nbsp" "~" nil "&nbsp;" " " " " " ")
-    ("ensp" "\\hspace*{.5em}" nil "&ensp;" " " " " " ")
-    ("emsp" "\\hspace*{1em}" nil "&emsp;" " " " " " ")
-    ("thinsp" "\\hspace*{.2em}" nil "&thinsp;" " " " " " ")
-
-    "** Currency"
-    ("curren" "\\textcurrency{}" nil "&curren;" "curr." "¤" "¤")
-    ("cent" "\\textcent{}" nil "&cent;" "cent" "¢" "¢")
-    ("pound" "\\pounds{}" nil "&pound;" "pound" "£" "£")
-    ("yen" "\\textyen{}" nil "&yen;" "yen" "¥" "¥")
-    ("euro" "\\texteuro{}" nil "&euro;" "EUR" "EUR" "€")
-    ("EUR" "\\EUR{}" nil "&euro;" "EUR" "EUR" "€")
-    ("EURdig" "\\EURdig{}" nil "&euro;" "EUR" "EUR" "€")
-    ("EURhv" "\\EURhv{}" nil "&euro;" "EUR" "EUR" "€")
-    ("EURcr" "\\EURcr{}" nil "&euro;" "EUR" "EUR" "€")
-    ("EURtm" "\\EURtm{}" nil "&euro;" "EUR" "EUR" "€")
-
-    "** Property Marks"
-    ("copy" "\\textcopyright{}" nil "&copy;" "(c)" "©" "©")
-    ("reg" "\\textregistered{}" nil "&reg;" "(r)" "®" "®")
-    ("trade" "\\texttrademark{}" nil "&trade;" "TM" "TM" "™")
-
-    "** Science et al."
-    ("minus" "\\minus" t "&minus;" "-" "-" "−")
-    ("pm" "\\textpm{}" nil "&plusmn;" "+-" "±" "±")
-    ("plusmn" "\\textpm{}" nil "&plusmn;" "+-" "±" "±")
-    ("times" "\\texttimes{}" nil "&times;" "*" "×" "×")
-    ("frasl" "/" nil "&frasl;" "/" "/" "⁄")
-    ("colon" "\\colon" t ":" ":" ":" ":")
-    ("div" "\\textdiv{}" nil "&divide;" "/" "÷" "÷")
-    ("frac12" "\\textonehalf{}" nil "&frac12;" "1/2" "½" "½")
-    ("frac14" "\\textonequarter{}" nil "&frac14;" "1/4" "¼" "¼")
-    ("frac34" "\\textthreequarters{}" nil "&frac34;" "3/4" "¾" "¾")
-    ("permil" "\\textperthousand{}" nil "&permil;" "per thousand" "per 
thousand" "‰")
-    ("sup1" "\\textonesuperior{}" nil "&sup1;" "^1" "¹" "¹")
-    ("sup2" "\\texttwosuperior{}" nil "&sup2;" "^2" "²" "²")
-    ("sup3" "\\textthreesuperior{}" nil "&sup3;" "^3" "³" "³")
-    ("radic" "\\sqrt{\\,}" t "&radic;" "[square root]" "[square root]" "√")
-    ("sum" "\\sum" t "&sum;" "[sum]" "[sum]" "∑")
-    ("prod" "\\prod" t "&prod;" "[product]" "[n-ary product]" "∏")
-    ("micro" "\\textmu{}" nil "&micro;" "micro" "µ" "µ")
-    ("macr" "\\textasciimacron{}" nil "&macr;" "[macron]" "¯" "¯")
-    ("deg" "\\textdegree{}" nil "&deg;" "degree" "°" "°")
-    ("prime" "\\prime" t "&prime;" "'" "'" "′")
-    ("Prime" "\\prime{}\\prime" t "&Prime;" "''" "''" "″")
-    ("infin" "\\propto" t "&infin;" "[infinity]" "[infinity]" "∞")
-    ("infty" "\\infty" t "&infin;" "[infinity]" "[infinity]" "∞")
-    ("prop" "\\propto" t "&prop;" "[proportional to]" "[proportional to]" "∝")
-    ("propto" "\\propto" t "&prop;" "[proportional to]" "[proportional to]" 
"∝")
-    ("not" "\\textlnot{}" nil "&not;" "[angled dash]" "¬" "¬")
-    ("neg" "\\neg{}" t "&not;" "[angled dash]" "¬" "¬")
-    ("land" "\\land" t "&and;" "[logical and]" "[logical and]" "∧")
-    ("wedge" "\\wedge" t "&and;" "[logical and]" "[logical and]" "∧")
-    ("lor" "\\lor" t "&or;" "[logical or]" "[logical or]" "∨")
-    ("vee" "\\vee" t "&or;" "[logical or]" "[logical or]" "∨")
-    ("cap" "\\cap" t "&cap;" "[intersection]" "[intersection]" "∩")
-    ("cup" "\\cup" t "&cup;" "[union]" "[union]" "∪")
-    ("int" "\\int" t "&int;" "[integral]" "[integral]" "∫")
-    ("therefore" "\\therefore" t "&there4;" "[therefore]" "[therefore]" "∴")
-    ("there4" "\\therefore" t "&there4;" "[therefore]" "[therefore]" "∴")
-    ("because" "\\because" t "&because;" "[because]" "[because]" "∵")
-    ("sim" "\\sim" t "&sim;" "~" "~" "∼")
-    ("cong" "\\cong" t "&cong;" "[approx. equal to]" "[approx. equal to]" "≅")
-    ("simeq" "\\simeq" t "&cong;"  "[approx. equal to]" "[approx. equal to]" 
"≅")
-    ("asymp" "\\asymp" t "&asymp;" "[almost equal to]" "[almost equal to]" "≈")
-    ("approx" "\\approx" t "&asymp;" "[almost equal to]" "[almost equal to]" 
"≈")
-    ("ne" "\\ne" t "&ne;" "[not equal to]" "[not equal to]" "≠")
-    ("neq" "\\neq" t "&ne;" "[not equal to]" "[not equal to]" "≠")
-    ("equiv" "\\equiv" t "&equiv;" "[identical to]" "[identical to]" "≡")
-
-    ("triangleq" "\\triangleq" t "&triangleq;" "[defined to]" "[defined to]" 
"≜")
-    ("le" "\\le" t "&le;" "<=" "<=" "≤")
-    ("leq" "\\le" t "&le;" "<=" "<=" "≤")
-    ("ge" "\\ge" t "&ge;" ">=" ">=" "≥")
-    ("geq" "\\ge" t "&ge;" ">=" ">=" "≥")
-    ("lessgtr" "\\lessgtr" t "&lessgtr;" "[less than or greater than]" "[less 
than or greater than]" "≶")
-    ("lesseqgtr" "\\lesseqgtr" t "&lesseqgtr;" "[less than or equal or greater 
than or equal]" "[less than or equal or greater than or equal]" "⋚")
-    ("ll" "\\ll" t  "&Lt;" "<<" "<<" "≪")
-    ("Ll" "\\lll" t "&Ll;" "<<<" "<<<" "⋘")
-    ("lll" "\\lll" t "&Ll;" "<<<" "<<<" "⋘")
-    ("gg" "\\gg" t  "&Gt;" ">>" ">>" "≫")
-    ("Gg" "\\ggg" t "&Gg;" ">>>" ">>>" "⋙")
-    ("ggg" "\\ggg" t "&Gg;" ">>>" ">>>" "⋙")
-    ("prec" "\\prec" t "&pr;" "[precedes]" "[precedes]" "≺")
-    ("preceq" "\\preceq" t "&prcue;" "[precedes or equal]" "[precedes or 
equal]" "≼")
-    ("preccurlyeq" "\\preccurlyeq" t "&prcue;" "[precedes or equal]" 
"[precedes or equal]" "≼")
-    ("succ" "\\succ" t "&sc;" "[succeeds]" "[succeeds]" "≻")
-    ("succeq" "\\succeq" t "&sccue;" "[succeeds or equal]" "[succeeds or 
equal]" "≽")
-    ("succcurlyeq" "\\succcurlyeq" t "&sccue;" "[succeeds or equal]" 
"[succeeds or equal]" "≽")
-    ("sub" "\\subset" t "&sub;" "[subset of]" "[subset of]" "⊂")
-    ("subset" "\\subset" t "&sub;" "[subset of]" "[subset of]" "⊂")
-    ("sup" "\\supset" t "&sup;" "[superset of]" "[superset of]" "⊃")
-    ("supset" "\\supset" t "&sup;" "[superset of]" "[superset of]" "⊃")
-    ("nsub" "\\not\\subset" t "&nsub;" "[not a subset of]" "[not a subset of" 
"⊄")
-    ("sube" "\\subseteq" t "&sube;" "[subset of or equal to]" "[subset of or 
equal to]" "⊆")
-    ("nsup" "\\not\\supset" t "&nsup;" "[not a superset of]" "[not a superset 
of]" "⊅")
-    ("supe" "\\supseteq" t "&supe;" "[superset of or equal to]" "[superset of 
or equal to]" "⊇")
-    ("setminus" "\\setminus" t "&setminus;" "\" "\" "⧵")
-    ("forall" "\\forall" t "&forall;" "[for all]" "[for all]" "∀")
-    ("exist" "\\exists" t "&exist;" "[there exists]" "[there exists]" "∃")
-    ("exists" "\\exists" t "&exist;" "[there exists]" "[there exists]" "∃")
-    ("nexist" "\\nexists" t "&exist;" "[there does not exists]" "[there does 
not  exists]" "∄")
-    ("nexists" "\\nexists" t "&exist;" "[there does not exists]" "[there does 
not  exists]" "∄")
-    ("empty" "\\empty" t "&empty;" "[empty set]" "[empty set]" "∅")
-    ("emptyset" "\\emptyset" t "&empty;" "[empty set]" "[empty set]" "∅")
-    ("isin" "\\in" t "&isin;" "[element of]" "[element of]" "∈")
-    ("in" "\\in" t "&isin;" "[element of]" "[element of]" "∈")
-    ("notin" "\\notin" t "&notin;" "[not an element of]" "[not an element of]" 
"∉")
-    ("ni" "\\ni" t "&ni;" "[contains as member]" "[contains as member]" "∋")
-    ("nabla" "\\nabla" t "&nabla;" "[nabla]" "[nabla]" "∇")
-    ("ang" "\\angle" t "&ang;" "[angle]" "[angle]" "∠")
-    ("angle" "\\angle" t "&ang;" "[angle]" "[angle]" "∠")
-    ("perp" "\\perp" t "&perp;" "[up tack]" "[up tack]" "⊥")
-    ("sdot" "\\cdot" t "&sdot;" "[dot]" "[dot]" "⋅")
-    ("cdot" "\\cdot" t "&sdot;" "[dot]" "[dot]" "⋅")
-    ("lceil" "\\lceil" t "&lceil;" "[left ceiling]" "[left ceiling]" "⌈")
-    ("rceil" "\\rceil" t "&rceil;" "[right ceiling]" "[right ceiling]" "⌉")
-    ("lfloor" "\\lfloor" t "&lfloor;" "[left floor]" "[left floor]" "⌊")
-    ("rfloor" "\\rfloor" t "&rfloor;" "[right floor]" "[right floor]" "⌋")
-    ("lang" "\\langle" t "&lang;" "<" "<" "⟨")
-    ("rang" "\\rangle" t "&rang;" ">" ">" "⟩")
-    ("hbar" "\\hbar" t "&hbar;" "hbar" "hbar" "ℏ")
-    ("mho" "\\mho" t "&mho;" "mho" "mho" "℧")
-
-    "** Arrows"
-    ("larr" "\\leftarrow" t "&larr;" "<-" "<-" "←")
-    ("leftarrow" "\\leftarrow" t "&larr;"  "<-" "<-" "←")
-    ("gets" "\\gets" t "&larr;"  "<-" "<-" "←")
-    ("lArr" "\\Leftarrow" t "&lArr;" "<=" "<=" "⇐")
-    ("Leftarrow" "\\Leftarrow" t "&lArr;" "<=" "<=" "⇐")
-    ("uarr" "\\uparrow" t "&uarr;" "[uparrow]" "[uparrow]" "↑")
-    ("uparrow" "\\uparrow" t "&uarr;" "[uparrow]" "[uparrow]" "↑")
-    ("uArr" "\\Uparrow" t "&uArr;" "[dbluparrow]" "[dbluparrow]" "⇑")
-    ("Uparrow" "\\Uparrow" t "&uArr;" "[dbluparrow]" "[dbluparrow]" "⇑")
-    ("rarr" "\\rightarrow" t "&rarr;" "->" "->" "→")
-    ("to" "\\to" t "&rarr;" "->" "->" "→")
-    ("rightarrow" "\\rightarrow" t "&rarr;"  "->" "->" "→")
-    ("rArr" "\\Rightarrow" t "&rArr;" "=>" "=>" "⇒")
-    ("Rightarrow" "\\Rightarrow" t "&rArr;" "=>" "=>" "⇒")
-    ("darr" "\\downarrow" t "&darr;" "[downarrow]" "[downarrow]" "↓")
-    ("downarrow" "\\downarrow" t "&darr;" "[downarrow]" "[downarrow]" "↓")
-    ("dArr" "\\Downarrow" t "&dArr;" "[dbldownarrow]" "[dbldownarrow]" "⇓")
-    ("Downarrow" "\\Downarrow" t "&dArr;" "[dbldownarrow]" "[dbldownarrow]" 
"⇓")
-    ("harr" "\\leftrightarrow" t "&harr;" "<->" "<->" "↔")
-    ("leftrightarrow" "\\leftrightarrow" t "&harr;"  "<->" "<->" "↔")
-    ("hArr" "\\Leftrightarrow" t "&hArr;" "<=>" "<=>" "⇔")
-    ("Leftrightarrow" "\\Leftrightarrow" t "&hArr;" "<=>" "<=>" "⇔")
-    ("crarr" "\\hookleftarrow" t "&crarr;" "<-'" "<-'" "↵")
-    ("hookleftarrow" "\\hookleftarrow" t "&crarr;"  "<-'" "<-'" "↵")
-
-    "** Function names"
-    ("arccos" "\\arccos" t "arccos" "arccos" "arccos" "arccos")
-    ("arcsin" "\\arcsin" t "arcsin" "arcsin" "arcsin" "arcsin")
-    ("arctan" "\\arctan" t "arctan" "arctan" "arctan" "arctan")
-    ("arg" "\\arg" t "arg" "arg" "arg" "arg")
-    ("cos" "\\cos" t "cos" "cos" "cos" "cos")
-    ("cosh" "\\cosh" t "cosh" "cosh" "cosh" "cosh")
-    ("cot" "\\cot" t "cot" "cot" "cot" "cot")
-    ("coth" "\\coth" t "coth" "coth" "coth" "coth")
-    ("csc" "\\csc" t "csc" "csc" "csc" "csc")
-    ("deg" "\\deg" t "&deg;" "deg" "deg" "deg")
-    ("det" "\\det" t "det" "det" "det" "det")
-    ("dim" "\\dim" t "dim" "dim" "dim" "dim")
-    ("exp" "\\exp" t "exp" "exp" "exp" "exp")
-    ("gcd" "\\gcd" t "gcd" "gcd" "gcd" "gcd")
-    ("hom" "\\hom" t "hom" "hom" "hom" "hom")
-    ("inf" "\\inf" t "inf" "inf" "inf" "inf")
-    ("ker" "\\ker" t "ker" "ker" "ker" "ker")
-    ("lg" "\\lg" t "lg" "lg" "lg" "lg")
-    ("lim" "\\lim" t "lim" "lim" "lim" "lim")
-    ("liminf" "\\liminf" t "liminf" "liminf" "liminf" "liminf")
-    ("limsup" "\\limsup" t "limsup" "limsup" "limsup" "limsup")
-    ("ln" "\\ln" t "ln" "ln" "ln" "ln")
-    ("log" "\\log" t "log" "log" "log" "log")
-    ("max" "\\max" t "max" "max" "max" "max")
-    ("min" "\\min" t "min" "min" "min" "min")
-    ("Pr" "\\Pr" t "Pr" "Pr" "Pr" "Pr")
-    ("sec" "\\sec" t "sec" "sec" "sec" "sec")
-    ("sin" "\\sin" t "sin" "sin" "sin" "sin")
-    ("sinh" "\\sinh" t "sinh" "sinh" "sinh" "sinh")
-    ("sup" "\\sup" t "&sup;" "sup" "sup" "sup")
-    ("tan" "\\tan" t "tan" "tan" "tan" "tan")
-    ("tanh" "\\tanh" t "tanh" "tanh" "tanh" "tanh")
-
-    "** Signs & Symbols"
-    ("bull" "\\textbullet{}" nil "&bull;" "*" "*" "•")
-    ("bullet" "\\textbullet{}" nil "&bull;" "*" "*" "•")
-    ("star" "\\star" t "*" "*" "*" "⋆")
-    ("lowast" "\\ast" t "&lowast;" "*" "*" "∗")
-    ("ast" "\\ast" t "&lowast;" "*" "*" "*")
-    ("odot" "\\odot" t "o" "[circled dot]" "[circled dot]" "ʘ")
-    ("oplus" "\\oplus" t "&oplus;" "[circled plus]" "[circled plus]" "⊕")
-    ("otimes" "\\otimes" t "&otimes;" "[circled times]" "[circled times]" "⊗")
-    ("check" "\\checkmark" t "&checkmark;" "[checkmark]" "[checkmark]" "✓")
-    ("checkmark" "\\checkmark" t "&check;" "[checkmark]" "[checkmark]" "✓")
-
-    "** Miscellaneous (seldom used)"
-    ("para" "\\P{}" nil "&para;" "[pilcrow]" "¶" "¶")
-    ("ordf" "\\textordfeminine{}" nil "&ordf;" "_a_" "ª" "ª")
-    ("ordm" "\\textordmasculine{}" nil "&ordm;" "_o_" "º" "º")
-    ("cedil" "\\c{}" nil "&cedil;" "[cedilla]" "¸" "¸")
-    ("oline" "\\overline{~}" t "&oline;" "[overline]" "¯" "‾")
-    ("uml" "\\textasciidieresis{}" nil "&uml;" "[diaeresis]" "¨" "¨")
-    ("zwnj" "\\/{}" nil "&zwnj;" "" "" "‌")
-    ("zwj" "" nil "&zwj;" "" "" "‍")
-    ("lrm" "" nil "&lrm;" "" "" "‎")
-    ("rlm" "" nil "&rlm;" "" "" "‏")
-
-    "** Smilies"
-    ("smile" "\\smile" t "&smile;" ":-)" ":-)" "⌣")
-    ("frown" "\\frown" t "&frown;" ":-(" ":-(" "⌢")
-    ("smiley" "\\smiley{}" nil "&#9786;" ":-)" ":-)" "☺")
-    ("blacksmile" "\\blacksmiley{}" nil "&#9787;" ":-)" ":-)" "☻")
-    ("sad" "\\frownie{}" nil "&#9785;" ":-(" ":-(" "☹")
-
-    "** Suits"
-    ("clubs" "\\clubsuit" t "&clubs;" "[clubs]" "[clubs]" "♣")
-    ("clubsuit" "\\clubsuit" t "&clubs;" "[clubs]" "[clubs]" "♣")
-    ("spades" "\\spadesuit" t "&spades;" "[spades]" "[spades]" "♠")
-    ("spadesuit" "\\spadesuit" t "&spades;" "[spades]" "[spades]" "♠")
-    ("hearts" "\\heartsuit" t "&hearts;" "[hearts]" "[hearts]" "♥")
-    ("heartsuit" "\\heartsuit" t "&heartsuit;" "[hearts]" "[hearts]" "♥")
-    ("diams" "\\diamondsuit" t "&diams;" "[diamonds]" "[diamonds]" "◆")
-    ("diamondsuit" "\\diamondsuit" t "&diams;" "[diamonds]" "[diamonds]" "◆")
-    ("diamond" "\\diamondsuit" t "&diamond;" "[diamond]" "[diamond]" "◆")
-    ("Diamond" "\\diamondsuit" t "&diamond;" "[diamond]" "[diamond]" "◆")
-    ("loz" "\\lozenge" t "&loz;" "[lozenge]" "[lozenge]" "⧫")
-    )
-  "Default entities used in Org-mode to produce special characters.
+  (append
+   '("* Letters"
+     "** Latin"
+     ("Agrave" "\\`{A}" nil "&Agrave;" "A" "À" "À")
+     ("agrave" "\\`{a}" nil "&agrave;" "a" "à" "à")
+     ("Aacute" "\\'{A}" nil "&Aacute;" "A" "Á" "Á")
+     ("aacute" "\\'{a}" nil "&aacute;" "a" "á" "á")
+     ("Acirc" "\\^{A}" nil "&Acirc;" "A" "Â" "Â")
+     ("acirc" "\\^{a}" nil "&acirc;" "a" "â" "â")
+     ("Amacr" "\\bar{A}" nil "&Amacr;" "A" "Ã" "Ã")
+     ("amacr" "\\bar{a}" nil "&amacr;" "a" "ã" "ã")
+     ("Atilde" "\\~{A}" nil "&Atilde;" "A" "Ã" "Ã")
+     ("atilde" "\\~{a}" nil "&atilde;" "a" "ã" "ã")
+     ("Auml" "\\\"{A}" nil "&Auml;" "Ae" "Ä" "Ä")
+     ("auml" "\\\"{a}" nil "&auml;" "ae" "ä" "ä")
+     ("Aring" "\\AA{}" nil "&Aring;" "A" "Å" "Å")
+     ("AA" "\\AA{}" nil "&Aring;" "A" "Å" "Å")
+     ("aring" "\\aa{}" nil "&aring;" "a" "å" "å")
+     ("AElig" "\\AE{}" nil "&AElig;" "AE" "Æ" "Æ")
+     ("aelig" "\\ae{}" nil "&aelig;" "ae" "æ" "æ")
+     ("Ccedil" "\\c{C}" nil "&Ccedil;" "C" "Ç" "Ç")
+     ("ccedil" "\\c{c}" nil "&ccedil;" "c" "ç" "ç")
+     ("Egrave" "\\`{E}" nil "&Egrave;" "E" "È" "È")
+     ("egrave" "\\`{e}" nil "&egrave;" "e" "è" "è")
+     ("Eacute" "\\'{E}" nil "&Eacute;" "E" "É" "É")
+     ("eacute" "\\'{e}" nil "&eacute;" "e" "é" "é")
+     ("Ecirc" "\\^{E}" nil "&Ecirc;" "E" "Ê" "Ê")
+     ("ecirc" "\\^{e}" nil "&ecirc;" "e" "ê" "ê")
+     ("Euml" "\\\"{E}" nil "&Euml;" "E" "Ë" "Ë")
+     ("euml" "\\\"{e}" nil "&euml;" "e" "ë" "ë")
+     ("Igrave" "\\`{I}" nil "&Igrave;" "I" "Ì" "Ì")
+     ("igrave" "\\`{i}" nil "&igrave;" "i" "ì" "ì")
+     ("Iacute" "\\'{I}" nil "&Iacute;" "I" "Í" "Í")
+     ("iacute" "\\'{i}" nil "&iacute;" "i" "í" "í")
+     ("Icirc" "\\^{I}" nil "&Icirc;" "I" "Î" "Î")
+     ("icirc" "\\^{i}" nil "&icirc;" "i" "î" "î")
+     ("Iuml" "\\\"{I}" nil "&Iuml;" "I" "Ï" "Ï")
+     ("iuml" "\\\"{i}" nil "&iuml;" "i" "ï" "ï")
+     ("Ntilde" "\\~{N}" nil "&Ntilde;" "N" "Ñ" "Ñ")
+     ("ntilde" "\\~{n}" nil "&ntilde;" "n" "ñ" "ñ")
+     ("Ograve" "\\`{O}" nil "&Ograve;" "O" "Ò" "Ò")
+     ("ograve" "\\`{o}" nil "&ograve;" "o" "ò" "ò")
+     ("Oacute" "\\'{O}" nil "&Oacute;" "O" "Ó" "Ó")
+     ("oacute" "\\'{o}" nil "&oacute;" "o" "ó" "ó")
+     ("Ocirc" "\\^{O}" nil "&Ocirc;" "O" "Ô" "Ô")
+     ("ocirc" "\\^{o}" nil "&ocirc;" "o" "ô" "ô")
+     ("Otilde" "\\~{O}" nil "&Otilde;" "O" "Õ" "Õ")
+     ("otilde" "\\~{o}" nil "&otilde;" "o" "õ" "õ")
+     ("Ouml" "\\\"{O}" nil "&Ouml;" "Oe" "Ö" "Ö")
+     ("ouml" "\\\"{o}" nil "&ouml;" "oe" "ö" "ö")
+     ("Oslash" "\\O" nil "&Oslash;" "O" "Ø" "Ø")
+     ("oslash" "\\o{}" nil "&oslash;" "o" "ø" "ø")
+     ("OElig" "\\OE{}" nil "&OElig;" "OE" "OE" "Œ")
+     ("oelig" "\\oe{}" nil "&oelig;" "oe" "oe" "œ")
+     ("Scaron" "\\v{S}" nil "&Scaron;" "S" "S" "Š")
+     ("scaron" "\\v{s}" nil "&scaron;" "s" "s" "š")
+     ("szlig" "\\ss{}" nil "&szlig;" "ss" "ß" "ß")
+     ("Ugrave" "\\`{U}" nil "&Ugrave;" "U" "Ù" "Ù")
+     ("ugrave" "\\`{u}" nil "&ugrave;" "u" "ù" "ù")
+     ("Uacute" "\\'{U}" nil "&Uacute;" "U" "Ú" "Ú")
+     ("uacute" "\\'{u}" nil "&uacute;" "u" "ú" "ú")
+     ("Ucirc" "\\^{U}" nil "&Ucirc;" "U" "Û" "Û")
+     ("ucirc" "\\^{u}" nil "&ucirc;" "u" "û" "û")
+     ("Uuml" "\\\"{U}" nil "&Uuml;" "Ue" "Ü" "Ü")
+     ("uuml" "\\\"{u}" nil "&uuml;" "ue" "ü" "ü")
+     ("Yacute" "\\'{Y}" nil "&Yacute;" "Y" "Ý" "Ý")
+     ("yacute" "\\'{y}" nil "&yacute;" "y" "ý" "ý")
+     ("Yuml" "\\\"{Y}" nil "&Yuml;" "Y" "Y" "Ÿ")
+     ("yuml" "\\\"{y}" nil "&yuml;" "y" "ÿ" "ÿ")
+
+     "** Latin (special face)"
+     ("fnof" "\\textit{f}" nil "&fnof;" "f" "f" "ƒ")
+     ("real" "\\Re" t "&real;" "R" "R" "ℜ")
+     ("image" "\\Im" t "&image;" "I" "I" "ℑ")
+     ("weierp" "\\wp" t "&weierp;" "P" "P" "℘")
+     ("ell" "\\ell" t "&ell;" "ell" "ell" "ℓ")
+     ("imath" "\\imath" t "&imath;" "[dotless i]" "dotless i" "ı")
+     ("jmath" "\\jmath" t "&jmath;" "[dotless j]" "dotless j" "ȷ")
+
+     "** Greek"
+     ("Alpha" "A" nil "&Alpha;" "Alpha" "Alpha" "Α")
+     ("alpha" "\\alpha" t "&alpha;" "alpha" "alpha" "α")
+     ("Beta" "B" nil "&Beta;" "Beta" "Beta" "Β")
+     ("beta" "\\beta" t "&beta;" "beta" "beta" "β")
+     ("Gamma" "\\Gamma" t "&Gamma;" "Gamma" "Gamma" "Γ")
+     ("gamma" "\\gamma" t "&gamma;" "gamma" "gamma" "γ")
+     ("Delta" "\\Delta" t "&Delta;" "Delta" "Delta" "Δ")
+     ("delta" "\\delta" t "&delta;" "delta" "delta" "δ")
+     ("Epsilon" "E" nil "&Epsilon;" "Epsilon" "Epsilon" "Ε")
+     ("epsilon" "\\epsilon" t "&epsilon;" "epsilon" "epsilon" "ε")
+     ("varepsilon" "\\varepsilon" t "&epsilon;" "varepsilon" "varepsilon" "ε")
+     ("Zeta" "Z" nil "&Zeta;" "Zeta" "Zeta" "Ζ")
+     ("zeta" "\\zeta" t "&zeta;" "zeta" "zeta" "ζ")
+     ("Eta" "H" nil "&Eta;" "Eta" "Eta" "Η")
+     ("eta" "\\eta" t "&eta;" "eta" "eta" "η")
+     ("Theta" "\\Theta" t "&Theta;" "Theta" "Theta" "Θ")
+     ("theta" "\\theta" t "&theta;" "theta" "theta" "θ")
+     ("thetasym" "\\vartheta" t "&thetasym;" "theta" "theta" "ϑ")
+     ("vartheta" "\\vartheta" t "&thetasym;" "theta" "theta" "ϑ")
+     ("Iota" "I" nil "&Iota;" "Iota" "Iota" "Ι")
+     ("iota" "\\iota" t "&iota;" "iota" "iota" "ι")
+     ("Kappa" "K" nil "&Kappa;" "Kappa" "Kappa" "Κ")
+     ("kappa" "\\kappa" t "&kappa;" "kappa" "kappa" "κ")
+     ("Lambda" "\\Lambda" t "&Lambda;" "Lambda" "Lambda" "Λ")
+     ("lambda" "\\lambda" t "&lambda;" "lambda" "lambda" "λ")
+     ("Mu" "M" nil "&Mu;" "Mu" "Mu" "Μ")
+     ("mu" "\\mu" t "&mu;" "mu" "mu" "μ")
+     ("nu" "\\nu" t "&nu;" "nu" "nu" "ν")
+     ("Nu" "N" nil "&Nu;" "Nu" "Nu" "Ν")
+     ("Xi" "\\Xi" t "&Xi;" "Xi" "Xi" "Ξ")
+     ("xi" "\\xi" t "&xi;" "xi" "xi" "ξ")
+     ("Omicron" "O" nil "&Omicron;" "Omicron" "Omicron" "Ο")
+     ("omicron" "\\textit{o}" nil "&omicron;" "omicron" "omicron" "ο")
+     ("Pi" "\\Pi" t "&Pi;" "Pi" "Pi" "Π")
+     ("pi" "\\pi" t "&pi;" "pi" "pi" "π")
+     ("Rho" "P" nil "&Rho;" "Rho" "Rho" "Ρ")
+     ("rho" "\\rho" t "&rho;" "rho" "rho" "ρ")
+     ("Sigma" "\\Sigma" t "&Sigma;" "Sigma" "Sigma" "Σ")
+     ("sigma" "\\sigma" t "&sigma;" "sigma" "sigma" "σ")
+     ("sigmaf" "\\varsigma" t "&sigmaf;" "sigmaf" "sigmaf" "ς")
+     ("varsigma" "\\varsigma" t "&sigmaf;" "varsigma" "varsigma" "ς")
+     ("Tau" "T" nil "&Tau;" "Tau" "Tau" "Τ")
+     ("Upsilon" "\\Upsilon" t "&Upsilon;" "Upsilon" "Upsilon" "Υ")
+     ("upsih" "\\Upsilon" t "&upsih;" "upsilon" "upsilon" "ϒ")
+     ("upsilon" "\\upsilon" t "&upsilon;" "upsilon" "upsilon" "υ")
+     ("Phi" "\\Phi" t "&Phi;" "Phi" "Phi" "Φ")
+     ("phi" "\\phi" t "&phi;" "phi" "phi" "ɸ")
+     ("varphi" "\\varphi" t "&varphi;" "varphi" "varphi" "φ")
+     ("Chi" "X" nil "&Chi;" "Chi" "Chi" "Χ")
+     ("chi" "\\chi" t "&chi;" "chi" "chi" "χ")
+     ("acutex" "\\acute x" t "&acute;x" "'x" "'x" "𝑥́")
+     ("Psi" "\\Psi" t "&Psi;" "Psi" "Psi" "Ψ")
+     ("psi" "\\psi" t "&psi;" "psi" "psi" "ψ")
+     ("tau" "\\tau" t "&tau;" "tau" "tau" "τ")
+     ("Omega" "\\Omega" t "&Omega;" "Omega" "Omega" "Ω")
+     ("omega" "\\omega" t "&omega;" "omega" "omega" "ω")
+     ("piv" "\\varpi" t "&piv;" "omega-pi" "omega-pi" "ϖ")
+     ("varpi" "\\varpi" t "&piv;" "omega-pi" "omega-pi" "ϖ")
+     ("partial" "\\partial" t "&part;" "[partial differential]" "[partial 
differential]" "∂")
+
+     "** Hebrew"
+     ("alefsym" "\\aleph" t "&alefsym;" "aleph" "aleph" "ℵ")
+     ("aleph" "\\aleph" t "&aleph;" "aleph" "aleph" "ℵ")
+     ("gimel" "\\gimel" t "&gimel;" "gimel" "gimel" "ℷ")
+     ("beth" "\\beth" t "&beth;" "beth" "beth" "ב")
+     ("dalet" "\\daleth" t "&daleth;" "dalet" "dalet" "ד")
+
+     "** Dead languages"
+     ("ETH" "\\DH{}" nil "&ETH;" "D" "Ð" "Ð")
+     ("eth" "\\dh{}" nil "&eth;" "dh" "ð" "ð")
+     ("THORN" "\\TH{}" nil "&THORN;" "TH" "Þ" "Þ")
+     ("thorn" "\\th{}" nil "&thorn;" "th" "þ" "þ")
+
+     "* Punctuation"
+     "** Dots and Marks"
+     ("dots" "\\dots{}" nil "&hellip;" "..." "..." "…")
+     ("cdots" "\\cdots{}" t "&ctdot;" "..." "..." "⋯")
+     ("hellip" "\\dots{}" nil "&hellip;" "..." "..." "…")
+     ("middot" "\\textperiodcentered{}" nil "&middot;" "." "·" "·")
+     ("iexcl" "!`" nil "&iexcl;" "!" "¡" "¡")
+     ("iquest" "?`" nil "&iquest;" "?" "¿" "¿")
+
+     "** Dash-like"
+     ("shy" "\\-" nil "&shy;" "" "" "")
+     ("ndash" "--" nil "&ndash;" "-" "-" "–")
+     ("mdash" "---" nil "&mdash;" "--" "--" "—")
+
+     "** Quotations"
+     ("quot" "\\textquotedbl{}" nil "&quot;" "\"" "\"" "\"")
+     ("acute" "\\textasciiacute{}" nil "&acute;" "'" "´" "´")
+     ("ldquo" "\\textquotedblleft{}" nil "&ldquo;" "\"" "\"" "“")
+     ("rdquo" "\\textquotedblright{}" nil "&rdquo;" "\"" "\"" "”")
+     ("bdquo" "\\quotedblbase{}" nil "&bdquo;" "\"" "\"" "„")
+     ("lsquo" "\\textquoteleft{}" nil "&lsquo;" "`" "`" "‘")
+     ("rsquo" "\\textquoteright{}" nil "&rsquo;" "'" "'" "’")
+     ("sbquo" "\\quotesinglbase{}" nil "&sbquo;" "," "," "‚")
+     ("laquo" "\\guillemotleft{}" nil "&laquo;" "<<" "«" "«")
+     ("raquo" "\\guillemotright{}" nil "&raquo;" ">>" "»" "»")
+     ("lsaquo" "\\guilsinglleft{}" nil "&lsaquo;" "<" "<" "‹")
+     ("rsaquo" "\\guilsinglright{}" nil "&rsaquo;" ">" ">" "›")
+
+     "* Other"
+     "** Misc. (often used)"
+     ("circ" "\\^{}" nil "&circ;" "^" "^" "∘")
+     ("vert" "\\vert{}" t "&vert;" "|" "|" "|")
+     ("vbar" "|" nil "|" "|" "|" "|")
+     ("brvbar" "\\textbrokenbar{}" nil "&brvbar;" "|" "¦" "¦")
+     ("S" "\\S" nil "&sect;" "paragraph" "§" "§")
+     ("sect" "\\S" nil "&sect;" "paragraph" "§" "§")
+     ("amp" "\\&" nil "&amp;" "&" "&" "&")
+     ("lt" "\\textless{}" nil "&lt;" "<" "<" "<")
+     ("gt" "\\textgreater{}" nil "&gt;" ">" ">" ">")
+     ("tilde" "\\textasciitilde{}" nil "~" "~" "~" "~")
+     ("slash" "/" nil "/" "/" "/" "/")
+     ("plus" "+" nil "+" "+" "+" "+")
+     ("under" "\\_" nil "_" "_" "_" "_")
+     ("equal" "=" nil "=" "=" "=" "=")
+     ("asciicirc" "\\textasciicircum{}" nil "^" "^" "^" "^")
+     ("dagger" "\\textdagger{}" nil "&dagger;" "[dagger]" "[dagger]" "†")
+     ("dag" "\\dag{}" nil "&dagger;" "[dagger]" "[dagger]" "†")
+     ("Dagger" "\\textdaggerdbl{}" nil "&Dagger;" "[doubledagger]" 
"[doubledagger]" "‡")
+     ("ddag" "\\ddag{}" nil "&Dagger;" "[doubledagger]" "[doubledagger]" "‡")
+
+     "** Whitespace"
+     ("nbsp" "~" nil "&nbsp;" " " "\x00A0" "\x00A0")
+     ("ensp" "\\hspace*{.5em}" nil "&ensp;" " " " " " ")
+     ("emsp" "\\hspace*{1em}" nil "&emsp;" " " " " " ")
+     ("thinsp" "\\hspace*{.2em}" nil "&thinsp;" " " " " " ")
+
+     "** Currency"
+     ("curren" "\\textcurrency{}" nil "&curren;" "curr." "¤" "¤")
+     ("cent" "\\textcent{}" nil "&cent;" "cent" "¢" "¢")
+     ("pound" "\\pounds{}" nil "&pound;" "pound" "£" "£")
+     ("yen" "\\textyen{}" nil "&yen;" "yen" "¥" "¥")
+     ("euro" "\\texteuro{}" nil "&euro;" "EUR" "EUR" "€")
+     ("EUR" "\\texteuro{}" nil "&euro;" "EUR" "EUR" "€")
+
+     "** Property Marks"
+     ("copy" "\\textcopyright{}" nil "&copy;" "(c)" "©" "©")
+     ("reg" "\\textregistered{}" nil "&reg;" "(r)" "®" "®")
+     ("trade" "\\texttrademark{}" nil "&trade;" "TM" "TM" "™")
+
+     "** Science et al."
+     ("minus" "\\minus" t "&minus;" "-" "-" "−")
+     ("pm" "\\textpm{}" nil "&plusmn;" "+-" "±" "±")
+     ("plusmn" "\\textpm{}" nil "&plusmn;" "+-" "±" "±")
+     ("times" "\\texttimes{}" nil "&times;" "*" "×" "×")
+     ("frasl" "/" nil "&frasl;" "/" "/" "⁄")
+     ("colon" "\\colon" t ":" ":" ":" ":")
+     ("div" "\\textdiv{}" nil "&divide;" "/" "÷" "÷")
+     ("frac12" "\\textonehalf{}" nil "&frac12;" "1/2" "½" "½")
+     ("frac14" "\\textonequarter{}" nil "&frac14;" "1/4" "¼" "¼")
+     ("frac34" "\\textthreequarters{}" nil "&frac34;" "3/4" "¾" "¾")
+     ("permil" "\\textperthousand{}" nil "&permil;" "per thousand" "per 
thousand" "‰")
+     ("sup1" "\\textonesuperior{}" nil "&sup1;" "^1" "¹" "¹")
+     ("sup2" "\\texttwosuperior{}" nil "&sup2;" "^2" "²" "²")
+     ("sup3" "\\textthreesuperior{}" nil "&sup3;" "^3" "³" "³")
+     ("radic" "\\sqrt{\\,}" t "&radic;" "[square root]" "[square root]" "√")
+     ("sum" "\\sum" t "&sum;" "[sum]" "[sum]" "∑")
+     ("prod" "\\prod" t "&prod;" "[product]" "[n-ary product]" "∏")
+     ("micro" "\\textmu{}" nil "&micro;" "micro" "µ" "µ")
+     ("macr" "\\textasciimacron{}" nil "&macr;" "[macron]" "¯" "¯")
+     ("deg" "\\textdegree{}" nil "&deg;" "degree" "°" "°")
+     ("prime" "\\prime" t "&prime;" "'" "'" "′")
+     ("Prime" "\\prime{}\\prime" t "&Prime;" "''" "''" "″")
+     ("infin" "\\infty" t "&infin;" "[infinity]" "[infinity]" "∞")
+     ("infty" "\\infty" t "&infin;" "[infinity]" "[infinity]" "∞")
+     ("prop" "\\propto" t "&prop;" "[proportional to]" "[proportional to]" "∝")
+     ("propto" "\\propto" t "&prop;" "[proportional to]" "[proportional to]" 
"∝")
+     ("not" "\\textlnot{}" nil "&not;" "[angled dash]" "¬" "¬")
+     ("neg" "\\neg{}" t "&not;" "[angled dash]" "¬" "¬")
+     ("land" "\\land" t "&and;" "[logical and]" "[logical and]" "∧")
+     ("wedge" "\\wedge" t "&and;" "[logical and]" "[logical and]" "∧")
+     ("lor" "\\lor" t "&or;" "[logical or]" "[logical or]" "∨")
+     ("vee" "\\vee" t "&or;" "[logical or]" "[logical or]" "∨")
+     ("cap" "\\cap" t "&cap;" "[intersection]" "[intersection]" "∩")
+     ("cup" "\\cup" t "&cup;" "[union]" "[union]" "∪")
+     ("smile" "\\smile" t "&smile;" "[cup product]" "[cup product]" "⌣")
+     ("frown" "\\frown" t "&frown;" "[Cap product]" "[cap product]" "⌢")
+     ("int" "\\int" t "&int;" "[integral]" "[integral]" "∫")
+     ("therefore" "\\therefore" t "&there4;" "[therefore]" "[therefore]" "∴")
+     ("there4" "\\therefore" t "&there4;" "[therefore]" "[therefore]" "∴")
+     ("because" "\\because" t "&because;" "[because]" "[because]" "∵")
+     ("sim" "\\sim" t "&sim;" "~" "~" "∼")
+     ("cong" "\\cong" t "&cong;" "[approx. equal to]" "[approx. equal to]" "≅")
+     ("simeq" "\\simeq" t "&cong;"  "[approx. equal to]" "[approx. equal to]" 
"≅")
+     ("asymp" "\\asymp" t "&asymp;" "[almost equal to]" "[almost equal to]" 
"≈")
+     ("approx" "\\approx" t "&asymp;" "[almost equal to]" "[almost equal to]" 
"≈")
+     ("ne" "\\ne" t "&ne;" "[not equal to]" "[not equal to]" "≠")
+     ("neq" "\\neq" t "&ne;" "[not equal to]" "[not equal to]" "≠")
+     ("equiv" "\\equiv" t "&equiv;" "[identical to]" "[identical to]" "≡")
+
+     ("triangleq" "\\triangleq" t "&triangleq;" "[defined to]" "[defined to]" 
"≜")
+     ("le" "\\le" t "&le;" "<=" "<=" "≤")
+     ("leq" "\\le" t "&le;" "<=" "<=" "≤")
+     ("ge" "\\ge" t "&ge;" ">=" ">=" "≥")
+     ("geq" "\\ge" t "&ge;" ">=" ">=" "≥")
+     ("lessgtr" "\\lessgtr" t "&lessgtr;" "[less than or greater than]" "[less 
than or greater than]" "≶")
+     ("lesseqgtr" "\\lesseqgtr" t "&lesseqgtr;" "[less than or equal or 
greater than or equal]" "[less than or equal or greater than or equal]" "⋚")
+     ("ll" "\\ll" t  "&Lt;" "<<" "<<" "≪")
+     ("Ll" "\\lll" t "&Ll;" "<<<" "<<<" "⋘")
+     ("lll" "\\lll" t "&Ll;" "<<<" "<<<" "⋘")
+     ("gg" "\\gg" t  "&Gt;" ">>" ">>" "≫")
+     ("Gg" "\\ggg" t "&Gg;" ">>>" ">>>" "⋙")
+     ("ggg" "\\ggg" t "&Gg;" ">>>" ">>>" "⋙")
+     ("prec" "\\prec" t "&pr;" "[precedes]" "[precedes]" "≺")
+     ("preceq" "\\preceq" t "&prcue;" "[precedes or equal]" "[precedes or 
equal]" "≼")
+     ("preccurlyeq" "\\preccurlyeq" t "&prcue;" "[precedes or equal]" 
"[precedes or equal]" "≼")
+     ("succ" "\\succ" t "&sc;" "[succeeds]" "[succeeds]" "≻")
+     ("succeq" "\\succeq" t "&sccue;" "[succeeds or equal]" "[succeeds or 
equal]" "≽")
+     ("succcurlyeq" "\\succcurlyeq" t "&sccue;" "[succeeds or equal]" 
"[succeeds or equal]" "≽")
+     ("sub" "\\subset" t "&sub;" "[subset of]" "[subset of]" "⊂")
+     ("subset" "\\subset" t "&sub;" "[subset of]" "[subset of]" "⊂")
+     ("sup" "\\supset" t "&sup;" "[superset of]" "[superset of]" "⊃")
+     ("supset" "\\supset" t "&sup;" "[superset of]" "[superset of]" "⊃")
+     ("nsub" "\\not\\subset" t "&nsub;" "[not a subset of]" "[not a subset of" 
"⊄")
+     ("sube" "\\subseteq" t "&sube;" "[subset of or equal to]" "[subset of or 
equal to]" "⊆")
+     ("nsup" "\\not\\supset" t "&nsup;" "[not a superset of]" "[not a superset 
of]" "⊅")
+     ("supe" "\\supseteq" t "&supe;" "[superset of or equal to]" "[superset of 
or equal to]" "⊇")
+     ("setminus" "\\setminus" t "&setminus;" "\" "\" "⧵")
+     ("forall" "\\forall" t "&forall;" "[for all]" "[for all]" "∀")
+     ("exist" "\\exists" t "&exist;" "[there exists]" "[there exists]" "∃")
+     ("exists" "\\exists" t "&exist;" "[there exists]" "[there exists]" "∃")
+     ("nexist" "\\nexists" t "&exist;" "[there does not exists]" "[there does 
not  exists]" "∄")
+     ("nexists" "\\nexists" t "&exist;" "[there does not exists]" "[there does 
not  exists]" "∄")
+     ("empty" "\\empty" t "&empty;" "[empty set]" "[empty set]" "∅")
+     ("emptyset" "\\emptyset" t "&empty;" "[empty set]" "[empty set]" "∅")
+     ("isin" "\\in" t "&isin;" "[element of]" "[element of]" "∈")
+     ("in" "\\in" t "&isin;" "[element of]" "[element of]" "∈")
+     ("notin" "\\notin" t "&notin;" "[not an element of]" "[not an element 
of]" "∉")
+     ("ni" "\\ni" t "&ni;" "[contains as member]" "[contains as member]" "∋")
+     ("nabla" "\\nabla" t "&nabla;" "[nabla]" "[nabla]" "∇")
+     ("ang" "\\angle" t "&ang;" "[angle]" "[angle]" "∠")
+     ("angle" "\\angle" t "&ang;" "[angle]" "[angle]" "∠")
+     ("perp" "\\perp" t "&perp;" "[up tack]" "[up tack]" "⊥")
+     ("parallel" "\\parallel" t "&parallel;" "||" "||" "∥")
+     ("sdot" "\\cdot" t "&sdot;" "[dot]" "[dot]" "⋅")
+     ("cdot" "\\cdot" t "&sdot;" "[dot]" "[dot]" "⋅")
+     ("lceil" "\\lceil" t "&lceil;" "[left ceiling]" "[left ceiling]" "⌈")
+     ("rceil" "\\rceil" t "&rceil;" "[right ceiling]" "[right ceiling]" "⌉")
+     ("lfloor" "\\lfloor" t "&lfloor;" "[left floor]" "[left floor]" "⌊")
+     ("rfloor" "\\rfloor" t "&rfloor;" "[right floor]" "[right floor]" "⌋")
+     ("lang" "\\langle" t "&lang;" "<" "<" "⟨")
+     ("rang" "\\rangle" t "&rang;" ">" ">" "⟩")
+     ("langle" "\\langle" t "&lang;" "<" "<" "⟨")
+     ("rangle" "\\rangle" t "&rang;" ">" ">" "⟩")
+     ("hbar" "\\hbar" t "&hbar;" "hbar" "hbar" "ℏ")
+     ("mho" "\\mho" t "&mho;" "mho" "mho" "℧")
+
+     "** Arrows"
+     ("larr" "\\leftarrow" t "&larr;" "<-" "<-" "←")
+     ("leftarrow" "\\leftarrow" t "&larr;"  "<-" "<-" "←")
+     ("gets" "\\gets" t "&larr;"  "<-" "<-" "←")
+     ("lArr" "\\Leftarrow" t "&lArr;" "<=" "<=" "⇐")
+     ("Leftarrow" "\\Leftarrow" t "&lArr;" "<=" "<=" "⇐")
+     ("uarr" "\\uparrow" t "&uarr;" "[uparrow]" "[uparrow]" "↑")
+     ("uparrow" "\\uparrow" t "&uarr;" "[uparrow]" "[uparrow]" "↑")
+     ("uArr" "\\Uparrow" t "&uArr;" "[dbluparrow]" "[dbluparrow]" "⇑")
+     ("Uparrow" "\\Uparrow" t "&uArr;" "[dbluparrow]" "[dbluparrow]" "⇑")
+     ("rarr" "\\rightarrow" t "&rarr;" "->" "->" "→")
+     ("to" "\\to" t "&rarr;" "->" "->" "→")
+     ("rightarrow" "\\rightarrow" t "&rarr;"  "->" "->" "→")
+     ("rArr" "\\Rightarrow" t "&rArr;" "=>" "=>" "⇒")
+     ("Rightarrow" "\\Rightarrow" t "&rArr;" "=>" "=>" "⇒")
+     ("darr" "\\downarrow" t "&darr;" "[downarrow]" "[downarrow]" "↓")
+     ("downarrow" "\\downarrow" t "&darr;" "[downarrow]" "[downarrow]" "↓")
+     ("dArr" "\\Downarrow" t "&dArr;" "[dbldownarrow]" "[dbldownarrow]" "⇓")
+     ("Downarrow" "\\Downarrow" t "&dArr;" "[dbldownarrow]" "[dbldownarrow]" 
"⇓")
+     ("harr" "\\leftrightarrow" t "&harr;" "<->" "<->" "↔")
+     ("leftrightarrow" "\\leftrightarrow" t "&harr;"  "<->" "<->" "↔")
+     ("hArr" "\\Leftrightarrow" t "&hArr;" "<=>" "<=>" "⇔")
+     ("Leftrightarrow" "\\Leftrightarrow" t "&hArr;" "<=>" "<=>" "⇔")
+     ("crarr" "\\hookleftarrow" t "&crarr;" "<-'" "<-'" "↵")
+     ("hookleftarrow" "\\hookleftarrow" t "&crarr;"  "<-'" "<-'" "↵")
+
+     "** Function names"
+     ("arccos" "\\arccos" t "arccos" "arccos" "arccos" "arccos")
+     ("arcsin" "\\arcsin" t "arcsin" "arcsin" "arcsin" "arcsin")
+     ("arctan" "\\arctan" t "arctan" "arctan" "arctan" "arctan")
+     ("arg" "\\arg" t "arg" "arg" "arg" "arg")
+     ("cos" "\\cos" t "cos" "cos" "cos" "cos")
+     ("cosh" "\\cosh" t "cosh" "cosh" "cosh" "cosh")
+     ("cot" "\\cot" t "cot" "cot" "cot" "cot")
+     ("coth" "\\coth" t "coth" "coth" "coth" "coth")
+     ("csc" "\\csc" t "csc" "csc" "csc" "csc")
+     ("deg" "\\deg" t "&deg;" "deg" "deg" "deg")
+     ("det" "\\det" t "det" "det" "det" "det")
+     ("dim" "\\dim" t "dim" "dim" "dim" "dim")
+     ("exp" "\\exp" t "exp" "exp" "exp" "exp")
+     ("gcd" "\\gcd" t "gcd" "gcd" "gcd" "gcd")
+     ("hom" "\\hom" t "hom" "hom" "hom" "hom")
+     ("inf" "\\inf" t "inf" "inf" "inf" "inf")
+     ("ker" "\\ker" t "ker" "ker" "ker" "ker")
+     ("lg" "\\lg" t "lg" "lg" "lg" "lg")
+     ("lim" "\\lim" t "lim" "lim" "lim" "lim")
+     ("liminf" "\\liminf" t "liminf" "liminf" "liminf" "liminf")
+     ("limsup" "\\limsup" t "limsup" "limsup" "limsup" "limsup")
+     ("ln" "\\ln" t "ln" "ln" "ln" "ln")
+     ("log" "\\log" t "log" "log" "log" "log")
+     ("max" "\\max" t "max" "max" "max" "max")
+     ("min" "\\min" t "min" "min" "min" "min")
+     ("Pr" "\\Pr" t "Pr" "Pr" "Pr" "Pr")
+     ("sec" "\\sec" t "sec" "sec" "sec" "sec")
+     ("sin" "\\sin" t "sin" "sin" "sin" "sin")
+     ("sinh" "\\sinh" t "sinh" "sinh" "sinh" "sinh")
+     ("sup" "\\sup" t "&sup;" "sup" "sup" "sup")
+     ("tan" "\\tan" t "tan" "tan" "tan" "tan")
+     ("tanh" "\\tanh" t "tanh" "tanh" "tanh" "tanh")
+
+     "** Signs & Symbols"
+     ("bull" "\\textbullet{}" nil "&bull;" "*" "*" "•")
+     ("bullet" "\\textbullet{}" nil "&bull;" "*" "*" "•")
+     ("star" "\\star" t "*" "*" "*" "⋆")
+     ("lowast" "\\ast" t "&lowast;" "*" "*" "∗")
+     ("ast" "\\ast" t "&lowast;" "*" "*" "*")
+     ("odot" "\\odot" t "o" "[circled dot]" "[circled dot]" "ʘ")
+     ("oplus" "\\oplus" t "&oplus;" "[circled plus]" "[circled plus]" "⊕")
+     ("otimes" "\\otimes" t "&otimes;" "[circled times]" "[circled times]" "⊗")
+     ("check" "\\checkmark" t "&checkmark;" "[checkmark]" "[checkmark]" "✓")
+     ("checkmark" "\\checkmark" t "&check;" "[checkmark]" "[checkmark]" "✓")
+
+     "** Miscellaneous (seldom used)"
+     ("para" "\\P{}" nil "&para;" "[pilcrow]" "¶" "¶")
+     ("ordf" "\\textordfeminine{}" nil "&ordf;" "_a_" "ª" "ª")
+     ("ordm" "\\textordmasculine{}" nil "&ordm;" "_o_" "º" "º")
+     ("cedil" "\\c{}" nil "&cedil;" "[cedilla]" "¸" "¸")
+     ("oline" "\\overline{~}" t "&oline;" "[overline]" "¯" "‾")
+     ("uml" "\\textasciidieresis{}" nil "&uml;" "[diaeresis]" "¨" "¨")
+     ("zwnj" "\\/{}" nil "&zwnj;" "" "" "‌")
+     ("zwj" "" nil "&zwj;" "" "" "‍")
+     ("lrm" "" nil "&lrm;" "" "" "‎")
+     ("rlm" "" nil "&rlm;" "" "" "‏")
+
+     "** Smilies"
+     ("smiley" "\\ddot\\smile" t "&#9786;" ":-)" ":-)" "☺")
+     ("blacksmile" "\\ddot\\smile" t "&#9787;" ":-)" ":-)" "☻")
+     ("sad" "\\ddot\\frown" t "&#9785;" ":-(" ":-(" "☹")
+     ("frowny" "\\ddot\\frown" t "&#9785;" ":-(" ":-(" "☹")
+
+     "** Suits"
+     ("clubs" "\\clubsuit" t "&clubs;" "[clubs]" "[clubs]" "♣")
+     ("clubsuit" "\\clubsuit" t "&clubs;" "[clubs]" "[clubs]" "♣")
+     ("spades" "\\spadesuit" t "&spades;" "[spades]" "[spades]" "♠")
+     ("spadesuit" "\\spadesuit" t "&spades;" "[spades]" "[spades]" "♠")
+     ("hearts" "\\heartsuit" t "&hearts;" "[hearts]" "[hearts]" "♥")
+     ("heartsuit" "\\heartsuit" t "&heartsuit;" "[hearts]" "[hearts]" "♥")
+     ("diams" "\\diamondsuit" t "&diams;" "[diamonds]" "[diamonds]" "◆")
+     ("diamondsuit" "\\diamondsuit" t "&diams;" "[diamonds]" "[diamonds]" "◆")
+     ("diamond" "\\diamondsuit" t "&diamond;" "[diamond]" "[diamond]" "◆")
+     ("Diamond" "\\diamondsuit" t "&diamond;" "[diamond]" "[diamond]" "◆")
+     ("loz" "\\lozenge" t "&loz;" "[lozenge]" "[lozenge]" "⧫"))
+   ;; Add "\_ "-entity family for spaces.
+   (let (space-entities html-spaces (entity "_"))
+     (dolist (n (number-sequence 1 20) (nreverse space-entities))
+       (let ((spaces (make-string n ?\s)))
+        (push (list (setq entity (concat entity " "))
+                    (format "\\hspace*{%sem}" (* n .5))
+                    nil
+                    (setq html-spaces (concat "&ensp;" html-spaces))
+                    spaces
+                    spaces
+                    (make-string n ?\x2002))
+              space-entities)))))
+  "Default entities used in Org mode to produce special characters.
 For details see `org-entities-user'.")
 
 (defsubst org-entity-get (name)
@@ -518,52 +531,27 @@ This first checks the user list, then the built-in list."
   (or (assoc name org-entities-user)
       (assoc name org-entities)))
 
-(defun org-entity-get-representation (name kind)
-  "Get the correct representation of entity NAME for export type KIND.
-Kind can be any of `latex', `html', `ascii', `latin1', or `utf8'."
-  (let* ((e (org-entity-get name))
-        (n (cdr (assq kind '((latex . 1) (html . 3) (ascii . 4)
-                             (latin1 . 5) (utf8 . 6)))))
-        (r (and e n (nth n e))))
-    (if (and e r
-            (not org-entities-ascii-explanatory)
-            (memq kind '(ascii latin1 utf8))
-            (= (string-to-char r) ?\[))
-       (concat "\\" name)
-      r)))
-
-(defsubst org-entity-latex-math-p (name)
-  "Does entity NAME require math mode in LaTeX?"
-  (nth 2 (org-entity-get name)))
-
 ;; Helpfunctions to create a table for orgmode.org/worg/org-symbols.org
 
 (defun org-entities-create-table ()
   "Create an Org mode table with all entities."
   (interactive)
-  (let ((pos (point)) e latex mathp html latin utf8 name ascii)
+  (let ((pos (point)))
     (insert "|Name|LaTeX code|LaTeX|HTML code |HTML|ASCII|Latin1|UTF-8\n|-\n")
-    (mapc (lambda (e) (when (listp e)
-                       (setq name (car e)
-                             latex (nth 1 e)
-                             mathp (nth 2 e)
-                             html (nth 3 e)
-                             ascii (nth 4 e)
-                             latin (nth 5 e)
-                             utf8 (nth 6 e))
-                       (if (equal ascii "|") (setq ascii "\\vert"))
-                       (if (equal latin "|") (setq latin "\\vert"))
-                       (if (equal utf8  "|") (setq utf8  "\\vert"))
-                       (if (equal ascii "=>") (setq ascii "= >"))
-                       (if (equal latin "=>") (setq latin "= >"))
-                       (insert "|" name
-                               "|" (format "=%s=" latex)
-                               "|" (format (if mathp "$%s$" "$\\mbox{%s}$")
-                                           latex)
-                               "|" (format "=%s=" html) "|" html
-                               "|" ascii "|" latin "|" utf8
-                               "|\n")))
-         org-entities)
+    (dolist (e org-entities)
+      (pcase e
+       (`(,name ,latex ,mathp ,html ,ascii ,latin ,utf8)
+        (if (equal ascii "|") (setq ascii "\\vert"))
+        (if (equal latin "|") (setq latin "\\vert"))
+        (if (equal utf8  "|") (setq utf8  "\\vert"))
+        (if (equal ascii "=>") (setq ascii "= >"))
+        (if (equal latin "=>") (setq latin "= >"))
+        (insert "|" name
+                "|" (format "=%s=" latex)
+                "|" (format (if mathp "$%s$" "$\\mbox{%s}$") latex)
+                "|" (format "=%s=" html) "|" html
+                "|" ascii "|" latin "|" utf8
+                "|\n"))))
     (goto-char pos)
     (org-table-align)))
 
@@ -572,31 +560,27 @@ Kind can be any of `latex', `html', `ascii', `latin1', or 
`utf8'."
   "Create a Help buffer with all available entities."
   (interactive)
   (with-output-to-temp-buffer "*Org Entity Help*"
-    (princ "Org-mode entities\n=================\n\n")
+    (princ "Org mode entities\n=================\n\n")
     (let ((ll (append '("* User-defined additions (variable 
org-entities-user)")
                      org-entities-user
                      org-entities))
-         e latex mathp html latin utf8 name ascii
          (lastwasstring t)
          (head (concat
                 "\n"
                 "   Symbol   Org entity        LaTeX code             HTML 
code\n"
                 "   
-----------------------------------------------------------\n")))
-      (while ll
-       (setq e (pop ll))
-       (if (stringp e)
-           (progn
-             (princ e)
-             (princ "\n")
-             (setq lastwasstring t))
-         (if lastwasstring (princ head))
-         (setq lastwasstring nil)
-         (setq name (car e)
-               latex (nth 1 e)
-               html (nth 3 e)
-               utf8 (nth 6 e))
-         (princ (format "   %-8s \\%-16s %-22s %-13s\n"
-                        utf8 name latex html))))))
+      (dolist (e ll)
+       (pcase e
+         (`(,name ,latex ,_ ,html ,_ ,_ ,utf8)
+          (when lastwasstring
+            (princ head)
+            (setq lastwasstring nil))
+          (princ (format "   %-8s \\%-16s %-22s %-13s\n"
+                         utf8 name latex html)))
+         ((pred stringp)
+          (princ e)
+          (princ "\n")
+          (setq lastwasstring t))))))
   (with-current-buffer "*Org Entity Help*"
     (org-mode)
     (when org-pretty-entities
@@ -604,12 +588,6 @@ Kind can be any of `latex', `html', `ascii', `latin1', or 
`utf8'."
   (select-window (get-buffer-window "*Org Entity Help*")))
 
 
-(defun replace-amp ()
-  "Postprocess HTML file to unescape the ampersand."
-  (interactive)
-  (while (re-search-forward "<td>&amp;\\([^<;]+;\\)" nil t)
-    (replace-match (concat "<td>&" (match-string 1)) t t)))
-
 (provide 'org-entities)
 
 ;; Local variables:
diff --git a/lisp/org/org-eshell.el b/lisp/org/org-eshell.el
index 9eddd3f..34cc4ff 100644
--- a/lisp/org/org-eshell.el
+++ b/lisp/org/org-eshell.el
@@ -1,4 +1,4 @@
-;;; org-eshell.el - Support for links to working directories in eshell
+;;; org-eshell.el - Support for Links to Working Directories in Eshell -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -27,8 +27,9 @@
 (require 'eshell)
 (require 'esh-mode)
 
-(org-add-link-type "eshell" 'org-eshell-open)
-(add-hook 'org-store-link-functions 'org-eshell-store-link)
+(org-link-set-parameters "eshell"
+                        :follow #'org-eshell-open
+                        :store #'org-eshell-store-link)
 
 (defun org-eshell-open (link)
   "Switch to am eshell buffer and execute a command line.
@@ -43,7 +44,7 @@
          (eshell-buffer-name (car buffer-and-command))
          (command (cadr buffer-and-command)))
     (if (get-buffer eshell-buffer-name)
-       (org-pop-to-buffer-same-window eshell-buffer-name)
+       (pop-to-buffer-same-window eshell-buffer-name)
       (eshell))
     (goto-char (point-max))
     (eshell-kill-input)
diff --git a/lisp/org/org-eww.el b/lisp/org/org-eww.el
new file mode 100644
index 0000000..7bc248d
--- /dev/null
+++ b/lisp/org/org-eww.el
@@ -0,0 +1,175 @@
+;;; org-eww.el --- Store url and kill from Eww mode for Org  -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Marco Wahl <marcowahlsoft>a<gmailcom>
+;; Keywords: link, eww
+;; Homepage: http://orgmode.org
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+
+;; When this module is active `org-store-link' (often on key C-c l) in
+;; a eww buffer stores a link to the current url of the eww buffer.
+
+;; In an eww buffer function `org-eww-copy-for-org-mode' kills either
+;; a region or the whole buffer if no region is set and transforms the
+;; text on the fly so that it can be pasted into an Org buffer with
+;; hot links.
+
+;; C-c C-x C-w (and also C-c C-x M-w) trigger
+;; `org-eww-copy-for-org-mode'.
+
+;; Hint: A lot of code of this module comes from module org-w3m which
+;; has been written by Andy Steward based on the idea of Richard
+;; Riley.  Thanks!
+
+;; Potential: Since the code for w3m and eww is so similar one could
+;; try to refactor.
+
+
+;;; Code:
+(require 'org)
+(require 'cl-lib)
+
+(defvar eww-current-title)
+(defvar eww-current-url)
+(defvar eww-data)
+(defvar eww-mode-map)
+
+(declare-function eww-current-url "eww")
+
+
+;; Store Org-link in eww-mode buffer
+(org-link-set-parameters "eww" :follow #'eww :store #'org-eww-store-link)
+(defun org-eww-store-link ()
+  "Store a link to the url of a Eww buffer."
+  (when (eq major-mode 'eww-mode)
+    (org-store-link-props
+     :type "eww"
+     :link (if (< emacs-major-version 25)
+              eww-current-url
+            (eww-current-url))
+     :url (url-view-url t)
+     :description (if (< emacs-major-version 25)
+                     (or eww-current-title eww-current-url)
+                   (or (plist-get eww-data :title)
+                       (eww-current-url))))))
+
+
+;; Some auxiliary functions concerning links in eww buffers
+(defun org-eww-goto-next-url-property-change ()
+  "Move to the start of next link if exists.
+Otherwise point is not moved.  Return point."
+  (goto-char
+   (or (next-single-property-change (point) 'shr-url)
+       (point))))
+
+(defun org-eww-has-further-url-property-change-p ()
+  "Non-nil if there is a next url property change."
+  (save-excursion
+    (not (eq (point) (org-eww-goto-next-url-property-change)))))
+
+(defun org-eww-url-below-point ()
+  "Return the url below point if there is an url; otherwise, return nil."
+  (get-text-property (point) 'shr-url))
+
+
+(defun org-eww-copy-for-org-mode ()
+  "Copy current buffer content or active region with `org-mode' style links.
+This will encode `link-title' and `link-location' with
+`org-make-link-string', and insert the transformed test into the kill ring,
+so that it can be yanked into an Org mode buffer with links working correctly.
+
+Further lines starting with a star get quoted with a comma to keep
+the structure of the Org file."
+  (interactive)
+  (let* ((regionp (org-region-active-p))
+         (transform-start (point-min))
+         (transform-end (point-max))
+         return-content
+         link-location link-title
+         temp-position out-bound)
+    (when regionp
+      (setq transform-start (region-beginning))
+      (setq transform-end (region-end))
+      ;; Deactivate mark if current mark is activate.
+      (when (fboundp 'deactivate-mark) (deactivate-mark)))
+    (message "Transforming links...")
+    (save-excursion
+      (goto-char transform-start)
+      (while (and (not out-bound)      ; still inside region to copy
+                  (org-eww-has-further-url-property-change-p)) ; there is a 
next link
+        ;; Store current point before jump next anchor.
+        (setq temp-position (point))
+        ;; Move to next anchor when current point is not at anchor.
+        (or (org-eww-url-below-point)
+           (org-eww-goto-next-url-property-change))
+       (cl-assert
+        (org-eww-url-below-point) t
+        "program logic error: point must have an url below but it hasn't")
+       (if (<= (point) transform-end) ; if point is inside transform bound
+           (progn
+             ;; Get content between two links.
+             (when (< temp-position (point))
+               (setq return-content (concat return-content
+                                            (buffer-substring
+                                             temp-position (point)))))
+             ;; Get link location at current point.
+             (setq link-location (org-eww-url-below-point))
+             ;; Get link title at current point.
+             (setq link-title
+                   (buffer-substring
+                    (point)
+                    (org-eww-goto-next-url-property-change)))
+              ;; concat `org-mode' style url to `return-content'.
+             (setq return-content
+                   (concat return-content
+                           (if (stringp link-location)
+                               ;; hint: link-location is different for 
form-elements.
+                               (org-make-link-string link-location link-title)
+                             link-title))))
+         (goto-char temp-position) ; reset point before jump next anchor
+         (setq out-bound t)        ; for break out `while' loop
+         ))
+      ;; Add the rest until end of the region to be copied.
+      (when (< (point) transform-end)
+       (setq return-content
+             (concat return-content
+                     (buffer-substring (point) transform-end))))
+      ;; Quote lines starting with *.
+      (org-kill-new (replace-regexp-in-string "^\\*" ",*" return-content))
+      (message "Transforming links...done, use C-y to insert text into Org 
mode file"))))
+
+
+;; Additional keys for eww-mode
+
+(defun org-eww-extend-eww-keymap ()
+  (define-key eww-mode-map "\C-c\C-x\M-w" 'org-eww-copy-for-org-mode)
+  (define-key eww-mode-map "\C-c\C-x\C-w" 'org-eww-copy-for-org-mode))
+
+(when (and (boundp 'eww-mode-map)
+           (keymapp eww-mode-map)) ; eww is already up.
+  (org-eww-extend-eww-keymap))
+
+(add-hook 'eww-mode-hook #'org-eww-extend-eww-keymap)
+
+
+(provide 'org-eww)
+
+;;; org-eww.el ends here
diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el
index c340aca..cd43d37 100644
--- a/lisp/org/org-faces.el
+++ b/lisp/org/org-faces.el
@@ -1,4 +1,4 @@
-;;; org-faces.el --- Face definitions for Org-mode.
+;;; org-faces.el --- Face definitions -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -28,32 +28,12 @@
 
 ;;; Code:
 
-(require 'org-macs)
-(require 'org-compat)
-
-(defun org-copy-face (old-face new-face docstring &rest attributes)
-  (unless (facep new-face)
-    (if (fboundp 'set-face-attribute)
-       (progn
-         (make-face new-face)
-         (set-face-attribute new-face nil :inherit old-face)
-         (apply 'set-face-attribute new-face nil attributes)
-         (set-face-doc-string new-face docstring))
-      (copy-face old-face new-face)
-      (if (fboundp 'set-face-doc-string)
-         (set-face-doc-string new-face docstring)))))
-(put 'org-copy-face 'lisp-indent-function 2)
-
-(when (featurep 'xemacs)
-  (put 'mode-line 'face-alias 'modeline))
-
 (defgroup org-faces nil
-  "Faces in Org-mode."
+  "Faces in Org mode."
   :tag "Org Faces"
   :group 'org-appearance)
 
-(defface org-default
-  (org-compatible-face 'default nil)
+(defface org-default '((t :inherit default))
   "Face used for default text."
   :group 'org-faces)
 
@@ -65,99 +45,49 @@ The foreground color of this face should be equal to the 
background
 color of the frame."
   :group 'org-faces)
 
-(defface org-level-1 ;; originally copied from font-lock-function-name-face
-  (org-compatible-face 'outline-1
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Blue1"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 8)) (:foreground "blue" :bold t))
-      (t (:bold t))))
+(defface org-level-1 '((t :inherit outline-1))
   "Face used for level 1 headlines."
   :group 'org-faces)
 
-(defface org-level-2 ;; originally copied from font-lock-variable-name-face
-  (org-compatible-face 'outline-2
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"DarkGoldenrod"))
-      (((class color) (min-colors 16) (background dark))  (:foreground 
"LightGoldenrod"))
-      (((class color) (min-colors 8)  (background light)) (:foreground 
"yellow"))
-      (((class color) (min-colors 8)  (background dark))  (:foreground 
"yellow" :bold t))
-      (t (:bold t))))
+(defface org-level-2 '((t :inherit outline-2))
   "Face used for level 2 headlines."
   :group 'org-faces)
 
-(defface org-level-3 ;; originally copied from font-lock-keyword-face
-  (org-compatible-face 'outline-3
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Purple"))
-      (((class color) (min-colors 88) (background dark))  (:foreground 
"Cyan1"))
-      (((class color) (min-colors 16) (background light)) (:foreground 
"Purple"))
-      (((class color) (min-colors 16) (background dark))  (:foreground "Cyan"))
-      (((class color) (min-colors 8)  (background light)) (:foreground 
"purple" :bold t))
-      (((class color) (min-colors 8)  (background dark))  (:foreground "cyan" 
:bold t))
-      (t (:bold t))))
+(defface org-level-3 '((t :inherit outline-3))
   "Face used for level 3 headlines."
   :group 'org-faces)
 
-(defface org-level-4   ;; originally copied from font-lock-comment-face
-  (org-compatible-face 'outline-4
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
-      (((class color) (min-colors 88) (background dark))  (:foreground 
"chocolate1"))
-      (((class color) (min-colors 16) (background light)) (:foreground "red"))
-      (((class color) (min-colors 16) (background dark))  (:foreground "red1"))
-      (((class color) (min-colors 8) (background light))  (:foreground "red" 
:bold t))
-      (((class color) (min-colors 8) (background dark))   (:foreground "red" 
:bold t))
-      (t (:bold t))))
+(defface org-level-4 '((t :inherit outline-4))
   "Face used for level 4 headlines."
   :group 'org-faces)
 
-(defface org-level-5 ;; originally copied from font-lock-type-face
-  (org-compatible-face 'outline-5
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"ForestGreen"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"PaleGreen"))
-      (((class color) (min-colors 8)) (:foreground "green"))))
+(defface org-level-5 '((t :inherit outline-5))
   "Face used for level 5 headlines."
   :group 'org-faces)
 
-(defface org-level-6 ;; originally copied from font-lock-constant-face
-  (org-compatible-face 'outline-6
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"CadetBlue"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"Aquamarine"))
-      (((class color) (min-colors 8)) (:foreground "magenta"))))
+(defface org-level-6 '((t :inherit outline-6))
   "Face used for level 6 headlines."
   :group 'org-faces)
 
-(defface org-level-7 ;; originally copied from font-lock-builtin-face
-  (org-compatible-face 'outline-7
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"Orchid"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSteelBlue"))
-      (((class color) (min-colors 8)) (:foreground "blue"))))
+(defface org-level-7 '((t :inherit outline-7))
   "Face used for level 7 headlines."
   :group 'org-faces)
 
-(defface org-level-8 ;; originally copied from font-lock-string-face
-  (org-compatible-face 'outline-8
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"RosyBrown"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSalmon"))
-      (((class color) (min-colors 8)) (:foreground "green"))))
+(defface org-level-8 '((t :inherit outline-8))
   "Face used for level 8 headlines."
   :group 'org-faces)
 
-(defface org-special-keyword ;; originally copied from font-lock-string-face
-  (org-compatible-face 'font-lock-keyword-face
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"RosyBrown"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSalmon"))
-      (t (:italic t))))
+(defface org-special-keyword '((t :inherit font-lock-keyword-face))
   "Face used for special keywords."
   :group 'org-faces)
 
-(defface org-drawer ;; originally copied from font-lock-function-name-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Blue1"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 8)) (:foreground "blue" :bold t))
-      (t (:bold t))))
+(defface org-drawer       ;Copied from `font-lock-function-name-face'
+  '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 8)) (:foreground "blue" :bold t))
+    (t (:bold t)))
   "Face used for drawers."
   :group 'org-faces)
 
@@ -166,18 +96,17 @@ color of the frame."
   :group 'org-faces)
 
 (defface org-column
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light))
-       (:background "grey90" :weight normal :slant normal :strike-through nil
-                   :underline nil))
-      (((class color) (min-colors 16) (background dark))
-       (:background "grey30" :weight normal :slant normal :strike-through nil
-                   :underline nil))
-      (((class color) (min-colors 8))
-       (:background "cyan" :foreground "black"
-                   :weight normal :slant normal :strike-through nil
-                   :underline nil))
-      (t (:inverse-video t))))
+  '((((class color) (min-colors 16) (background light))
+     (:background "grey90" :weight normal :slant normal :strike-through nil
+                 :underline nil))
+    (((class color) (min-colors 16) (background dark))
+     (:background "grey30" :weight normal :slant normal :strike-through nil
+                 :underline nil))
+    (((class color) (min-colors 8))
+     (:background "cyan" :foreground "black"
+                 :weight normal :slant normal :strike-through nil
+                 :underline nil))
+    (t (:inverse-video t)))
   "Face for column display of entry properties.
 This is actually only part of the face definition for the text in column view.
 The following faces apply, with this priority.
@@ -198,59 +127,33 @@ character (this might for example be the a TODO keyword) 
might still
 shine through in some properties.  So when your column view looks
 funny, with \"random\" colors, weight, strike-through, try to explicitly
 set the properties in the `org-column' face.  For example, set
-:underline to nil, or the :slant to `normal'.
-
-Under XEmacs, the rules are simpler, because the XEmacs version of
-column view defines special faces for each outline level.  See the file
-`org-colview-xemacs.el' in Org's contrib/ directory for details."
+:underline to nil, or the :slant to `normal'."
   :group 'org-faces)
 
 (defface org-column-title
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light))
-       (:background "grey90" :underline t :weight bold))
-      (((class color) (min-colors 16) (background dark))
-       (:background "grey30" :underline t :weight bold))
-      (((class color) (min-colors 8))
-       (:background "cyan" :foreground "black" :underline t :weight bold))
-      (t (:inverse-video t))))
+  '((((class color) (min-colors 16) (background light))
+     (:background "grey90" :underline t :weight bold))
+    (((class color) (min-colors 16) (background dark))
+     (:background "grey30" :underline t :weight bold))
+    (((class color) (min-colors 8))
+     (:background "cyan" :foreground "black" :underline t :weight bold))
+    (t (:inverse-video t)))
   "Face for column display of entry properties."
   :group 'org-faces)
 
-(defface org-agenda-column-dateline
-  (org-compatible-face 'org-column
-    '((t nil)))
+(defface org-agenda-column-dateline '((t :inherit org-column))
   "Face used in agenda column view for datelines with summaries."
   :group 'org-faces)
 
-(defface org-warning
-  (org-compatible-face 'font-lock-warning-face
-    '((((class color) (min-colors 16) (background light)) (:foreground "Red1" 
:bold t))
-      (((class color) (min-colors 16) (background dark))  (:foreground "Pink" 
:bold t))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"  
:bold t))
-      (((class color) (min-colors 8)  (background dark))  (:foreground "red"  
:bold t))
-      (t (:bold t))))
+(defface org-warning '((t :inherit font-lock-warning-face))
   "Face for deadlines and TODO keywords."
   :group 'org-faces)
 
-(defface org-archived    ; similar to shadow
-  (org-compatible-face 'shadow
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey50"))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey70"))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green"))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow"))))
+(defface org-archived '((t :inherit shadow))
   "Face for headline with the ARCHIVE tag."
   :group 'org-faces)
 
-(defface org-link
-  (org-compatible-face 'link
-    '((((class color) (background light)) (:foreground "Purple" :underline t))
-      (((class color) (background dark)) (:foreground "Cyan" :underline t))
-      (t (:underline t))))
+(defface org-link '((t :inherit link))
   "Face for links."
   :group 'org-faces)
 
@@ -283,12 +186,11 @@ column view defines special faces for each outline level. 
 See the file
   :group 'org-faces)
 
 (defface org-date-selected
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground "Red1" 
:inverse-video t))
-      (((class color) (min-colors 16) (background dark))  (:foreground "Pink" 
:inverse-video t))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"  
:inverse-video t))
-      (((class color) (min-colors 8)  (background dark))  (:foreground "red"  
:inverse-video t))
-      (t (:inverse-video t))))
+  '((((class color) (min-colors 16) (background light)) (:foreground "Red1" 
:inverse-video t))
+    (((class color) (min-colors 16) (background dark))  (:foreground "Pink" 
:inverse-video t))
+    (((class color) (min-colors 8)  (background light)) (:foreground "red"  
:inverse-video t))
+    (((class color) (min-colors 8)  (background dark))  (:foreground "red"  
:inverse-video t))
+    (t (:inverse-video t)))
   "Face for highlighting the calendar day when using `org-read-date'.
 Using a bold face here might cause discrepancies while displaying the
 calendar."
@@ -301,43 +203,38 @@ calendar."
   "Face for diary-like sexp date specifications."
   :group 'org-faces)
 
-(defface org-tag
-  '((t (:bold t)))
+(defface org-tag '((t (:bold t)))
   "Default face for tags.
 Note that the variable `org-tag-faces' can be used to overrule this face for
 specific tags."
   :group 'org-faces)
 
-(defface org-list-dt
-  '((t (:bold t)))
+(defface org-list-dt '((t (:bold t)))
   "Default face for definition terms in lists."
   :group 'org-faces)
 
-(defface org-todo ; font-lock-warning-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground "Red1" 
:bold t))
-      (((class color) (min-colors 16) (background dark))  (:foreground "Pink" 
:bold t))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"  
:bold t))
-      (((class color) (min-colors 8)  (background dark))  (:foreground "red"  
:bold t))
-      (t (:inverse-video t :bold t))))
+(defface org-todo               ;Copied from `font-lock-warning-face'
+  '((((class color) (min-colors 16) (background light)) (:foreground "Red1" 
:bold t))
+    (((class color) (min-colors 16) (background dark))  (:foreground "Pink" 
:bold t))
+    (((class color) (min-colors 8)  (background light)) (:foreground "red"  
:bold t))
+    (((class color) (min-colors 8)  (background dark))  (:foreground "red"  
:bold t))
+    (t (:inverse-video t :bold t)))
   "Face for TODO keywords."
   :group 'org-faces)
 
-(defface org-done ;; originally copied from font-lock-type-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"ForestGreen" :bold t))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"PaleGreen" :bold t))
-      (((class color) (min-colors 8)) (:foreground "green"))
-      (t (:bold t))))
+(defface org-done                  ;Copied from `font-lock-type-face'
+  '((((class color) (min-colors 16) (background light)) (:foreground 
"ForestGreen" :bold t))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"PaleGreen" :bold t))
+    (((class color) (min-colors 8)) (:foreground "green"))
+    (t (:bold t)))
   "Face used for todo keywords that indicate DONE items."
   :group 'org-faces)
 
-(defface org-agenda-done ;; originally copied from font-lock-type-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"ForestGreen"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"PaleGreen"))
-      (((class color) (min-colors 8)) (:foreground "green"))
-      (t (:bold nil))))
+(defface org-agenda-done           ;Copied from `font-lock-type-face'
+  '((((class color) (min-colors 16) (background light)) (:foreground 
"ForestGreen"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"PaleGreen"))
+    (((class color) (min-colors 8)) (:foreground "green"))
+    (t (:bold nil)))
   "Face used in agenda, to indicate lines switched to DONE.
 This face is used to de-emphasize items that where brightly colored in the
 agenda because they were things to do, or overdue.  The DONE state itself
@@ -346,11 +243,10 @@ is of course immediately visible, but for example a 
passed deadline is
 of the frame, for example."
   :group 'org-faces)
 
-(defface org-headline-done ;; originally copied from font-lock-string-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"RosyBrown"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSalmon"))
-      (((class color) (min-colors 8)  (background light)) (:bold nil))))
+(defface org-headline-done       ;Copied from `font-lock-string-face'
+  '((((class color) (min-colors 16) (background light)) (:foreground 
"RosyBrown"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSalmon"))
+    (((class color) (min-colors 8)  (background light)) (:bold nil)))
   "Face used to indicate that a headline is DONE.
 This face is only used if `org-fontify-done-headline' is set.  If applies
 to the part of the headline after the DONE keyword."
@@ -388,11 +284,7 @@ determines if it is a foreground or a background color."
                   (string :tag "Color")
                   (sexp :tag "Face")))))
 
-(defface org-priority ;; originally copied from font-lock-string-face
-  (org-compatible-face 'font-lock-keyword-face
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"RosyBrown"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSalmon"))
-      (t (:italic t))))
+(defface org-priority '((t :inherit font-lock-keyword-face))
   "Face used for priority cookies."
   :group 'org-faces)
 
@@ -421,18 +313,17 @@ determines if it is a foreground or a background color."
     (setq org-tags-special-faces-re
          (concat ":\\(" (mapconcat 'car value "\\|") "\\):"))))
 
-(defface org-checkbox
-  (org-compatible-face 'bold
-    '((t (:bold t))))
+(defface org-checkbox '((t :inherit bold))
   "Face for checkboxes."
   :group 'org-faces)
 
+(defface org-checkbox-statistics-todo '((t (:inherit org-todo)))
+  "Face used for unfinished checkbox statistics."
+  :group 'org-faces)
 
-(org-copy-face 'org-todo 'org-checkbox-statistics-todo
-  "Face used for unfinished checkbox statistics.")
-
-(org-copy-face 'org-done 'org-checkbox-statistics-done
-  "Face used for finished checkbox statistics.")
+(defface org-checkbox-statistics-done '((t (:inherit org-done)))
+  "Face used for finished checkbox statistics."
+  :group 'org-faces)
 
 (defcustom org-tag-faces nil
   "Faces for specific tags.
@@ -454,44 +345,32 @@ changes."
                   (string :tag "Foreground color")
                   (sexp :tag "Face")))))
 
-(defface org-table ;; originally copied from font-lock-function-name-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Blue1"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 8)  (background light)) (:foreground "blue"))
-      (((class color) (min-colors 8)  (background dark)))))
+(defface org-table        ;Copied from `font-lock-function-name-face'
+  '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 8)  (background light)) (:foreground "blue"))
+    (((class color) (min-colors 8)  (background dark))))
   "Face used for tables."
   :group 'org-faces)
 
 (defface org-formula
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"))
-      (((class color) (min-colors 8)  (background dark)) (:foreground "red"))
-      (t (:bold t :italic t))))
+  '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
+    (((class color) (min-colors 8)  (background light)) (:foreground "red"))
+    (((class color) (min-colors 8)  (background dark)) (:foreground "red"))
+    (t (:bold t :italic t)))
   "Face for formulas."
   :group 'org-faces)
 
-(defface org-code
-  (org-compatible-face 'shadow
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey50"))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey70"))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green"))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow"))))
+(defface org-code '((t :inherit shadow))
   "Face for fixed-width text like code snippets."
   :group 'org-faces
   :version "22.1")
 
-(defface org-meta-line
-  (org-compatible-face 'font-lock-comment-face nil)
-  "Face for meta lines startin with \"#+\"."
+(defface org-meta-line '((t :inherit font-lock-comment-face))
+  "Face for meta lines starting with \"#+\"."
   :group 'org-faces
   :version "22.1")
 
@@ -510,60 +389,37 @@ changes."
 follows a #+DATE:, #+AUTHOR: or #+EMAIL: keyword."
   :group 'org-faces)
 
-(defface org-document-info-keyword
-  (org-compatible-face 'shadow
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey50"))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey70"))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green"))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow"))))
+(defface org-document-info-keyword '((t :inherit shadow))
   "Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords."
   :group 'org-faces)
 
-(defface org-block
-  (org-compatible-face 'shadow
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey50"))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey70"))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green"))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow"))))
-  "Face text in #+begin ... #+end blocks."
+(defface org-block '((t :inherit shadow))
+  "Face text in #+begin ... #+end blocks.
+For source-blocks `org-src-block-faces' takes precedence.
+See also `org-fontify-quote-and-verse-blocks'."
   :group 'org-faces
-  :version "22.1")
+  :version "26.1")
 
-(defface org-block-background '((t ()))
-  "Face used for the source block background.")
-
-(org-copy-face 'org-meta-line 'org-block-begin-line
-  "Face used for the line delimiting the begin of source blocks.")
-
-(org-copy-face 'org-meta-line 'org-block-end-line
-  "Face used for the line delimiting the end of source blocks.")
-
-(defface org-verbatim
-  (org-compatible-face 'shadow
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey50" :underline t))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey70" :underline t))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green" :underline t))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow" :underline t))))
-  "Face for fixed-with text like code snippets."
+(defface org-block-begin-line '((t (:inherit org-meta-line)))
+  "Face used for the line delimiting the begin of source blocks."
+  :group 'org-faces)
+
+(defface org-block-end-line '((t (:inherit org-block-begin-line)))
+  "Face used for the line delimiting the end of source blocks."
+  :group 'org-faces)
+
+(defface org-verbatim '((t (:inherit shadow)))
+  "Face for fixed-with text like code snippets"
   :group 'org-faces
   :version "22.1")
 
-(org-copy-face 'org-block 'org-quote
-  "Face for #+BEGIN_QUOTE ... #+END_QUOTE blocks.")
-(org-copy-face 'org-block 'org-verse
-  "Face for #+BEGIN_VERSE ... #+END_VERSE blocks.")
+(defface org-quote '((t (:inherit org-block)))
+  "Face for #+BEGIN_QUOTE ... #+END_QUOTE blocks."
+  :group 'org-faces)
+
+(defface org-verse '((t (:inherit org-block)))
+  "Face for #+BEGIN_VERSE ... #+END_VERSE blocks."
+  :group 'org-faces)
 
 (defcustom org-fontify-quote-and-verse-blocks nil
   "Non-nil means, add a special face to #+begin_quote and #+begin_verse block.
@@ -573,64 +429,64 @@ content of these blocks will still be treated as Org 
syntax."
   :version "24.1"
   :type 'boolean)
 
-(defface org-clock-overlay ;; copied from secondary-selection
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light))
-       (:background "yellow1"))
-      (((class color) (min-colors 88) (background dark))
-       (:background "SkyBlue4"))
-      (((class color) (min-colors 16) (background light))
-       (:background "yellow"))
-      (((class color) (min-colors 16) (background dark))
-       (:background "SkyBlue4"))
-      (((class color) (min-colors 8))
-       (:background "cyan" :foreground "black"))
-      (t (:inverse-video t))))
+(defface org-clock-overlay         ;Copied from `secondary-selection'
+  '((((class color) (min-colors 88) (background light))
+     (:background "LightGray" :foreground "black"))
+    (((class color) (min-colors 88) (background dark))
+     (:background "SkyBlue4" :foreground "white"))
+    (((class color) (min-colors 16) (background light))
+     (:background "gray" :foreground "black"))
+    (((class color) (min-colors 16) (background dark))
+     (:background "SkyBlue4" :foreground "white"))
+    (((class color) (min-colors 8))
+     (:background "cyan" :foreground "black"))
+    (t (:inverse-video t)))
   "Basic face for displaying the secondary selection."
   :group 'org-faces)
 
-(defface org-agenda-structure ;; originally copied from 
font-lock-function-name-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Blue1"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
-      (((class color) (min-colors 8)) (:foreground "blue" :bold t))
-      (t (:bold t))))
+(defface org-agenda-structure ;Copied from `font-lock-function-name-face'
+  '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"LightSkyBlue"))
+    (((class color) (min-colors 8)) (:foreground "blue" :bold t))
+    (t (:bold t)))
   "Face used in agenda for captions and dates."
   :group 'org-faces)
 
-(org-copy-face 'org-agenda-structure 'org-agenda-date
-  "Face used in agenda for normal days.")
+(defface org-agenda-date '((t (:inherit org-agenda-structure)))
+  "Face used in agenda for normal days."
+  :group 'org-faces)
 
-(org-copy-face 'org-agenda-date 'org-agenda-date-today
+(defface org-agenda-date-today
+  '((t (:inherit org-agenda-date :weight bold :italic t)))
   "Face used in agenda for today."
-  :weight 'bold :italic 't)
+  :group 'org-faces)
 
-(org-copy-face 'secondary-selection 'org-agenda-clocking
-  "Face marking the current clock item in the agenda.")
+(defface org-agenda-clocking '((t (:inherit secondary-selection)))
+  "Face marking the current clock item in the agenda."
+  :group 'org-faces)
 
-(org-copy-face 'org-agenda-date 'org-agenda-date-weekend
+(defface org-agenda-date-weekend '((t (:inherit org-agenda-date :weight bold)))
   "Face used in agenda for weekend days.
-See the variable `org-agenda-weekend-days' for a definition of which days
-belong to the weekend."
-  :weight 'bold)
+
+See the variable `org-agenda-weekend-days' for a definition of
+which days belong to the weekend."
+  :group 'org-faces)
 
 (defface org-scheduled
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"DarkGreen"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"PaleGreen"))
-      (((class color) (min-colors 8)) (:foreground "green"))
-      (t (:bold t :italic t))))
+  '((((class color) (min-colors 88) (background light)) (:foreground 
"DarkGreen"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"PaleGreen"))
+    (((class color) (min-colors 8)) (:foreground "green"))
+    (t (:bold t :italic t)))
   "Face for items scheduled for a certain day."
   :group 'org-faces)
 
 (defface org-scheduled-today
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"DarkGreen"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"PaleGreen"))
-      (((class color) (min-colors 8)) (:foreground "green"))
-      (t (:bold t :italic t))))
+  '((((class color) (min-colors 88) (background light)) (:foreground 
"DarkGreen"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"PaleGreen"))
+    (((class color) (min-colors 8)) (:foreground "green"))
+    (t (:bold t :italic t)))
   "Face for items scheduled for a certain day."
   :group 'org-faces)
 
@@ -641,22 +497,20 @@ belong to the weekend."
   :group 'org-faces)
 
 (defface org-scheduled-previously
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"))
-      (((class color) (min-colors 8)  (background dark)) (:foreground "red" 
:bold t))
-      (t (:bold t))))
+  '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
+    (((class color) (min-colors 8)  (background light)) (:foreground "red"))
+    (((class color) (min-colors 8)  (background dark)) (:foreground "red" 
:bold t))
+    (t (:bold t)))
   "Face for items scheduled previously, and not yet done."
   :group 'org-faces)
 
 (defface org-upcoming-deadline
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
-      (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
-      (((class color) (min-colors 8)  (background light)) (:foreground "red"))
-      (((class color) (min-colors 8)  (background dark)) (:foreground "red" 
:bold t))
-      (t (:bold t))))
+  '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
+    (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
+    (((class color) (min-colors 8)  (background light)) (:foreground "red"))
+    (((class color) (min-colors 8)  (background dark)) (:foreground "red" 
:bold t))
+    (t (:bold t)))
   "Face for items scheduled previously, and not yet done."
   :group 'org-faces)
 
@@ -666,7 +520,7 @@ belong to the weekend."
     (0.0 . default))
   "Faces for showing deadlines in the agenda.
 This is a list of cons cells.  The cdr of each cell is a face to be used,
-and it can also just be like (:foreground \"yellow\").
+and it can also just be like \\='(:foreground \"yellow\").
 Each car is a fraction of the head-warning time that must have passed for
 this the face in the cdr to be used for display.  The numbers must be
 given in descending order.  The head-warning time is normally taken
@@ -686,65 +540,61 @@ month and 365.24 days for a year)."
           (sexp :tag "Face"))))
 
 (defface org-agenda-restriction-lock
-  (org-compatible-face nil
-    '((((class color) (min-colors 88) (background light)) (:background 
"#eeeeee"))
-      (((class color) (min-colors 88) (background dark))  (:background 
"#1C1C1C"))
-      (((class color) (min-colors 16) (background light)) (:background 
"#eeeeee"))
-      (((class color) (min-colors 16) (background dark))  (:background 
"#1C1C1C"))
-      (((class color) (min-colors 8)) (:background "cyan" :foreground "black"))
-      (t (:inverse-video t))))
+  '((((class color) (min-colors 88) (background light)) (:background 
"#eeeeee"))
+    (((class color) (min-colors 88) (background dark))  (:background 
"#1C1C1C"))
+    (((class color) (min-colors 16) (background light)) (:background 
"#eeeeee"))
+    (((class color) (min-colors 16) (background dark))  (:background 
"#1C1C1C"))
+    (((class color) (min-colors 8)) (:background "cyan" :foreground "black"))
+    (t (:inverse-video t)))
   "Face for showing the agenda restriction lock."
   :group 'org-faces)
 
-(defface org-agenda-filter-tags
-  (org-compatible-face 'mode-line nil)
+(defface org-agenda-filter-tags '((t :inherit mode-line))
   "Face for tag(s) in the mode-line when filtering the agenda."
   :group 'org-faces)
 
-(defface org-agenda-filter-regexp
-  (org-compatible-face 'mode-line nil)
+(defface org-agenda-filter-regexp '((t :inherit mode-line))
   "Face for regexp(s) in the mode-line when filtering the agenda."
   :group 'org-faces)
 
-(defface org-agenda-filter-category
-  (org-compatible-face 'mode-line nil)
-  "Face for categories(s) in the mode-line when filtering the agenda."
+(defface org-agenda-filter-category '((t :inherit mode-line))
+  "Face for categories in the mode-line when filtering the agenda."
   :group 'org-faces)
 
-(defface org-time-grid ;; originally copied from font-lock-variable-name-face
-  (org-compatible-face nil
-    '((((class color) (min-colors 16) (background light)) (:foreground 
"DarkGoldenrod"))
-      (((class color) (min-colors 16) (background dark)) (:foreground 
"LightGoldenrod"))
-      (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
+(defface org-agenda-filter-effort '((t :inherit mode-line))
+  "Face for effort in the mode-line when filtering the agenda."
+  :group 'org-faces)
+
+(defface org-time-grid    ;Copied from `font-lock-variable-name-face'
+  '((((class color) (min-colors 16) (background light)) (:foreground 
"DarkGoldenrod"))
+    (((class color) (min-colors 16) (background dark)) (:foreground 
"LightGoldenrod"))
+    (((class color) (min-colors 8)) (:foreground "yellow" :weight light)))
   "Face used for time grids."
   :group 'org-faces)
 
-(org-copy-face 'org-time-grid 'org-agenda-current-time
-  "Face used to show the current time in the time grid.")
+(defface org-agenda-current-time '((t (:inherit org-time-grid)))
+  "Face used to show the current time in the time grid."
+  :group 'org-faces)
 
-(defface org-agenda-diary
-  (org-compatible-face 'default nil)
+(defface org-agenda-diary '((t :inherit default))
   "Face used for agenda entries that come from the Emacs diary."
   :group 'org-faces)
 
-(defface org-agenda-calendar-event
-  (org-compatible-face 'default nil)
+(defface org-agenda-calendar-event '((t :inherit default))
   "Face used to show events and appointments in the agenda."
   :group 'org-faces)
 
-(defface org-agenda-calendar-sexp
-  (org-compatible-face 'default nil)
+(defface org-agenda-calendar-sexp '((t :inherit default))
   "Face used to show events computed from a S-expression."
   :group 'org-faces)
 
 (defconst org-level-faces
   '(org-level-1 org-level-2 org-level-3 org-level-4
-               org-level-5 org-level-6 org-level-7 org-level-8
-               ))
+               org-level-5 org-level-6 org-level-7 org-level-8))
 
 (defcustom org-n-level-faces (length org-level-faces)
   "The number of different faces to be used for headlines.
-Org-mode defines 8 different headline faces, so this can be at most 8.
+Org mode defines 8 different headline faces, so this can be at most 8.
 If it is less than 8, the level-1 face gets re-used for level N+1 etc."
   :type 'integer
   :group 'org-faces)
@@ -777,25 +627,26 @@ level org-n-level-faces"
   :version "24.4"
   :package-version '(Org . "8.0"))
 
-(defface org-macro
-  (org-compatible-face 'org-latex-and-related nil)
+(defface org-macro '((t :inherit org-latex-and-related))
   "Face for macros."
   :group 'org-faces
   :version "24.4"
   :package-version '(Org . "8.0"))
 
-(defface org-tag-group
-  (org-compatible-face 'org-tag nil)
+(defface org-tag-group '((t :inherit org-tag))
   "Face for group tags."
   :group 'org-faces
   :version "24.4"
   :package-version '(Org . "8.0"))
 
-(org-copy-face 'mode-line 'org-mode-line-clock
-  "Face used for clock display in mode line.")
-(org-copy-face 'mode-line 'org-mode-line-clock-overrun
+(defface org-mode-line-clock '((t (:inherit mode-line)))
+  "Face used for clock display in mode line."
+  :group 'org-faces)
+
+(defface org-mode-line-clock-overrun
+  '((t (:inherit mode-line :background "red")))
   "Face used for clock display for overrun tasks in mode line."
-  :background "red")
+  :group 'org-faces)
 
 (provide 'org-faces)
 
diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el
index cfb4b4f..6ebe5ec 100644
--- a/lisp/org/org-feed.el
+++ b/lisp/org/org-feed.el
@@ -1,4 +1,4 @@
-;;; org-feed.el --- Add RSS feed items to Org files
+;;; org-feed.el --- Add RSS feed items to Org files  -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 ;;
@@ -24,11 +24,11 @@
 ;;
 ;;; Commentary:
 ;;
-;;  This module allows entries to be created and changed in an Org-mode
-;;  file triggered by items in an RSS feed.  The basic functionality is
-;;  geared toward simply adding new items found in a feed as outline nodes
-;;  to an Org file.  Using hooks, arbitrary actions can be triggered for
-;;  new or changed items.
+;;  This module allows entries to be created and changed in an Org mode
+;;  file triggered by items in an RSS feed.  The basic functionality
+;;  is geared toward simply adding new items found in a feed as
+;;  outline nodes to an Org file.  Using hooks, arbitrary actions can
+;;  be triggered for new or changed items.
 ;;
 ;;  Selecting feeds and target locations
 ;;  ------------------------------------
@@ -77,10 +77,8 @@
 ;;  org-feed.el needs to keep track of which feed items have been handled
 ;;  before, so that they will not be handled again.  For this, org-feed.el
 ;;  stores information in a special drawer, FEEDSTATUS, under the heading
-;;  that received the input of the feed.  You should add FEEDSTATUS
-;;  to your list of drawers in the files that receive feed input:
+;;  that received the input of the feed.
 ;;
-;;       #+DRAWERS: PROPERTIES CLOCK LOGBOOK RESULTS FEEDSTATUS
 ;;
 ;;  Acknowledgments
 ;;  ---------------
@@ -102,8 +100,8 @@
 (declare-function xml-substitute-special "xml" (string))
 
 (declare-function org-capture-escaped-% "org-capture" ())
+(declare-function org-capture-expand-embedded-elisp "org-capture" (&optional 
mark))
 (declare-function org-capture-inside-embedded-elisp-p "org-capture" ())
-(declare-function org-capture-expand-embedded-elisp "org-capture" ())
 
 (defgroup org-feed  nil
   "Options concerning RSS feeds as inputs for Org files."
@@ -117,7 +115,9 @@ to create inbox items in Org.  Each entry is a list with 
the following items:
 
 name         a custom name for this feed
 URL          the Feed URL
-file         the target Org file where entries should be listed
+file         the target Org file where entries should be listed, when
+             nil the target becomes the current buffer (may be an
+             indirect buffer) each time the feed update is invoked
 headline     the headline under which entries should be listed
 
 Additional arguments can be given using keyword-value pairs.  Many of these
@@ -216,10 +216,7 @@ Here are the keyword-value pair allows in `org-feed-alist'.
 (defcustom org-feed-drawer "FEEDSTATUS"
   "The name of the drawer for feed status information.
 Each feed may also specify its own drawer name using the `:drawer'
-parameter in `org-feed-alist'.
-Note that in order to make these drawers behave like drawers, they must
-be added to the variable `org-drawers' or configured with a #+DRAWERS
-line."
+parameter in `org-feed-alist'."
   :group 'org-feed
   :type '(string :tag "Drawer Name"))
 
@@ -300,7 +297,8 @@ it can be a list structured like an entry in 
`org-feed-alist'."
   (catch 'exit
     (let ((name (car feed))
          (url (nth 1 feed))
-         (file (nth 2 feed))
+         (file (or (nth 2 feed) (buffer-file-name (or (buffer-base-buffer)
+                                                      (current-buffer)))))
          (headline (nth 3 feed))
          (filter (nth 1 (memq :filter feed)))
          (formatter (nth 1 (memq :formatter feed)))
@@ -315,7 +313,7 @@ it can be a list structured like an entry in 
`org-feed-alist'."
          (parse-entry (or (nth 1 (memq :parse-entry feed))
                           'org-feed-parse-rss-entry))
          feed-buffer inbox-pos new-formatted
-         entries old-status status new changed guid-alist e guid olds)
+         entries old-status status new changed guid-alist guid olds)
       (setq feed-buffer (org-feed-get-feed url))
       (unless (and feed-buffer (bufferp (get-buffer feed-buffer)))
        (error "Cannot get feed %s" name))
@@ -407,8 +405,8 @@ it can be a list structured like an entry in 
`org-feed-alist'."
 
          ;; Normalize the visibility of the inbox tree
          (goto-char inbox-pos)
-         (hide-subtree)
-         (show-children)
+         (outline-hide-subtree)
+         (org-show-children)
          (org-cycle-hide-drawers 'children)
 
          ;; Hooks and messages
@@ -442,7 +440,7 @@ it can be a list structured like an entry in 
`org-feed-alist'."
   (if (stringp feed) (setq feed (assoc feed org-feed-alist)))
   (unless feed
     (error "No such feed in `org-feed-alist"))
-  (org-pop-to-buffer-same-window
+  (pop-to-buffer-same-window
    (org-feed-update feed 'retrieve-only))
   (goto-char (point-min)))
 
@@ -477,8 +475,7 @@ This will find DRAWER and extract the alist."
   "Write the feed STATUS to DRAWER in entry at POS."
   (save-excursion
     (goto-char pos)
-    (let ((end (save-excursion (org-end-of-subtree t t)))
-         guid)
+    (let ((end (save-excursion (org-end-of-subtree t t))))
       (if (re-search-forward (concat "^[ \t]*:" drawer ":[ \t]*\n")
                             end t)
          (progn
@@ -514,66 +511,77 @@ ENTRY is a property list.  This function adds a 
`:formatted-for-org' property
 and returns the full property list.
 If that property is already present, nothing changes."
   (require 'org-capture)
-  (if formatter
-      (funcall formatter entry)
-    (let (dlines time escape name tmp
-                v-h v-t v-T v-u v-U v-a)
-      (setq dlines (org-split-string (or (plist-get entry :description) "???")
-                                    "\n")
-           v-h (or (plist-get entry :title) (car dlines) "???")
-           time (or (if (plist-get entry :pubDate)
-                        (org-read-date t t (plist-get entry :pubDate)))
-                    (current-time))
-           v-t (format-time-string (org-time-stamp-format nil nil) time)
-           v-T (format-time-string (org-time-stamp-format t   nil) time)
-           v-u (format-time-string (org-time-stamp-format nil t)   time)
-           v-U (format-time-string (org-time-stamp-format t   t)   time)
-           v-a (if (setq tmp (or (and (plist-get entry :guid-permalink)
-                                      (plist-get entry :guid))
-                                 (plist-get entry :link)))
-                   (concat "[[" tmp "]]\n")
-                 ""))
+  (if formatter (funcall formatter entry)
+    (let* ((dlines
+            (org-split-string (or (plist-get entry :description) "???")
+                              "\n"))
+           (time (or (if (plist-get entry :pubDate)
+                         (org-read-date t t (plist-get entry :pubDate)))
+                     (current-time)))
+           (v-h (or (plist-get entry :title) (car dlines) "???"))
+           (v-t (format-time-string (org-time-stamp-format nil nil) time))
+           (v-T (format-time-string (org-time-stamp-format t   nil) time))
+           (v-u (format-time-string (org-time-stamp-format nil t)   time))
+           (v-U (format-time-string (org-time-stamp-format t   t)   time))
+           (v-a (let ((tmp (or (and (plist-get entry :guid-permalink)
+                                   (plist-get entry :guid))
+                              (plist-get entry :link))))
+                 (if tmp (format "[[%s]]\n" tmp ) ""))))
       (with-temp-buffer
-       (insert template)
-
-       ;; Simple %-escapes
-       ;; before embedded elisp to support simple %-escapes as
-       ;; arguments for embedded elisp
-       (goto-char (point-min))
-       (while (re-search-forward "%\\([a-zA-Z]+\\)" nil t)
-         (unless (org-capture-escaped-%)
-           (setq name (match-string 1)
-                 escape (org-capture-inside-embedded-elisp-p))
-           (cond
-            ((member name '("h" "t" "T" "u" "U" "a"))
-             (setq tmp (symbol-value (intern (concat "v-" name)))))
-            ((setq tmp (plist-get entry (intern (concat ":" name))))
-             (save-excursion
-               (save-match-data
-                 (beginning-of-line 1)
-                 (when (looking-at
-                        (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
-                   (setq tmp (org-feed-make-indented-block
-                              tmp (org-get-indentation))))))))
-           (when tmp
-             ;; escape string delimiters `"' when inside %() embedded lisp
-             (when escape
-               (setq tmp (replace-regexp-in-string "\"" "\\\\\"" tmp)))
-             (replace-match tmp t t))))
-
-       ;; %() embedded elisp
-       (org-capture-expand-embedded-elisp)
-
-       (decode-coding-string
-        (buffer-string) (detect-coding-region (point-min) (point-max) t))))))
+        (insert template)
+        (goto-char (point-min))
+
+        ;; Mark %() embedded elisp for later evaluation.
+        (org-capture-expand-embedded-elisp 'mark)
+
+        ;; Simple %-escapes.  `org-capture-escaped-%' may modify
+       ;; buffer and cripple match-data.  Use markers instead.
+        (while (re-search-forward "%\\([a-zA-Z]+\\)" nil t)
+          (let ((key (match-string 1))
+               (beg (copy-marker (match-beginning 0)))
+               (end (copy-marker (match-end 0))))
+           (unless (org-capture-escaped-%)
+             (delete-region beg end)
+             (set-marker beg nil)
+             (set-marker end nil)
+             (let ((replacement
+                    (pcase key
+                      ("h" v-h)
+                      ("t" v-t)
+                      ("T" v-T)
+                      ("u" v-u)
+                      ("U" v-U)
+                      ("a" v-a)
+                      (name
+                       (let ((v (plist-get entry (intern (concat ":" name)))))
+                         (save-excursion
+                           (save-match-data
+                             (beginning-of-line)
+                             (if (looking-at
+                                  (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
+                                 (org-feed-make-indented-block
+                                  v (org-get-indentation))
+                               v))))))))
+               (when replacement
+                 (insert
+                  ;; Escape string delimiters within embedded lisp.
+                  (if (org-capture-inside-embedded-elisp-p)
+                      (replace-regexp-in-string "\"" "\\\\\"" replacement)
+                    replacement)))))))
+
+        ;; %() embedded elisp
+        (org-capture-expand-embedded-elisp)
+
+        (decode-coding-string
+         (buffer-string) (detect-coding-region (point-min) (point-max) t))))))
 
 (defun org-feed-make-indented-block (s n)
   "Add indentation of N spaces to a multiline string S."
   (if (not (string-match "\n" s))
       s
     (mapconcat 'identity
-              (org-split-string s "\n")
-              (concat "\n" (make-string n ?\ )))))
+               (org-split-string s "\n")
+               (concat "\n" (make-string n ?\ )))))
 
 (defun org-feed-skip-http-headers (buffer)
   "Remove HTTP headers from BUFFER, and return it.
@@ -605,6 +613,7 @@ Assumes headers are indeed present!"
   "Parse BUFFER for RSS feed entries.
 Returns a list of entries, with each entry a property list,
 containing the properties `:guid' and `:item-full-text'."
+  (require 'xml)
   (let ((case-fold-search t)
        entries beg end item guid entry)
     (with-current-buffer buffer
@@ -616,7 +625,7 @@ containing the properties `:guid' and `:item-full-text'."
                       (match-beginning 0)))
        (setq item (buffer-substring beg end)
              guid (if (string-match "<guid\\>.*?>\\(.*?\\)</guid>" item)
-                      (org-match-string-no-properties 1 item)))
+                      (xml-substitute-special (match-string-no-properties 1 
item))))
        (setq entry (list :guid guid :item-full-text item))
        (push entry entries)
        (widen)
diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el
index 553f124..af03fbf 100644
--- a/lisp/org/org-footnote.el
+++ b/lisp/org/org-footnote.el
@@ -1,4 +1,4 @@
-;;; org-footnote.el --- Footnote support in Org and elsewhere
+;;; org-footnote.el --- Footnote support in Org      -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 ;;
@@ -24,72 +24,68 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the code dealing with footnotes in Org-mode.
-;; The code can also be used in arbitrary text modes to provide
-;; footnotes.  Compared to Steven L Baur's footnote.el it provides
-;; better support for resuming editing.  It is less configurable than
-;; Steve's code, though.
+;; This file contains the code dealing with footnotes in Org mode.
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
+;;;; Declarations
+
+(require 'cl-lib)
 (require 'org-macs)
 (require 'org-compat)
 
-(declare-function message-point-in-header-p "message" ())
+(declare-function org-at-comment-p "org" ())
+(declare-function org-at-heading-p "org" (&optional ignored))
 (declare-function org-back-over-empty-lines "org" ())
-(declare-function org-back-to-heading "org" (&optional invisible-ok))
-(declare-function org-combine-plists "org" (&rest plists))
+(declare-function org-edit-footnote-reference "org-src" ())
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-class "org-element" (datum &optional parent))
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-lineage "org-element" (blob &optional types 
with-self))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
 (declare-function org-end-of-subtree "org"  (&optional invisible-ok 
to-heading))
 (declare-function org-fill-paragraph "org" (&optional justify))
-(declare-function org-icompleting-read "org" (&rest args))
-(declare-function org-id-uuid "org-id" ())
 (declare-function org-in-block-p "org" (names))
-(declare-function org-in-commented-line "org" ())
-(declare-function org-in-indented-comment-line "org" ())
 (declare-function org-in-regexp "org" (re &optional nlines visually))
 (declare-function org-in-verbatim-emphasis "org" ())
 (declare-function org-inside-LaTeX-fragment-p "org" ())
 (declare-function org-inside-latex-macro-p "org" ())
 (declare-function org-mark-ring-push "org" (&optional pos buffer))
 (declare-function org-show-context "org" (&optional key))
-(declare-function org-trim "org" (s))
-(declare-function org-skip-whitespace "org" ())
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function outline-next-heading "outline")
-(declare-function org-skip-whitespace "org" ())
 
-(defvar org-outline-regexp-bol)                ; defined in org.el
-(defvar org-odd-levels-only)           ; defined in org.el
+(defvar electric-indent-mode)
+(defvar org-blank-before-new-entry)    ; defined in org.el
 (defvar org-bracket-link-regexp)       ; defined in org.el
-(defvar message-cite-prefix-regexp)    ; defined in message.el
-(defvar message-signature-separator)   ; defined in message.el
+(defvar org-complex-heading-regexp)    ; defined in org.el
+(defvar org-odd-levels-only)           ; defined in org.el
+(defvar org-outline-regexp)            ; defined in org.el
+(defvar org-outline-regexp-bol)                ; defined in org.el
+
+
+;;;; Constants
 
 (defconst org-footnote-re
-  ;; Only [1]-like footnotes are closed in this regexp, as footnotes
-  ;; from other types might contain square brackets (i.e. links) in
-  ;; their definition.
-  ;;
-  ;; `org-re' is used for regexp compatibility with XEmacs.
-  (concat "\\[\\(?:"
-         ;; Match inline footnotes.
-         (org-re "fn:\\([-_[:word:]]+\\)?:\\|")
-         ;; Match other footnotes.
-         "\\(?:\\([0-9]+\\)\\]\\)\\|"
-         (org-re "\\(fn:[-_[:word:]]+\\)")
-         "\\)")
-  "Regular expression for matching footnotes.")
-
-(defconst org-footnote-definition-re
-  (org-re "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]")
-  "Regular expression matching the definition of a footnote.")
-
-(defconst org-footnote-forbidden-blocks
-  '("ascii" "beamer" "comment" "example" "html" "latex" "odt" "src")
+  "\\[fn:\\(?:\\(?1:[-_[:word:]]+\\)?\\(:\\)\\|\\(?1:[-_[:word:]]+\\)\\]\\)"
+  "Regular expression for matching footnotes.
+Match group 1 contains footnote's label.  It is nil for anonymous
+footnotes.  Match group 2 is non-nil only when footnote is
+inline, i.e., it contains its own definition.")
+
+(defconst org-footnote-definition-re "^\\[fn:\\([-_[:word:]]+\\)\\]"
+  "Regular expression matching the definition of a footnote.
+Match group 1 contains definition's label.")
+
+(defconst org-footnote-forbidden-blocks '("comment" "example" "export" "src")
   "Names of blocks where footnotes are not allowed.")
 
+
+;;;; Customization
+
 (defgroup org-footnote nil
-  "Footnotes in Org-mode."
+  "Footnotes in Org mode."
   :tag "Org Footnote"
   :group 'org)
 
@@ -106,25 +102,21 @@ the notes.  However, by hand you may place definitions
 *anywhere*.
 
 If this is a string, during export, all subtrees starting with
-this heading will be ignored."
-  :group 'org-footnote
-  :type '(choice
-         (string :tag "Collect footnotes under heading")
-         (const :tag "Define footnotes locally" nil)))
+this heading will be ignored.
 
-(defcustom org-footnote-tag-for-non-org-mode-files "Footnotes:"
-  "Tag marking the beginning of footnote section.
-The Org footnote engine can be used in arbitrary text files as well
-as in Org-mode.  Outside Org mode, new footnotes are always placed at
-the end of the file.  When you normalize the notes, any line containing
-only this tag will be removed, a new one will be inserted at the end
-of the file, followed by the collected and normalized footnotes.
+If you don't use the customize interface to change this variable,
+you will need to run the following command after the change:
 
-If you don't want any tag in such buffers, set this variable to nil."
+  `\\[universal-argument] \\[org-element-cache-reset]'"
   :group 'org-footnote
+  :initialize 'custom-initialize-default
+  :set (lambda (var val)
+        (set var val)
+        (when (fboundp 'org-element-cache-reset)
+          (org-element-cache-reset 'all)))
   :type '(choice
-         (string :tag "Collect footnotes under tag")
-         (const :tag "Don't use a tag" nil)))
+         (string :tag "Collect footnotes under heading")
+         (const :tag "Define footnotes locally" nil)))
 
 (defcustom org-footnote-define-inline nil
   "Non-nil means define footnotes inline, at reference location.
@@ -143,15 +135,13 @@ t          Create unique labels of the form [fn:1], 
[fn:2], etc.
 confirm    Like t, but let the user edit the created value.
            The label can be removed from the minibuffer to create
            an anonymous footnote.
-random    Automatically generate a unique, random label.
-plain      Automatically create plain number labels like [1]."
+random    Automatically generate a unique, random label."
   :group 'org-footnote
   :type '(choice
          (const :tag "Prompt for label" nil)
          (const :tag "Create automatic [fn:N]" t)
          (const :tag "Offer automatic [fn:N] for editing" confirm)
-         (const :tag "Create a random label" random)
-         (const :tag "Create automatic [N]" plain)))
+         (const :tag "Create a random label" random)))
 
 (defcustom org-footnote-auto-adjust nil
   "Non-nil means automatically adjust footnotes after insert/delete.
@@ -179,23 +169,19 @@ extracted will be filled again."
   :group 'org-footnote
   :type 'boolean)
 
+
+;;;; Predicates
+
 (defun org-footnote-in-valid-context-p ()
   "Is point in a context where footnotes are allowed?"
   (save-match-data
-    (not (or (org-in-commented-line)
-            (org-in-indented-comment-line)
+    (not (or (org-at-comment-p)
             (org-inside-LaTeX-fragment-p)
             ;; Avoid literal example.
             (org-in-verbatim-emphasis)
             (save-excursion
               (beginning-of-line)
               (looking-at "[ \t]*:[ \t]+"))
-            ;; Avoid cited text and headers in message-mode.
-            (and (derived-mode-p 'message-mode)
-                 (or (save-excursion
-                       (beginning-of-line)
-                       (looking-at message-cite-prefix-regexp))
-                     (message-point-in-header-p)))
             ;; Avoid forbidden blocks.
             (org-in-block-p org-footnote-forbidden-blocks)))))
 
@@ -208,13 +194,9 @@ positions, and the definition, when inlined."
             (or (looking-at org-footnote-re)
                 (org-in-regexp org-footnote-re)
                 (save-excursion (re-search-backward org-footnote-re nil t)))
-            (/= (match-beginning 0) (point-at-bol)))
+            (/= (match-beginning 0) (line-beginning-position)))
     (let* ((beg (match-beginning 0))
-          (label (or (org-match-string-no-properties 2)
-                     (org-match-string-no-properties 3)
-                     ;; Anonymous footnotes don't have labels
-                     (and (match-string 1)
-                          (concat "fn:" (org-match-string-no-properties 1)))))
+          (label (match-string-no-properties 1))
           ;; Inline footnotes don't end at (match-end 0) as
           ;; `org-footnote-re' stops just after the second colon.
           ;; Find the real ending with `scan-sexps', so Org doesn't
@@ -222,7 +204,8 @@ positions, and the definition, when inlined."
           (end (ignore-errors (scan-sexps beg 1))))
       ;; Point is really at a reference if it's located before true
       ;; ending of the footnote.
-      (when (and end (< (point) end)
+      (when (and end
+                (< (point) end)
                 ;; Verify match isn't a part of a link.
                 (not (save-excursion
                        (goto-char beg)
@@ -234,16 +217,17 @@ positions, and the definition, when inlined."
                 (not (org-inside-latex-macro-p)))
        (list label beg end
              ;; Definition: ensure this is an inline footnote first.
-             (and (or (not label) (match-string 1))
-                  (org-trim (buffer-substring-no-properties
-                             (match-end 0) (1- end)))))))))
+             (and (match-end 2)
+                  (org-trim
+                   (buffer-substring-no-properties
+                    (match-end 0) (1- end)))))))))
 
 (defun org-footnote-at-definition-p ()
   "Is point within a footnote definition?
 
 This matches only pure definitions like [1] or [fn:name] at the
 beginning of a line.  It does not match references like
-[fn:name:definition], where the footnote text is included and
+\[fn:name:definition], where the footnote text is included and
 defined locally.
 
 The return value will be nil if not at a footnote definition, and
@@ -259,26 +243,224 @@ otherwise."
                    (concat org-outline-regexp-bol
                            "\\|^\\([ \t]*\n\\)\\{2,\\}") nil t))))
        (when (re-search-backward org-footnote-definition-re lim t)
-         (let ((label (org-match-string-no-properties 1))
+         (let ((label (match-string-no-properties 1))
                (beg (match-beginning 0))
                (beg-def (match-end 0))
-               ;; In message-mode, do not search after signature.
-               (end (let ((bound (and (derived-mode-p 'message-mode)
-                                      (save-excursion
-                                        (goto-char (point-max))
-                                        (re-search-backward
-                                         message-signature-separator nil t)))))
-                      (if (progn
-                            (end-of-line)
-                            (re-search-forward
-                             (concat org-outline-regexp-bol "\\|"
-                                     org-footnote-definition-re "\\|"
-                                     "^\\([ \t]*\n\\)\\{2,\\}") bound 'move))
-                          (match-beginning 0)
-                        (point)))))
+               (end (if (progn
+                          (end-of-line)
+                          (re-search-forward
+                           (concat org-outline-regexp-bol "\\|"
+                                   org-footnote-definition-re "\\|"
+                                   "^\\([ \t]*\n\\)\\{2,\\}") nil 'move))
+                        (match-beginning 0)
+                      (point))))
            (list label beg end
                  (org-trim (buffer-substring-no-properties beg-def end)))))))))
 
+
+;;;; Internal functions
+
+(defun org-footnote--allow-reference-p ()
+  "Non-nil when a footnote reference can be inserted at point."
+  ;; XXX: This is similar to `org-footnote-in-valid-context-p' but
+  ;; more accurate and usually faster, except in some corner cases.
+  ;; It may replace it after doing proper benchmarks as it would be
+  ;; used in fontification.
+  (unless (bolp)
+    (let* ((context (org-element-context))
+          (type (org-element-type context)))
+      (cond
+       ;; No footnote reference in attributes.
+       ((let ((post (org-element-property :post-affiliated context)))
+         (and post (< (point) post)))
+       nil)
+       ;; Paragraphs and blank lines at top of document are fine.
+       ((memq type '(nil paragraph)))
+       ;; So are contents of verse blocks.
+       ((eq type 'verse-block)
+       (and (>= (point) (org-element-property :contents-begin context))
+            (< (point) (org-element-property :contents-end context))))
+       ;; In an headline or inlinetask, point must be either on the
+       ;; heading itself or on the blank lines below.
+       ((memq type '(headline inlinetask))
+       (or (not (org-at-heading-p))
+           (and (save-excursion
+                  (beginning-of-line)
+                  (and (let ((case-fold-search t))
+                         (not (looking-at-p "\\*+ END[ \t]*$")))
+                       (let ((case-fold-search nil))
+                         (looking-at org-complex-heading-regexp))))
+                (match-beginning 4)
+                (>= (point) (match-beginning 4))
+                (or (not (match-beginning 5))
+                    (< (point) (match-beginning 5))))))
+       ;; White spaces after an object or blank lines after an element
+       ;; are OK.
+       ((>= (point)
+           (save-excursion (goto-char (org-element-property :end context))
+                           (skip-chars-backward " \r\t\n")
+                           (if (eq (org-element-class context) 'object) (point)
+                             (1+ (line-beginning-position 2))))))
+       ;; Other elements are invalid.
+       ((eq (org-element-class context) 'element) nil)
+       ;; Just before object is fine.
+       ((= (point) (org-element-property :begin context)))
+       ;; Within recursive object too, but not in a link.
+       ((eq type 'link) nil)
+       ((let ((cbeg (org-element-property :contents-begin context))
+             (cend (org-element-property :contents-end context)))
+         (and cbeg (>= (point) cbeg) (<= (point) cend))))))))
+
+(defun org-footnote--clear-footnote-section ()
+  "Remove all footnote sections in buffer and create a new one.
+New section is created at the end of the buffer, before any file
+local variable definition.  Leave point within the new section."
+  (when org-footnote-section
+    (goto-char (point-min))
+    (let ((regexp
+          (format "^\\*+ +%s[ \t]*$"
+                  (regexp-quote org-footnote-section))))
+      (while (re-search-forward regexp nil t)
+       (delete-region
+        (match-beginning 0)
+        (progn (org-end-of-subtree t t)
+               (if (not (eobp)) (point)
+                 (org-footnote--goto-local-insertion-point)
+                 (skip-chars-forward " \t\n")
+                 (if (eobp) (point) (line-beginning-position)))))))
+    (goto-char (point-max))
+    (org-footnote--goto-local-insertion-point)
+    (when (and (cdr (assq 'heading org-blank-before-new-entry))
+              (zerop (save-excursion (org-back-over-empty-lines))))
+      (insert "\n"))
+    (insert "* " org-footnote-section "\n")))
+
+(defun org-footnote--set-label (label)
+  "Set label of footnote at point to string LABEL.
+Assume point is at the beginning of the reference or definition
+to rename."
+  (forward-char 4)
+  (cond ((eq (char-after) ?:) (insert label))
+       ((looking-at "\\([-_[:word:]]+\\)") (replace-match label nil nil nil 1))
+       (t nil)))
+
+(defun org-footnote--collect-references (&optional anonymous)
+  "Collect all labelled footnote references in current buffer.
+
+Return an alist where associations follow the pattern
+
+  (LABEL MARKER TOP-LEVEL SIZE)
+
+with
+
+  LABEL     the label of the of the definition,
+  MARKER    a marker pointing to its beginning,
+  TOP-LEVEL a boolean, nil when the footnote is contained within
+            another one,
+  SIZE      the length of the inline definition, in characters,
+            or nil for non-inline references.
+
+When optional ANONYMOUS is non-nil, also collect anonymous
+references.  In such cases, LABEL is nil.
+
+References are sorted according to a deep-reading order."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let ((regexp (if anonymous org-footnote-re "\\[fn:[-_[:word:]]+[]:]"))
+        references nested)
+     (save-excursion
+       (while (re-search-forward regexp nil t)
+        ;; Ignore definitions.
+        (unless (and (eq (char-before) ?\])
+                     (= (line-beginning-position) (match-beginning 0)))
+          ;; Ensure point is within the reference before parsing it.
+          (backward-char)
+          (let ((object (org-element-context)))
+            (when (eq (org-element-type object) 'footnote-reference)
+              (let* ((label (org-element-property :label object))
+                     (begin (org-element-property :begin object))
+                     (size
+                      (and (eq (org-element-property :type object) 'inline)
+                           (- (org-element-property :contents-end object)
+                              (org-element-property :contents-begin object)))))
+                (let ((d (org-element-lineage object '(footnote-definition))))
+                  (push (list label (copy-marker begin) (not d) size)
+                        references)
+                  (when d
+                    ;; Nested references are stored in alist NESTED.
+                    ;; Associations there follow the pattern
+                    ;;
+                    ;;   (DEFINITION-LABEL . REFERENCES)
+                    (let* ((def-label (org-element-property :label d))
+                           (labels (assoc def-label nested)))
+                      (if labels (push label (cdr labels))
+                        (push (list def-label label) nested)))))))))))
+     ;; Sort the list of references.  Nested footnotes have priority
+     ;; over top-level ones.
+     (letrec ((ordered nil)
+             (add-reference
+              (lambda (ref allow-nested)
+                (when (or allow-nested (nth 2 ref))
+                  (push ref ordered)
+                  (dolist (r (mapcar (lambda (l) (assoc l references))
+                                     (reverse
+                                      (cdr (assoc (nth 0 ref) nested)))))
+                    (funcall add-reference r t))))))
+       (dolist (r (reverse references) (nreverse ordered))
+        (funcall add-reference r nil))))))
+
+(defun org-footnote--collect-definitions (&optional delete)
+  "Collect all footnote definitions in current buffer.
+
+Return an alist where associations follow the pattern
+
+  (LABEL . DEFINITION)
+
+with LABEL and DEFINITION being, respectively, the label and the
+definition of the footnote, as strings.
+
+When optional argument DELETE is non-nil, delete the definition
+while collecting them."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let (definitions seen)
+     (while (re-search-forward org-footnote-definition-re nil t)
+       (backward-char)
+       (let ((element (org-element-at-point)))
+        (let ((label (org-element-property :label element)))
+          (when (and (eq (org-element-type element) 'footnote-definition)
+                     (not (member label seen)))
+            (push label seen)
+            (let* ((beg (progn
+                          (goto-char (org-element-property :begin element))
+                          (skip-chars-backward " \r\t\n")
+                          (if (bobp) (point) (line-beginning-position 2))))
+                   (end (progn
+                          (goto-char (org-element-property :end element))
+                          (skip-chars-backward " \r\t\n")
+                          (line-beginning-position 2)))
+                   (def (org-trim (buffer-substring-no-properties beg end))))
+              (push (cons label def) definitions)
+              (when delete (delete-region beg end)))))))
+     definitions)))
+
+(defun org-footnote--goto-local-insertion-point ()
+  "Find insertion point for footnote, just before next outline heading.
+Assume insertion point is within currently accessible part of the buffer."
+  (org-with-limited-levels (outline-next-heading))
+  ;; Skip file local variables.  See `modify-file-local-variable'.
+  (when (eobp)
+    (let ((case-fold-search t))
+      (re-search-backward "^[ \t]*# +Local Variables:"
+                         (max (- (point-max) 3000) (point-min))
+                         t)))
+  (skip-chars-backward " \t\n")
+  (forward-line)
+  (unless (bolp) (insert "\n")))
+
+
+;;;; Navigation
+
 (defun org-footnote-get-next-reference (&optional label backward limit)
   "Return complete reference of the next footnote.
 
@@ -289,7 +471,7 @@ the buffer position bounding the search.
 Return value is a list like those provided by `org-footnote-at-reference-p'.
 If no footnote is found, return nil."
   (save-excursion
-    (let* ((label-fmt (if label (format "\\[%s[]:]" label) org-footnote-re)))
+    (let* ((label-fmt (if label (format "\\[fn:%s[]:]" label) 
org-footnote-re)))
       (catch 'exit
        (while t
          (unless (funcall (if backward #'re-search-backward 
#'re-search-forward)
@@ -313,59 +495,54 @@ If no footnote is found, return nil."
        (unless (re-search-forward org-footnote-re limit t)
          (goto-char origin)
          (throw 'exit nil))
-       ;; Beware: with [1]-like footnotes point will be just after
+       ;; Beware: with non-inline footnotes point will be just after
        ;; the closing square bracket.
        (backward-char)
        (cond
         ((setq ref (org-footnote-at-reference-p))
          (throw 'exit ref))
-        ;; Definition: also grab the last square bracket, only
-        ;; matched in `org-footnote-re' for [1]-like footnotes.
+        ;; Definition: also grab the last square bracket, matched in
+        ;; `org-footnote-re' for non-inline footnotes.
         ((save-match-data (org-footnote-at-definition-p))
          (let ((end (match-end 0)))
            (throw 'exit
                   (list nil (match-beginning 0)
-                        (if (eq (char-before end) 93) end (1+ end)))))))))))
+                        (if (eq (char-before end) ?\]) end (1+ end)))))))))))
 
-(defun org-footnote-get-definition (label)
-  "Return label, boundaries and definition of the footnote LABEL."
-  (let* ((label (regexp-quote (org-footnote-normalize-label label)))
-        (re (format "^\\[%s\\]\\|.\\[%s:" label label))
-        pos)
-    (save-excursion
-      (save-restriction
-       (when (or (re-search-forward re nil t)
-                 (and (goto-char (point-min))
-                      (re-search-forward re nil t))
-                 (and (progn (widen) t)
-                      (goto-char (point-min))
-                      (re-search-forward re nil t)))
-         (let ((refp (org-footnote-at-reference-p)))
-           (cond
-            ((and (nth 3 refp) refp))
-            ((org-footnote-at-definition-p)))))))))
-
-(defun org-footnote-goto-definition (label)
+(defun org-footnote-goto-definition (label &optional location)
   "Move point to the definition of the footnote LABEL.
-Return a non-nil value when a definition has been found."
+
+LOCATION, when non-nil specifies the buffer position of the
+definition.
+
+Throw an error if there is no definition or if it cannot be
+reached from current narrowed part of buffer.  Return a non-nil
+value if point was successfully moved."
   (interactive "sLabel: ")
-  (org-mark-ring-push)
-  (let ((def (org-footnote-get-definition label)))
-    (if (not def)
-       (error "Cannot find definition of footnote %s" label)
-      (goto-char (nth 1 def))
-      (looking-at (format "\\[%s\\]\\|\\[%s:" label label))
-      (goto-char (match-end 0))
-      (org-show-context 'link-search)
-      (when (derived-mode-p 'org-mode)
-       (message "Edit definition and go back with `C-c &' or, if unique, with 
`C-c C-c'."))
-      t)))
+  (let* ((label (org-footnote-normalize-label label))
+        (def-start (or location (nth 1 (org-footnote-get-definition label)))))
+    (cond
+     ((not def-start)
+      (user-error "Cannot find definition of footnote %s" label))
+     ((or (> def-start (point-max)) (< def-start (point-min)))
+      (user-error "Definition is outside narrowed part of buffer")))
+    (org-mark-ring-push)
+    (goto-char def-start)
+    (looking-at (format "\\[fn:%s[]:] ?" (regexp-quote label)))
+    (goto-char (match-end 0))
+    (org-show-context 'link-search)
+    (when (derived-mode-p 'org-mode)
+      (message "%s" (substitute-command-keys
+                    "Edit definition and go back with \
+`\\[org-mark-ring-goto]' or, if unique, with `\\[org-ctrl-c-ctrl-c]'.")))
+    t))
 
 (defun org-footnote-goto-previous-reference (label)
   "Find the first closest (to point) reference of footnote with label LABEL."
   (interactive "sLabel: ")
   (org-mark-ring-push)
-  (let* ((label (org-footnote-normalize-label label)) ref)
+  (let ((label (org-footnote-normalize-label label))
+       ref)
     (save-excursion
       (setq ref (or (org-footnote-get-next-reference label t)
                    (org-footnote-get-next-reference label)
@@ -379,62 +556,74 @@ Return a non-nil value when a definition has been found."
       (goto-char (nth 1 ref))
       (org-show-context 'link-search))))
 
+
+;;;; Getters
+
 (defun org-footnote-normalize-label (label)
-  "Return LABEL as an appropriate string."
-  (cond
-   ((numberp label) (number-to-string label))
-   ((equal "" label) nil)
-   ((not (string-match "^[0-9]+$\\|^fn:" label))
-    (concat "fn:" label))
-   (t label)))
-
-(defun org-footnote-all-labels (&optional with-defs)
-  "Return list with all defined foot labels used in the buffer.
-
-If WITH-DEFS is non-nil, also associate the definition to each
-label.  The function will then return an alist whose key is label
-and value definition."
-  (let* (rtn
-        (push-to-rtn
-         (function
-          ;; Depending on WITH-DEFS, store label or (label . def) of
-          ;; footnote reference/definition given as argument in RTN.
-          (lambda (el)
-            (let ((lbl (car el)))
-              (push (if with-defs (cons lbl (nth 3 el)) lbl) rtn))))))
-    (save-excursion
-      (save-restriction
-       (widen)
-       ;; Find all labels found in definitions.
-       (goto-char (point-min))
-       (let (def)
-         (while (re-search-forward org-footnote-definition-re nil t)
-           (when (setq def (org-footnote-at-definition-p))
-             (funcall push-to-rtn def))))
-       ;; Find all labels found in references.
-       (goto-char (point-min))
-       (let (ref)
-         (while (setq ref (org-footnote-get-next-reference))
-           (goto-char (nth 2 ref))
-           (and (car ref)              ; ignore anonymous footnotes
-                (not (funcall (if with-defs #'assoc #'member) (car ref) rtn))
-                (funcall push-to-rtn ref))))))
-    rtn))
+  "Return LABEL without \"fn:\" prefix.
+If LABEL is the empty string or constituted of white spaces only,
+return nil instead."
+  (pcase (org-trim label)
+    ("" nil)
+    ((pred (string-prefix-p "fn:")) (substring label 3))
+    (_ label)))
+
+(defun org-footnote-get-definition (label)
+  "Return label, boundaries and definition of the footnote LABEL."
+  (let* ((label (regexp-quote (org-footnote-normalize-label label)))
+        (re (format "^\\[fn:%s\\]\\|.\\[fn:%s:" label label)))
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (catch 'found
+       (while (re-search-forward re nil t)
+        (let* ((datum (progn (backward-char) (org-element-context)))
+               (type (org-element-type datum)))
+          (when (memq type '(footnote-definition footnote-reference))
+            (throw 'found
+                   (list
+                    label
+                    (org-element-property :begin datum)
+                    (org-element-property :end datum)
+                    (let ((cbeg (org-element-property :contents-begin datum)))
+                      (if (not cbeg) ""
+                        (replace-regexp-in-string
+                         "[ \t\n]*\\'"
+                         ""
+                         (buffer-substring-no-properties
+                          cbeg
+                          (org-element-property :contents-end datum))))))))))
+       nil))))
+
+(defun org-footnote-all-labels ()
+  "List all defined footnote labels used throughout the buffer.
+This function ignores narrowing, if any."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let (all)
+     (while (re-search-forward org-footnote-re nil t)
+       (backward-char)
+       (let ((context (org-element-context)))
+        (when (memq (org-element-type context)
+                    '(footnote-definition footnote-reference))
+          (let ((label (org-element-property :label context)))
+            (when label (cl-pushnew label all :test #'equal))))))
+     all)))
 
 (defun org-footnote-unique-label (&optional current)
   "Return a new unique footnote label.
 
-The function returns the first \"fn:N\" or \"N\" label that is
-currently not used.
+The function returns the first numeric label currently unused.
 
 Optional argument CURRENT is the list of labels active in the
 buffer."
-  (unless current (setq current (org-footnote-all-labels)))
-  (let ((fmt (if (eq org-footnote-auto-label 'plain) "%d" "fn:%d"))
-       (cnt 1))
-    (while (member (format fmt cnt) current)
-      (incf cnt))
-    (format fmt cnt)))
+  (let ((current (or current (org-footnote-all-labels))))
+    (let ((count 1))
+      (while (member (number-to-string count) current)
+       (cl-incf count))
+      (number-to-string count))))
+
+
+;;;; Adding, Deleting Footnotes
 
 (defun org-footnote-new ()
   "Insert a new footnote.
@@ -442,343 +631,66 @@ This command prompts for a label.  If this is a label 
referencing an
 existing label, only insert the label.  If the footnote label is empty
 or new, let the user edit the definition of the footnote."
   (interactive)
-  (unless (org-footnote-in-valid-context-p)
-    (error "Cannot insert a footnote here"))
-  (let* ((lbls (and (not (equal org-footnote-auto-label 'random))
-                   (org-footnote-all-labels)))
-        (propose (and (not (equal org-footnote-auto-label 'random))
-                      (org-footnote-unique-label lbls)))
+  (unless (org-footnote--allow-reference-p)
+    (user-error "Cannot insert a footnote here"))
+  (let* ((all (org-footnote-all-labels))
         (label
-         (org-footnote-normalize-label
-          (cond
-           ((member org-footnote-auto-label '(t plain))
-            propose)
-           ((equal org-footnote-auto-label 'random)
-            (require 'org-id)
-            (substring (org-id-uuid) 0 8))
-           (t
-            (org-icompleting-read
-             "Label (leave empty for anonymous): "
-             (mapcar 'list lbls) nil nil
-             (if (eq org-footnote-auto-label 'confirm) propose nil)))))))
-    (cond
-     ((bolp) (error "Cannot create a footnote reference at left margin"))
-     ((not label)
-      (insert "[fn:: ]")
-      (backward-char 1))
-     ((member label lbls)
-      (insert "[" label "]")
-      (message "New reference to existing note"))
-     (org-footnote-define-inline
-      (insert "[" label ": ]")
-      (backward-char 1)
-      (org-footnote-auto-adjust-maybe))
-     (t
-      (insert "[" label "]")
-      (org-footnote-create-definition label)
-      (org-footnote-auto-adjust-maybe)))))
-
-(defvar org-blank-before-new-entry) ; silence byte-compiler
+         (if (eq org-footnote-auto-label 'random)
+             (format "%x" (random most-positive-fixnum))
+           (org-footnote-normalize-label
+            (let ((propose (org-footnote-unique-label all)))
+              (if (eq org-footnote-auto-label t) propose
+                (completing-read
+                 "Label (leave empty for anonymous): "
+                 (mapcar #'list all) nil nil
+                 (and (eq org-footnote-auto-label 'confirm) propose))))))))
+    (cond ((not label)
+          (insert "[fn::]")
+          (backward-char 1))
+         ((member label all)
+          (insert "[fn:" label "]")
+          (message "New reference to existing note"))
+         (org-footnote-define-inline
+          (insert "[fn:" label ":]")
+          (backward-char 1)
+          (org-footnote-auto-adjust-maybe))
+         (t
+          (insert "[fn:" label "]")
+          (let ((p (org-footnote-create-definition label)))
+            ;; `org-footnote-goto-definition' needs to be called
+            ;; after `org-footnote-auto-adjust-maybe'.  Otherwise
+            ;; both label and location of the definition are lost.
+            ;; On the contrary, it needs to be called before
+            ;; `org-edit-footnote-reference' so that the remote
+            ;; editing buffer can display the correct label.
+            (if (ignore-errors (org-footnote-goto-definition label p))
+                (org-footnote-auto-adjust-maybe)
+              ;; Definition was created outside current scope: edit
+              ;; it remotely.
+              (org-footnote-auto-adjust-maybe)
+              (org-edit-footnote-reference)))))))
+
 (defun org-footnote-create-definition (label)
-  "Start the definition of a footnote with label LABEL."
-  (interactive "sLabel: ")
+  "Start the definition of a footnote with label LABEL.
+Return buffer position at the beginning of the definition.  This
+function doesn't move point."
   (let ((label (org-footnote-normalize-label label))
-       electric-indent-mode) ;; Prevent wrong indentation
-    (cond
-     ;; In an Org file.
-     ((derived-mode-p 'org-mode)
-      ;; If `org-footnote-section' is defined, find it, or create it
-      ;; at the end of the buffer.
-      (when org-footnote-section
-       (goto-char (point-min))
-       (let ((re (concat "^\\*+[ \t]+" org-footnote-section "[ \t]*$")))
-         (unless (or (re-search-forward re nil t)
-                     (and (progn (widen) t)
-                          (re-search-forward re nil t)))
-           (goto-char (point-max))
-           (skip-chars-backward " \t\r\n")
-           (unless (bolp) (newline))
-           ;; Insert new section.  Separate it from the previous one
-           ;; with a blank line, unless `org-blank-before-new-entry'
-           ;; explicitly says no.
-           (when (and (cdr (assq 'heading org-blank-before-new-entry))
-                      (zerop (save-excursion (org-back-over-empty-lines))))
-             (insert "\n"))
-           (insert "* " org-footnote-section "\n"))))
-      ;; Move to the end of this entry (which may be
-      ;; `org-footnote-section' or the current one).
-      (org-footnote-goto-local-insertion-point)
-      (org-show-context 'link-search))
-     (t
-      ;; In a non-Org file.  Search for footnote tag, or create it if
-      ;; specified (at the end of buffer, or before signature if in
-      ;; Message mode).  Set point after any definition already there.
-      (let ((tag (and org-footnote-tag-for-non-org-mode-files
-                     (concat "^" (regexp-quote
-                                  org-footnote-tag-for-non-org-mode-files)
-                             "[ \t]*$")))
-           (max (if (and (derived-mode-p 'message-mode)
-                         (goto-char (point-max))
-                         (re-search-backward
-                          message-signature-separator nil t))
-                    (progn
-                      ;; Ensure one blank line separates last
-                      ;; footnote from signature.
-                      (beginning-of-line)
-                      (open-line 2)
-                      (point-marker))
-                  (point-max-marker))))
-       (set-marker-insertion-type max t)
-       (goto-char max)
-       ;; Check if the footnote tag is defined but missing.  In this
-       ;; case, insert it, before any footnote or one blank line
-       ;; after any previous text.
-       (when (and tag (not (re-search-backward tag nil t)))
-         (skip-chars-backward " \t\r\n")
-         (while (re-search-backward org-footnote-definition-re nil t))
-         (unless (bolp) (newline 2))
-         (insert org-footnote-tag-for-non-org-mode-files "\n\n"))
-       ;; Remove superfluous white space and clear marker.
-       (goto-char max)
-       (skip-chars-backward " \t\r\n")
-       (delete-region (point) max)
-       (unless (bolp) (newline))
-       (set-marker max nil))))
-    ;; Insert footnote label.
-    (when (zerop (org-back-over-empty-lines)) (newline))
-    (insert "[" label "] \n")
-    (backward-char)
-    ;; Only notify user about next possible action when in an Org
-    ;; buffer, as the bindings may have different meanings otherwise.
-    (when (derived-mode-p 'org-mode)
-      (message
-       "Edit definition and go back with `C-c &' or, if unique, with `C-c 
C-c'."))))
-
-;;;###autoload
-(defun org-footnote-action (&optional special)
-  "Do the right thing for footnotes.
-
-When at a footnote reference, jump to the definition.
-
-When at a definition, jump to the references if they exist, offer
-to create them otherwise.
-
-When neither at definition or reference, create a new footnote,
-interactively.
-
-With prefix arg SPECIAL, offer additional commands in a menu."
-  (interactive "P")
-  (let (tmp c)
-    (cond
-     (special
-      (message "Footnotes: [s]ort  |  [r]enumber fn:N  |  [S]=r+s |->[n]umeric 
 |  [d]elete")
-      (setq c (read-char-exclusive))
-      (cond
-       ((eq c ?s) (org-footnote-normalize 'sort))
-       ((eq c ?r) (org-footnote-renumber-fn:N))
-       ((eq c ?S)
-       (org-footnote-renumber-fn:N)
-       (org-footnote-normalize 'sort))
-       ((eq c ?n) (org-footnote-normalize))
-       ((eq c ?d) (org-footnote-delete))
-       (t (error "No such footnote command %c" c))))
-     ((setq tmp (org-footnote-at-reference-p))
-      (cond
-       ;; Anonymous footnote: move point at the beginning of its
-       ;; definition.
-       ((not (car tmp))
-       (goto-char (nth 1 tmp))
-       (forward-char 5))
-       ;; A definition exists: move to it.
-       ((ignore-errors (org-footnote-goto-definition (car tmp))))
-       ;; No definition exists: offer to create it.
-       ((yes-or-no-p (format "No definition for %s.  Create one? " (car tmp)))
-       (org-footnote-create-definition (car tmp)))))
-     ((setq tmp (org-footnote-at-definition-p))
-      (org-footnote-goto-previous-reference (car tmp)))
-     (t (org-footnote-new)))))
-
-;;;###autoload
-(defun org-footnote-normalize (&optional sort-only)
-  "Collect the footnotes in various formats and normalize them.
-
-This finds the different sorts of footnotes allowed in Org, and
-normalizes them to the usual [N] format.
-
-When SORT-ONLY is set, only sort the footnote definitions into the
-referenced sequence."
-  ;; This is based on Paul's function, but rewritten.
-  ;;
-  ;; Re-create `org-with-limited-levels', but not limited to Org
-  ;; buffers.
-  (let* ((limit-level
-         (and (boundp 'org-inlinetask-min-level)
-              org-inlinetask-min-level
-              (1- org-inlinetask-min-level)))
-        (nstars (and limit-level
-                     (if org-odd-levels-only (1- (* limit-level 2))
-                       limit-level)))
-        (org-outline-regexp
-         (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))
-        (count 0)
-        ins-point ref ref-table)
-    (save-excursion
-      ;; 1. Find every footnote reference, extract the definition, and
-      ;;    collect that data in REF-TABLE.  If SORT-ONLY is nil, also
-      ;;    normalize references.
-      (goto-char (point-min))
-      (while (setq ref (org-footnote-get-next-reference))
-       (let* ((lbl (car ref))
-              (pos (nth 1 ref))
-              ;; When footnote isn't anonymous, check if it's label
-              ;; (REF) is already stored in REF-TABLE.  In that case,
-              ;; extract number used to identify it (MARKER).  If
-              ;; footnote is unknown, increment the global counter
-              ;; (COUNT) to create an unused identifier.
-              (a (and lbl (assoc lbl ref-table)))
-              (marker (or (nth 1 a) (incf count)))
-              ;; Is the reference inline or pointing to an inline
-              ;; footnote?
-              (inlinep (or (stringp (nth 3 ref)) (nth 3 a))))
-         ;; Replace footnote reference with [MARKER].  Maybe fill
-         ;; paragraph once done.  If SORT-ONLY is non-nil, only move
-         ;; to the end of reference found to avoid matching it twice.
-         (if sort-only (goto-char (nth 2 ref))
-           (delete-region (nth 1 ref) (nth 2 ref))
-           (goto-char (nth 1 ref))
-           (insert (format "[%d]" marker))
-           (and inlinep
-                org-footnote-fill-after-inline-note-extraction
-                (org-fill-paragraph)))
-         ;; Add label (REF), identifier (MARKER), definition (DEF)
-         ;; type (INLINEP) and position (POS) to REF-TABLE if data
-         ;; was unknown.
-         (unless a
-           (let ((def (or (nth 3 ref)  ; Inline definition.
-                          (nth 3 (org-footnote-get-definition lbl)))))
-             (push (list lbl marker def
-                         ;; Reference beginning position is a marker
-                         ;; to preserve it during further buffer
-                         ;; modifications.
-                         inlinep (copy-marker pos)) ref-table)))))
-      ;; 2. Find and remove the footnote section, if any.  Also
-      ;;    determine where footnotes shall be inserted (INS-POINT).
-      (cond
-       ((and org-footnote-section (derived-mode-p 'org-mode))
-       (goto-char (point-min))
-       (if (re-search-forward
-            (concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
-                    "[ \t]*$") nil t)
-           (delete-region (match-beginning 0) (org-end-of-subtree t t)))
-       ;; A new footnote section is inserted by default at the end of
-       ;; the buffer.
-       (goto-char (point-max))
-       (skip-chars-backward " \r\t\n")
-       (forward-line)
-       (unless (bolp) (newline)))
-       ;; No footnote section set: Footnotes will be added at the end
-       ;; of the section containing their first reference.
-       ((derived-mode-p 'org-mode))
-       (t
-       ;; Remove any left-over tag in the buffer, if one is set up.
-       (when org-footnote-tag-for-non-org-mode-files
-         (let ((tag (concat "^" (regexp-quote
-                                 org-footnote-tag-for-non-org-mode-files)
-                            "[ \t]*$")))
-           (goto-char (point-min))
-           (while (re-search-forward tag nil t)
-             (replace-match "")
-             (delete-region (point) (progn (forward-line) (point))))))
-       ;; In Message mode, ensure footnotes are inserted before the
-       ;; signature.
-       (if (and (derived-mode-p 'message-mode)
-                (goto-char (point-max))
-                (re-search-backward message-signature-separator nil t))
-           (beginning-of-line)
-         (goto-char (point-max)))))
-      (setq ins-point (point-marker))
-      ;; 3. Clean-up REF-TABLE.
-      (setq ref-table
-           (delq nil
-                 (mapcar
-                  (lambda (x)
-                    (cond
-                     ;; When only sorting, ignore inline footnotes.
-                     ;; Also clear position marker.
-                     ((and sort-only (nth 3 x))
-                      (set-marker (nth 4 x) nil) nil)
-                     ;; No definition available: provide one.
-                     ((not (nth 2 x))
-                      (append
-                       (list (car x) (nth 1 x)
-                             (format "DEFINITION NOT FOUND: %s" (car x)))
-                       (nthcdr 3 x)))
-                     (t x)))
-                  ref-table)))
-      (setq ref-table (nreverse ref-table))
-      ;; 4. Remove left-over definitions in the buffer.
-      (mapc (lambda (x)
-             (unless (nth 3 x) (org-footnote-delete-definitions (car x))))
-           ref-table)
-      ;; 5. Insert the footnotes again in the buffer, at the
-      ;;    appropriate spot.
-      (goto-char ins-point)
-      (cond
-       ;; No footnote: exit.
-       ((not ref-table))
-       ;; Cases when footnotes should be inserted in one place.
-       ((or (not (derived-mode-p 'org-mode)) org-footnote-section)
-       ;; Insert again the section title, if any.  Ensure that title,
-       ;; or the subsequent footnotes, will be separated by a blank
-       ;; lines from the rest of the document.  In an Org buffer,
-       ;; separate section with a blank line, unless explicitly
-       ;; stated in `org-blank-before-new-entry'.
-       (if (not (derived-mode-p 'org-mode))
-           (progn (skip-chars-backward " \t\n\r")
-                  (delete-region (point) ins-point)
-                  (unless (bolp) (newline))
-                  (when org-footnote-tag-for-non-org-mode-files
-                    (insert "\n" org-footnote-tag-for-non-org-mode-files 
"\n")))
-         (when (and (cdr (assq 'heading org-blank-before-new-entry))
-                    (zerop (save-excursion (org-back-over-empty-lines))))
-           (insert "\n"))
-         (insert "* " org-footnote-section "\n"))
-       (set-marker ins-point nil)
-       ;; Insert the footnotes, separated by a blank line.
-       (insert
-        (mapconcat
-         (lambda (x)
-           ;; Clean markers.
-           (set-marker (nth 4 x) nil)
-           (format "\n[%s] %s" (nth (if sort-only 0 1) x) (nth 2 x)))
-         ref-table "\n"))
-       (unless (eobp) (insert "\n\n")))
-       ;; Each footnote definition has to be inserted at the end of
-       ;; the section where its first reference belongs.
-       (t
-       (mapc
-        (lambda (x)
-          (let ((pos (nth 4 x)))
-            (goto-char pos)
-            ;; Clean marker.
-            (set-marker pos nil))
-          (org-footnote-goto-local-insertion-point)
-          (insert (format "\n[%s] %s\n"
-                          (if sort-only (car x) (nth 1 x))
-                          (nth 2 x))))
-        ref-table))))))
-
-(defun org-footnote-goto-local-insertion-point ()
-  "Find insertion point for footnote, just before next outline heading."
-  (org-with-limited-levels (outline-next-heading))
-  (or (bolp) (newline))
-  (beginning-of-line 0)
-  (while (and (not (bobp)) (= (char-after) ?#))
-    (beginning-of-line 0))
-  (if (let ((case-fold-search t)) (looking-at "[ \t]*#\\+tblfm:")) 
(beginning-of-line 2))
-  (end-of-line 1)
-  (skip-chars-backward "\n\r\t ")
-  (forward-line))
+       electric-indent-mode)           ; Prevent wrong indentation.
+    (org-with-wide-buffer
+     (cond
+      ((not org-footnote-section) (org-footnote--goto-local-insertion-point))
+      ((save-excursion
+        (goto-char (point-min))
+        (re-search-forward
+         (concat "^\\*+[ \t]+" (regexp-quote org-footnote-section) "[ \t]*$")
+         nil t))
+       (goto-char (match-end 0))
+       (forward-line)
+       (unless (bolp) (insert "\n")))
+      (t (org-footnote--clear-footnote-section)))
+     (when (zerop (org-back-over-empty-lines)) (insert "\n"))
+     (insert "[fn:" label "] \n")
+     (line-beginning-position 0))))
 
 (defun org-footnote-delete-references (label)
   "Delete every reference to footnote LABEL.
@@ -789,7 +701,7 @@ Return the number of footnotes removed."
       (while (setq ref (org-footnote-get-next-reference label))
        (goto-char (nth 1 ref))
        (delete-region (nth 1 ref) (nth 2 ref))
-       (incf nref))
+       (cl-incf nref))
       nref)))
 
 (defun org-footnote-delete-definitions (label)
@@ -797,17 +709,21 @@ Return the number of footnotes removed."
 Return the number of footnotes removed."
   (save-excursion
     (goto-char (point-min))
-    (let ((def-re (concat "^\\[" (regexp-quote label) "\\]"))
+    (let ((def-re (format "^\\[fn:%s\\]" (regexp-quote label)))
          (ndef 0))
       (while (re-search-forward def-re nil t)
-       (let ((full-def (org-footnote-at-definition-p)))
-         (when full-def
-           ;; Remove the footnote, and all blank lines before it.
-           (goto-char (nth 1 full-def))
-           (skip-chars-backward " \r\t\n")
-           (unless (bolp) (forward-line))
-           (delete-region (point) (nth 2 full-def))
-           (incf ndef))))
+       (pcase (org-footnote-at-definition-p)
+         (`(,_ ,start ,end ,_)
+          ;; Remove the footnote, and all blank lines before it.
+          (delete-region (progn
+                           (goto-char start)
+                           (skip-chars-backward " \r\t\n")
+                           (if (bobp) (point) (line-beginning-position 2)))
+                         (progn
+                           (goto-char end)
+                           (skip-chars-backward " \r\t\n")
+                           (if (bobp) (point) (line-beginning-position 2))))
+          (cl-incf ndef))))
       ndef)))
 
 (defun org-footnote-delete (&optional label)
@@ -843,24 +759,165 @@ If LABEL is non-nil, delete that footnote instead."
       (message "%d definition(s) of and %d reference(s) of footnote %s removed"
               ndef nref label))))
 
+
+;;;; Sorting, Renumbering, Normalizing
+
 (defun org-footnote-renumber-fn:N ()
-  "Renumber the simple footnotes like fn:17 into a sequence in the document."
+  "Order numbered footnotes into a sequence in the document."
   (interactive)
-  (let (map (n 0))
-    (org-with-wide-buffer
-     (goto-char (point-min))
-     (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
-       (save-excursion
-        (goto-char (match-beginning 0))
-        ;; Ensure match is a footnote reference or definition.
-        (when (save-match-data (if (bolp)
-                                   (org-footnote-at-definition-p)
-                                 (org-footnote-at-reference-p)))
-          (let ((new-val (or (cdr (assoc (match-string 1) map))
-                             (number-to-string (incf n)))))
-            (unless (assoc (match-string 1) map)
-              (push (cons (match-string 1) new-val) map))
-            (replace-match new-val nil nil nil 1))))))))
+  (let ((references (org-footnote--collect-references)))
+    (unwind-protect
+       (let* ((c 0)
+              (references (cl-remove-if-not
+                           (lambda (r) (string-match-p "\\`[0-9]+\\'" (car r)))
+                           references))
+              (alist (mapcar (lambda (l) (cons l (number-to-string (cl-incf 
c))))
+                             (delete-dups (mapcar #'car references)))))
+         (org-with-wide-buffer
+          ;; Re-number references.
+          (dolist (ref references)
+            (goto-char (nth 1 ref))
+            (org-footnote--set-label (cdr (assoc (nth 0 ref) alist))))
+          ;; Re-number definitions.
+          (goto-char (point-min))
+          (while (re-search-forward "^\\[fn:\\([0-9]+\\)\\]" nil t)
+            (replace-match (or (cdr (assoc (match-string 1) alist))
+                               ;; Un-referenced definitions get
+                               ;; higher numbers.
+                               (number-to-string (cl-incf c)))
+                           nil nil nil 1))))
+      (dolist (r references) (set-marker (nth 1 r) nil)))))
+
+(defun org-footnote-sort ()
+  "Rearrange footnote definitions in the current buffer.
+Sort footnote definitions so they match order of footnote
+references.  Also relocate definitions at the end of their
+relative section or within a single footnote section, according
+to `org-footnote-section'.  Inline definitions are ignored."
+  (let ((references (org-footnote--collect-references)))
+    (unwind-protect
+       (let ((definitions (org-footnote--collect-definitions 'delete)))
+         (org-with-wide-buffer
+          (org-footnote--clear-footnote-section)
+          ;; Insert footnote definitions at the appropriate location,
+          ;; separated by a blank line.  Each definition is inserted
+          ;; only once throughout the buffer.
+          (let (inserted)
+            (dolist (cell references)
+              (let ((label (car cell))
+                    (nested (not (nth 2 cell)))
+                    (inline (nth 3 cell)))
+                (unless (or (member label inserted) inline)
+                  (push label inserted)
+                  (unless (or org-footnote-section nested)
+                    ;; If `org-footnote-section' is non-nil, or
+                    ;; reference is nested, point is already at the
+                    ;; correct position.  Otherwise, move at the
+                    ;; appropriate location within the section
+                    ;; containing the reference.
+                    (goto-char (nth 1 cell))
+                    (org-footnote--goto-local-insertion-point))
+                  (insert "\n"
+                          (or (cdr (assoc label definitions))
+                              (format "[fn:%s] DEFINITION NOT FOUND." label))
+                          "\n"))))
+            ;; Insert un-referenced footnote definitions at the end.
+            (let ((unreferenced
+                   (cl-remove-if (lambda (d) (member (car d) inserted))
+                                 definitions)))
+              (dolist (d unreferenced) (insert "\n" (cdr d) "\n"))))))
+      ;; Clear dangling markers in the buffer.
+      (dolist (r references) (set-marker (nth 1 r) nil)))))
+
+(defun org-footnote-normalize ()
+  "Turn every footnote in buffer into a numbered one."
+  (interactive)
+  (let ((references (org-footnote--collect-references 'anonymous)))
+    (unwind-protect
+       (let ((n 0)
+             (translations nil)
+             (definitions nil))
+         (org-with-wide-buffer
+          ;; Update label for reference.  We need to do this before
+          ;; clearing definitions in order to rename nested footnotes
+          ;; before they are deleted.
+          (dolist (cell references)
+            (let* ((label (car cell))
+                   (anonymous (not label))
+                   (new
+                    (cond
+                     ;; In order to differentiate anonymous
+                     ;; references from regular ones, set their
+                     ;; labels to integers, not strings.
+                     (anonymous (setcar cell (cl-incf n)))
+                     ((cdr (assoc label translations)))
+                     (t (let ((l (number-to-string (cl-incf n))))
+                          (push (cons label l) translations)
+                          l)))))
+              (goto-char (nth 1 cell)) ; Move to reference's start.
+              (org-footnote--set-label
+               (if anonymous (number-to-string new) new))
+              (let ((size (nth 3 cell)))
+                ;; Transform inline footnotes into regular references
+                ;; and retain their definition for later insertion as
+                ;; a regular footnote definition.
+                (when size
+                  (let ((def (concat
+                              (format "[fn:%s] " new)
+                              (org-trim
+                               (substring
+                                (delete-and-extract-region
+                                 (point) (+ (point) size 1))
+                                1)))))
+                    (push (cons (if anonymous new label) def) definitions)
+                    (when org-footnote-fill-after-inline-note-extraction
+                      (org-fill-paragraph)))))))
+          ;; Collect definitions.  Update labels according to ALIST.
+          (let ((definitions
+                  (nconc definitions
+                         (org-footnote--collect-definitions 'delete)))
+                (inserted))
+            (org-footnote--clear-footnote-section)
+            (dolist (cell references)
+              (let* ((label (car cell))
+                     (anonymous (integerp label))
+                     (pos (nth 1 cell)))
+                ;; Move to appropriate location, if required.  When
+                ;; there is a footnote section or reference is
+                ;; nested, point is already at the expected location.
+                (unless (or org-footnote-section (not (nth 2 cell)))
+                  (goto-char pos)
+                  (org-footnote--goto-local-insertion-point))
+                ;; Insert new definition once label is updated.
+                (unless (member label inserted)
+                  (push label inserted)
+                  (let ((stored (cdr (assoc label definitions)))
+                        ;; Anonymous footnotes' label is already
+                        ;; up-to-date.
+                        (new (if anonymous label
+                               (cdr (assoc label translations)))))
+                    (insert "\n"
+                            (cond
+                             ((not stored)
+                              (format "[fn:%s] DEFINITION NOT FOUND." new))
+                             (anonymous stored)
+                             (t
+                              (replace-regexp-in-string
+                               "\\`\\[fn:\\(.*?\\)\\]" new stored nil nil 1)))
+                            "\n")))))
+            ;; Insert un-referenced footnote definitions at the end.
+            (let ((unreferenced
+                   (cl-remove-if (lambda (d) (member (car d) inserted))
+                                 definitions)))
+              (dolist (d unreferenced)
+                (insert "\n"
+                        (replace-regexp-in-string
+                         org-footnote-definition-re
+                         (format "[fn:%d]" (cl-incf n))
+                         (cdr d))
+                        "\n"))))))
+      ;; Clear dangling markers.
+      (dolist (r references) (set-marker (nth 1 r) nil)))))
 
 (defun org-footnote-auto-adjust-maybe ()
   "Renumber and/or sort footnotes according to user settings."
@@ -868,14 +925,77 @@ If LABEL is non-nil, delete that footnote instead."
     (org-footnote-renumber-fn:N))
   (when (memq org-footnote-auto-adjust '(t sort))
     (let ((label (car (org-footnote-at-definition-p))))
-      (org-footnote-normalize 'sort)
+      (org-footnote-sort)
       (when label
        (goto-char (point-min))
-       (and (re-search-forward (concat "^\\[" (regexp-quote label) "\\]")
+       (and (re-search-forward (format "^\\[fn:%s\\]" (regexp-quote label))
                                nil t)
             (progn (insert " ")
                    (just-one-space)))))))
 
+
+;;;; End-user interface
+
+;;;###autoload
+(defun org-footnote-action (&optional special)
+  "Do the right thing for footnotes.
+
+When at a footnote reference, jump to the definition.
+
+When at a definition, jump to the references if they exist, offer
+to create them otherwise.
+
+When neither at definition or reference, create a new footnote,
+interactively if possible.
+
+With prefix arg SPECIAL, or when no footnote can be created,
+offer additional commands in a menu."
+  (interactive "P")
+  (let* ((context (and (not special) (org-element-context)))
+        (type (org-element-type context)))
+    (cond
+     ;; On white space after element, insert a new footnote.
+     ((and context
+          (> (point)
+             (save-excursion
+               (goto-char (org-element-property :end context))
+               (skip-chars-backward " \t")
+               (point))))
+      (org-footnote-new))
+     ((eq type 'footnote-reference)
+      (let ((label (org-element-property :label context)))
+       (cond
+        ;; Anonymous footnote: move point at the beginning of its
+        ;; definition.
+        ((not label)
+         (goto-char (org-element-property :contents-begin context)))
+        ;; Check if a definition exists: then move to it.
+        ((let ((p (nth 1 (org-footnote-get-definition label))))
+           (when p (org-footnote-goto-definition label p))))
+        ;; No definition exists: offer to create it.
+        ((yes-or-no-p (format "No definition for %s.  Create one? " label))
+         (let ((p (org-footnote-create-definition label)))
+           (or (ignore-errors (org-footnote-goto-definition label p))
+               ;; Since definition was created outside current scope,
+               ;; edit it remotely.
+               (org-edit-footnote-reference)))))))
+     ((eq type 'footnote-definition)
+      (org-footnote-goto-previous-reference
+       (org-element-property :label context)))
+     ((or special (not (org-footnote--allow-reference-p)))
+      (message "Footnotes: [s]ort | [r]enumber fn:N | [S]=r+s | [n]ormalize | \
+\[d]elete")
+      (pcase (read-char-exclusive)
+       (?s (org-footnote-sort))
+       (?r (org-footnote-renumber-fn:N))
+       (?S (org-footnote-renumber-fn:N)
+           (org-footnote-sort))
+       (?n (org-footnote-normalize))
+       (?d (org-footnote-delete))
+       (char (error "No such footnote command %c" char))))
+     (t (org-footnote-new)))))
+
+
 (provide 'org-footnote)
 
 ;; Local variables:
diff --git a/lisp/org/org-gnus.el b/lisp/org/org-gnus.el
index 1d287a7..b9d0989 100644
--- a/lisp/org/org-gnus.el
+++ b/lisp/org/org-gnus.el
@@ -1,4 +1,4 @@
-;;; org-gnus.el --- Support for links to Gnus groups and messages from within 
Org-mode
+;;; org-gnus.el --- Support for Links to Gnus Groups and Messages -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -25,8 +25,8 @@
 ;;
 ;;; Commentary:
 
-;; This file implements links to Gnus groups and messages from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; This file implements links to Gnus groups and messages from within Org.
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;;; Code:
@@ -36,18 +36,20 @@
 (eval-when-compile (require 'gnus-sum))
 
 ;; Declare external functions and variables
+
 (declare-function message-fetch-field "message" (header &optional not-all))
 (declare-function message-narrow-to-head-1 "message" nil)
-;; The following line suppresses a compiler warning stemming from gnus-sum.el
 (declare-function gnus-summary-last-subject "gnus-sum" nil)
+(declare-function nnvirtual-map-article "nnvirtual" (article))
+
 ;; Customization variables
 
-(org-defvaralias 'org-usenet-links-prefer-google 'org-gnus-prefer-web-links)
+(defvaralias 'org-usenet-links-prefer-google 'org-gnus-prefer-web-links)
 
 (defcustom org-gnus-prefer-web-links nil
   "If non-nil, `org-store-link' creates web links to Google groups or Gmane.
-When nil, Gnus will be used for such links.
-Using a prefix arg to the command \\[org-store-link] (`org-store-link')
+\\<org-mode-map>When nil, Gnus will be used for such links.
+Using a prefix argument to the command `\\[org-store-link]' (`org-store-link')
 negates this setting for the duration of the command."
   :group 'org-link-store
   :type 'boolean)
@@ -72,20 +74,21 @@ this variable to t."
   :type 'boolean)
 
 ;; Install the link type
-(org-add-link-type "gnus" 'org-gnus-open)
-(add-hook 'org-store-link-functions 'org-gnus-store-link)
+(org-link-set-parameters "gnus" :follow #'org-gnus-open :store 
#'org-gnus-store-link)
 
 ;; Implementation
 
-;; FIXME: nnimap-group-overview-filename was removed from Gnus in
-;; September 2010.  Perhaps remove this function?
 (defun org-gnus-nnimap-cached-article-number (group server message-id)
   "Return cached article number (uid) of message in GROUP on SERVER.
 MESSAGE-ID is the message-id header field that identifies the
 message.  If the uid is not cached, return nil."
   (with-temp-buffer
-    (let ((nov (nnimap-group-overview-filename group server)))
-      (when (file-exists-p nov)
+    (let ((nov (and (fboundp 'nnimap-group-overview-filename)
+                   ;; nnimap-group-overview-filename was removed from
+                   ;; Gnus in September 2010, and therefore should
+                   ;; only be present in Emacs 23.1.
+                   (nnimap-group-overview-filename group server))))
+      (when (and nov (file-exists-p nov))
        (mm-insert-file-contents nov)
        (set-buffer-modified-p nil)
        (goto-char (point-min))
@@ -104,7 +107,7 @@ Otherwise create a link to the group inside Gnus.
 If `org-store-link' was called with a prefix arg the meaning of
 `org-gnus-prefer-web-links' is reversed."
   (let ((unprefixed-group (replace-regexp-in-string "^[^:]+:" "" group)))
-    (if (and (string-match "^nntp" group) ;; Only for nntp groups
+    (if (and (string-prefix-p "nntp" group) ;; Only for nntp groups
             (org-xor current-prefix-arg
                      org-gnus-prefer-web-links))
        (concat (if (string-match "gmane" unprefixed-group)
@@ -156,21 +159,17 @@ If `org-store-link' was called with a prefix arg the 
meaning of
           (header (with-current-buffer gnus-summary-buffer
                     (gnus-summary-article-header)))
           (from (mail-header-from header))
-          (message-id (org-remove-angle-brackets (mail-header-id header)))
+          (message-id (org-unbracket-string "<" ">" (mail-header-id header)))
           (date (org-trim (mail-header-date header)))
-          (date-ts (and date
-                        (ignore-errors
-                          (format-time-string
-                           (org-time-stamp-format t)
-                           (date-to-time date)))))
-          (date-ts-ia (and date
-                           (ignore-errors
-                             (format-time-string
-                              (org-time-stamp-format t t)
-                              (date-to-time date)))))
           (subject (copy-sequence (mail-header-subject header)))
           (to (cdr (assq 'To (mail-header-extra header))))
           newsgroups x-no-archive desc link)
+      (cl-case  (car (gnus-find-method-for-group gnus-newsgroup-name))
+       (nnvirtual
+        (setq group (car (nnvirtual-map-article
+                          (gnus-summary-article-number)))))
+       (nnir
+        (setq group (nnir-article-group (gnus-summary-article-number)))))
       ;; Remove text properties of subject string to avoid Emacs bug
       ;; #3506
       (set-text-properties 0 (length subject) nil subject)
@@ -183,11 +182,8 @@ If `org-store-link' was called with a prefix arg the 
meaning of
        (setq to (or to (gnus-fetch-original-field "To"))
              newsgroups (gnus-fetch-original-field "Newsgroups")
              x-no-archive (gnus-fetch-original-field "x-no-archive")))
-      (org-store-link-props :type "gnus" :from from :subject subject
+      (org-store-link-props :type "gnus" :from from :date date :subject subject
                            :message-id message-id :group group :to to)
-      (when date
-       (org-add-link-props :date date :date-timestamp date-ts
-                           :date-timestamp-inactive date-ts-ia))
       (setq desc (org-email-link-description)
            link (org-gnus-article-link
                  group newsgroups message-id x-no-archive))
@@ -206,7 +202,7 @@ If `org-store-link' was called with a prefix arg the 
meaning of
         (let ((gcc (car (last
                          (message-unquote-tokens
                           (message-tokenize-header (mail-fetch-field "gcc" nil 
t) " ,")))))
-              (id (org-remove-angle-brackets (mail-fetch-field "Message-ID")))
+              (id (org-unbracket-string "<" ">" (mail-fetch-field 
"Message-ID")))
               (to (mail-fetch-field "To"))
               (from (mail-fetch-field "From"))
               (subject (mail-fetch-field "Subject"))
@@ -250,10 +246,8 @@ If `org-store-link' was called with a prefix arg the 
meaning of
   (require 'gnus)
   (funcall (cdr (assq 'gnus org-link-frame-setup)))
   (if gnus-other-frame-object (select-frame gnus-other-frame-object))
-  (when group
-    (setq group (org-no-properties group)))
-  (when article
-    (setq article (org-no-properties article)))
+  (setq group (org-no-properties group))
+  (setq article (org-no-properties article))
   (cond ((and group article)
         (gnus-activate-group group)
         (condition-case nil
diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el
index bbbf845..1f61565 100644
--- a/lisp/org/org-habit.el
+++ b/lisp/org/org-habit.el
@@ -1,4 +1,4 @@
-;;; org-habit.el --- The habit tracking code for Org-mode
+;;; org-habit.el --- The habit tracking code for Org -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
@@ -24,18 +24,16 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the habit tracking code for Org-mode
+;; This file contains the habit tracking code for Org mode
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'org)
 (require 'org-agenda)
 
-(eval-when-compile
-  (require 'cl))
-
 (defgroup org-habit nil
-  "Options concerning habit tracking in Org-mode."
+  "Options concerning habit tracking in Org mode."
   :tag "Org Habit"
   :group 'org-progress)
 
@@ -165,16 +163,17 @@ Returns a list with the following elements:
   2: Optional deadline (nil if not present)
   3: If deadline, the repeater for the deadline, otherwise nil
   4: A list of all the past dates this todo was mark closed
+  5: Repeater type as a string
 
 This list represents a \"habit\" for the rest of this module."
   (save-excursion
     (if pom (goto-char pom))
-    (assert (org-is-habit-p (point)))
+    (cl-assert (org-is-habit-p (point)))
     (let* ((scheduled (org-get-scheduled-time (point)))
           (scheduled-repeat (org-get-repeat org-scheduled-string))
           (end (org-entry-end-position))
           (habit-entry (org-no-properties (nth 4 (org-heading-components))))
-          closed-dates deadline dr-days sr-days)
+          closed-dates deadline dr-days sr-days sr-type)
       (if scheduled
          (setq scheduled (time-to-days scheduled))
        (error "Habit %s has no scheduled date" habit-entry))
@@ -182,7 +181,9 @@ This list represents a \"habit\" for the rest of this 
module."
        (error
         "Habit `%s' has no scheduled repeat period or has an incorrect one"
         habit-entry))
-      (setq sr-days (org-habit-duration-to-days scheduled-repeat))
+      (setq sr-days (org-habit-duration-to-days scheduled-repeat)
+           sr-type (progn (string-match "[\\.+]?\\+" scheduled-repeat)
+                          (match-string-no-properties 0 scheduled-repeat)))
       (unless (> sr-days 0)
        (error "Habit %s scheduled repeat period is less than 1d" habit-entry))
       (when (string-match "/\\([0-9]+[dwmy]\\)" scheduled-repeat)
@@ -197,17 +198,33 @@ This list represents a \"habit\" for the rest of this 
module."
             (reversed org-log-states-order-reversed)
             (search (if reversed 're-search-forward 're-search-backward))
             (limit (if reversed end (point)))
-            (count 0))
+            (count 0)
+            (re (format
+                 "^[ \t]*-[ \t]+\\(?:State \"%s\".*%s%s\\)"
+                 (regexp-opt org-done-keywords)
+                 org-ts-regexp-inactive
+                 (let ((value (cdr (assq 'done org-log-note-headings))))
+                   (if (not value) ""
+                     (concat "\\|"
+                             (org-replace-escapes
+                              (regexp-quote value)
+                              `(("%d" . ,org-ts-regexp-inactive)
+                                ("%D" . ,org-ts-regexp)
+                                ("%s" . "\"\\S-+\"")
+                                ("%S" . "\"\\S-+\"")
+                                ("%t" . ,org-ts-regexp-inactive)
+                                ("%T" . ,org-ts-regexp)
+                                ("%u" . ".*?")
+                                ("%U" . ".*?")))))))))
        (unless reversed (goto-char end))
-       (while (and (< count maxdays)
-                   (funcall search (format "- State \"%s\".*\\[\\([^]]+\\)\\]"
-                                           (regexp-opt org-done-keywords))
-                            limit t))
+       (while (and (< count maxdays) (funcall search re limit t))
          (push (time-to-days
-                (org-time-string-to-time (match-string-no-properties 1)))
+                (org-time-string-to-time
+                 (or (match-string-no-properties 1)
+                     (match-string-no-properties 2))))
                closed-dates)
          (setq count (1+ count))))
-      (list scheduled sr-days deadline dr-days closed-dates))))
+      (list scheduled sr-days deadline dr-days closed-dates sr-type))))
 
 (defsubst org-habit-scheduled (habit)
   (nth 0 habit))
@@ -225,6 +242,8 @@ This list represents a \"habit\" for the rest of this 
module."
       (org-habit-scheduled-repeat habit)))
 (defsubst org-habit-done-dates (habit)
   (nth 4 habit))
+(defsubst org-habit-repeat-type (habit)
+  (nth 5 habit))
 
 (defsubst org-habit-get-priority (habit &optional moment)
   "Determine the relative priority of a habit.
@@ -265,7 +284,6 @@ Habits are assigned colors on the following basis:
            schedule's repeat period."
   (let* ((scheduled (or scheduled-days (org-habit-scheduled habit)))
         (s-repeat (org-habit-scheduled-repeat habit))
-        (scheduled-end (+ scheduled (1- s-repeat)))
         (d-repeat (org-habit-deadline-repeat habit))
         (deadline (if scheduled-days
                       (+ scheduled-days (- d-repeat s-repeat))
@@ -289,13 +307,14 @@ Habits are assigned colors on the following basis:
 CURRENT gives the current time between STARTING and ENDING, for
 the purpose of drawing the graph.  It need not be the actual
 current time."
-  (let* ((done-dates (sort (org-habit-done-dates habit) '<))
+  (let* ((all-done-dates (sort (org-habit-done-dates habit) #'<))
+        (done-dates all-done-dates)
         (scheduled (org-habit-scheduled habit))
         (s-repeat (org-habit-scheduled-repeat habit))
         (start (time-to-days starting))
         (now (time-to-days current))
         (end (time-to-days ending))
-        (graph (make-string (1+ (- end start)) ?\ ))
+        (graph (make-string (1+ (- end start)) ?\s))
         (index 0)
         last-done-date)
     (while (and done-dates (< (car done-dates) start))
@@ -304,18 +323,55 @@ current time."
     (while (< start end)
       (let* ((in-the-past-p (< start now))
             (todayp (= start now))
-            (donep (and done-dates
-                        (= start (car done-dates))))
-            (faces (if (and in-the-past-p
-                            (not last-done-date)
-                            (not (< scheduled now)))
-                       '(org-habit-clear-face . org-habit-clear-future-face)
-                     (org-habit-get-faces
-                      habit start (and in-the-past-p
-                                       (if last-done-date
-                                           (+ last-done-date s-repeat)
-                                         scheduled))
-                      donep)))
+            (donep (and done-dates (= start (car done-dates))))
+            (faces
+             (if (and in-the-past-p
+                      (not last-done-date)
+                      (not (< scheduled now)))
+                 '(org-habit-clear-face . org-habit-clear-future-face)
+               (org-habit-get-faces
+                habit start
+                (and in-the-past-p
+                     last-done-date
+                     ;; Compute scheduled time for habit at the time
+                     ;; START was current.
+                     (let ((type (org-habit-repeat-type habit)))
+                       (cond
+                        ;; At the last done date, use current
+                        ;; scheduling in all cases.
+                        ((null done-dates) scheduled)
+                        ((equal type ".+") (+ last-done-date s-repeat))
+                        ((equal type "+")
+                         ;; Since LAST-DONE-DATE, each done mark
+                         ;; shifted scheduled date by S-REPEAT.
+                         (- scheduled (* (length done-dates) s-repeat)))
+                        (t
+                         ;; Compute the scheduled time after the
+                         ;; first repeat.  This is the closest time
+                         ;; past FIRST-DONE which can reach SCHEDULED
+                         ;; by a number of S-REPEAT hops.
+                         ;;
+                         ;; Then, play TODO state change history from
+                         ;; the beginning in order to find current
+                         ;; scheduled time.
+                         (let* ((first-done (car all-done-dates))
+                                (s (let ((shift (mod (- scheduled first-done)
+                                                     s-repeat)))
+                                     (+ (if (= shift 0) s-repeat shift)
+                                        first-done))))
+                           (if (= first-done last-done-date) s
+                             (catch :exit
+                               (dolist (done (cdr all-done-dates) s)
+                                 ;; Each repeat shifts S by any
+                                 ;; number of S-REPEAT hops it takes
+                                 ;; to get past DONE, with a minimum
+                                 ;; of one hop.
+                                 (cl-incf s (* (1+ (/ (max (- done s) 0)
+                                                      s-repeat))
+                                               s-repeat))
+                                 (when (= done last-done-date)
+                                   (throw :exit s))))))))))
+                donep)))
             markedp face)
        (if donep
            (let ((done-time (time-add
@@ -348,7 +404,7 @@ current time."
 
 (defun org-habit-insert-consistency-graphs (&optional line)
   "Insert consistency graph for any habitual tasks."
-  (let ((inhibit-read-only t) l c
+  (let ((inhibit-read-only t)
        (buffer-invisibility-spec '(org-link))
        (moment (time-subtract (current-time)
                               (list 0 (* 3600 org-extend-today-until) 0))))
diff --git a/lisp/org/org-id.el b/lisp/org/org-id.el
index 54fc733..f07d243 100644
--- a/lisp/org/org-id.el
+++ b/lisp/org/org-id.el
@@ -1,4 +1,4 @@
-;;; org-id.el --- Global identifiers for Org-mode entries
+;;; org-id.el --- Global identifiers for Org entries -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 ;;
@@ -24,7 +24,7 @@
 ;;
 ;;; Commentary:
 
-;; This file implements globally unique identifiers for Org-mode entries.
+;; This file implements globally unique identifiers for Org entries.
 ;; Identifiers are stored in the entry as an :ID: property.  Functions
 ;; are provided that create and retrieve such identifiers, and that find
 ;; entries based on the identifier.
@@ -73,20 +73,17 @@
 (require 'org)
 
 (declare-function message-make-fqdn "message" ())
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
 
 ;;; Customization
 
 (defgroup org-id nil
-  "Options concerning global entry identifiers in Org-mode."
+  "Options concerning global entry identifiers in Org mode."
   :tag "Org ID"
   :group 'org)
 
-(define-obsolete-variable-alias
-  'org-link-to-org-use-id 'org-id-link-to-org-use-id "24.3")
 (defcustom org-id-link-to-org-use-id nil
   "Non-nil means storing a link to an Org file will use entry IDs.
+\\<org-mode-map>\
 
 The variable can have the following values:
 
@@ -101,7 +98,7 @@ create-if-interactive
       call `org-capture' that automatically and preemptively creates a
       link.  If you do want to get an ID link in a capture template to
       an entry not having an ID, create it first by explicitly creating
-      a link to it, using `C-c C-l' first.
+      a link to it, using `\\[org-store-link]' first.
 
 create-if-interactive-and-no-custom-id
       Like create-if-interactive, but do not create an ID if there is
@@ -203,7 +200,7 @@ This variable is only relevant when `org-id-track-globally' 
is set."
 When Org reparses files to remake the list of files and IDs it is tracking,
 it will normally scan the agenda files, the archives related to agenda files,
 any files that are listed as ID containing in the current register, and
-any Org-mode files currently visited by Emacs.
+any Org file currently visited by Emacs.
 You can list additional files here.
 This variable is only relevant when `org-id-track-globally' is set."
   :group 'org-id
@@ -277,7 +274,7 @@ If necessary, the ID is created."
       (move-marker pom nil))))
 
 ;;;###autoload
-(defun org-id-get-with-outline-drilling (&optional targets)
+(defun org-id-get-with-outline-drilling ()
   "Use an outline-cycling interface to retrieve the ID of an entry.
 This only finds entries in the current buffer, using `org-get-location'.
 It returns the ID of the entry.  If necessary, the ID is created."
@@ -294,7 +291,7 @@ Move the cursor to that entry in that buffer."
   (let ((m (org-id-find id 'marker)))
     (unless m
       (error "Cannot find entry with ID \"%s\"" id))
-    (org-pop-to-buffer-same-window (marker-buffer m))
+    (pop-to-buffer-same-window (marker-buffer m))
     (goto-char m)
     (move-marker m nil)
     (org-show-context)))
@@ -447,8 +444,7 @@ and time is the usual three-integer representation of time."
 Store the relation between files and corresponding IDs.
 This will scan all agenda files, all associated archives, and all
 files currently mentioned in `org-id-locations'.
-When FILES is given, scan these files instead.
-When CHECK is given, prepare detailed information about duplicate IDs."
+When FILES is given, scan these files instead."
   (interactive)
   (if (not org-id-track-globally)
       (error "Please turn on `org-id-track-globally' if you want to track IDs")
@@ -466,7 +462,7 @@ When CHECK is given, prepare detailed information about 
duplicate IDs."
                 (if (symbolp org-id-extra-files)
                     (symbol-value org-id-extra-files)
                   org-id-extra-files)
-                ;; Files associated with live org-mode buffers
+                ;; Files associated with live Org buffers
                 (delq nil
                       (mapcar (lambda (b)
                                 (with-current-buffer b
@@ -494,7 +490,7 @@ When CHECK is given, prepare detailed information about 
duplicate IDs."
                (goto-char (point-min))
                (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$"
                                          nil t)
-                 (setq id (org-match-string-no-properties 1))
+                 (setq id (match-string-no-properties 1))
                  (if (member id found)
                      (progn
                        (message "Duplicate ID \"%s\", also in file %s"
@@ -678,7 +674,7 @@ optional argument MARKERP, return the position as a new 
marker."
     (move-marker m nil)
     (org-show-context)))
 
-(org-add-link-type "id" 'org-id-open)
+(org-link-set-parameters "id" :follow #'org-id-open)
 
 (provide 'org-id)
 
diff --git a/lisp/org/org-indent.el b/lisp/org/org-indent.el
index baaff2f..10c9617 100644
--- a/lisp/org/org-indent.el
+++ b/lisp/org/org-indent.el
@@ -1,4 +1,5 @@
-;;; org-indent.el --- Dynamic indentation for  Org-mode
+;;; org-indent.el --- Dynamic indentation for Org    -*- lexical-binding: t; 
-*-
+
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
@@ -39,8 +40,7 @@
 (require 'org-compat)
 (require 'org)
 
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 
 (declare-function org-inlinetask-get-task-level "org-inlinetask" ())
 (declare-function org-inlinetask-in-task-p "org-inlinetask" ())
@@ -52,20 +52,6 @@
   :tag "Org Indent"
   :group 'org)
 
-(defconst org-indent-max 40
-  "Maximum indentation in characters.")
-(defconst org-indent-max-levels 20
-  "Maximum added level through virtual indentation, in characters.
-
-It is computed by multiplying `org-indent-indentation-per-level'
-minus one by actual level of the headline minus one.")
-
-(defvar org-indent-strings nil
-  "Vector with all indentation strings.
-It will be set in `org-indent-initialize'.")
-(defvar org-indent-stars nil
-  "Vector with all indentation star strings.
-It will be set in `org-indent-initialize'.")
 (defvar org-indent-inlinetask-first-star (org-add-props "*" '(face 
org-warning))
   "First star of inline tasks, with correct face.")
 (defvar org-indent-agent-timer nil
@@ -82,7 +68,7 @@ Delay used when the buffer to initialize is current.")
 Delay used when the buffer to initialize isn't current.")
 (defvar org-indent-agent-resume-delay '(0 0 100000)
   "Minimal time for other idle processes before switching back to agent.")
-(defvar org-indent-initial-marker nil
+(defvar org-indent--initial-marker nil
   "Position of initialization before interrupt.
 This is used locally in each buffer being initialized.")
 (defvar org-hide-leading-stars-before-indent-mode nil
@@ -92,15 +78,12 @@ This is used locally in each buffer being initialized.")
 It is modified by `org-indent-notify-modified-headline'.")
 
 
-(defcustom org-indent-boundary-char ?\   ; comment to protect space char
+(defcustom org-indent-boundary-char ?\s
   "The end of the virtual indentation strings, a single-character string.
 The default is just a space, but if you wish, you can use \"|\" or so.
 This can be useful on a terminal window - under a windowing system,
-it may be prettier to customize the org-indent face."
+it may be prettier to customize the `org-indent' face."
   :group 'org-indent
-  :set (lambda (var val)
-        (set var val)
-        (and org-indent-strings (org-indent-initialize)))
   :type 'character)
 
 (defcustom org-indent-mode-turns-off-org-adapt-indentation t
@@ -121,29 +104,56 @@ turn on `org-hide-leading-stars'."
   :group 'org-indent
   :type 'integer)
 
-(defface org-indent
-  (org-compatible-face nil nil)
+(defface org-indent '((t (:inherit org-hide)))
   "Face for outline indentation.
 The default is to make it look like whitespace.  But you may find it
 useful to make it ever so slightly different."
   :group 'org-faces)
 
-(defun org-indent-initialize ()
-  "Initialize the indentation strings."
-  (setq org-indent-strings (make-vector (1+ org-indent-max) nil))
-  (setq org-indent-stars (make-vector (1+ org-indent-max) nil))
-  (aset org-indent-strings 0 nil)
-  (aset org-indent-stars 0 nil)
-  (loop for i from 1 to org-indent-max do
-       (aset org-indent-strings i
-             (org-add-props
-                 (concat (make-string (1- i) ?\ )
-                         (char-to-string org-indent-boundary-char))
+(defvar org-indent--text-line-prefixes nil
+  "Vector containing line prefixes strings for regular text.")
+
+(defvar org-indent--heading-line-prefixes nil
+  "Vector containing line prefix strings for headlines.")
+
+(defvar org-indent--inlinetask-line-prefixes nil
+  "Vector containing line prefix strings for inline tasks.")
+
+(defconst org-indent--deepest-level 50
+  "Maximum theoretical headline depth.")
+
+(defun org-indent--compute-prefixes ()
+  "Compute prefix strings for regular text and headlines."
+  (setq org-indent--heading-line-prefixes
+       (make-vector org-indent--deepest-level nil))
+  (setq org-indent--inlinetask-line-prefixes
+       (make-vector org-indent--deepest-level nil))
+  (setq org-indent--text-line-prefixes
+       (make-vector org-indent--deepest-level nil))
+  (dotimes (n org-indent--deepest-level)
+    (let ((indentation (if (<= n 1) 0
+                        (* (1- org-indent-indentation-per-level)
+                           (1- n)))))
+      ;; Headlines line prefixes.
+      (let ((heading-prefix (make-string indentation ?*)))
+       (aset org-indent--heading-line-prefixes
+             n
+             (org-add-props heading-prefix nil 'face 'org-indent))
+       ;; Inline tasks line prefixes
+       (aset org-indent--inlinetask-line-prefixes
+             n
+             (org-add-props (if (bound-and-true-p 
org-inlinetask-show-first-star)
+                                (concat org-indent-inlinetask-first-star
+                                        (substring heading-prefix 1))
+                              heading-prefix)
                  nil 'face 'org-indent)))
-  (loop for i from 1 to org-indent-max-levels do
-       (aset org-indent-stars i
-             (org-add-props (make-string i ?*)
-                 nil 'face 'org-hide))))
+      ;; Text line prefixes.
+      (aset org-indent--text-line-prefixes
+           n
+           (concat (org-add-props (make-string (+ n indentation) ?\s)
+                       nil 'face 'org-indent)
+                   (and (> n 0)
+                        (char-to-string org-indent-boundary-char)))))))
 
 (defsubst org-indent-remove-properties (beg end)
   "Remove indentations between BEG and END."
@@ -162,34 +172,25 @@ buffer, which can take a few seconds on large buffers, is 
done
 during idle time."
   nil " Ind" nil
   (cond
-   ((and org-indent-mode (featurep 'xemacs))
-    (message "org-indent-mode does not work in XEmacs - refusing to turn it 
on")
-    (setq org-indent-mode nil))
-   ((and org-indent-mode
-        (not (org-version-check "23.1.50" "Org Indent mode" :predicate)))
-    (message "org-indent-mode can crash Emacs 23.1 - refusing to turn it on!")
-    (ding)
-    (sit-for 1)
-    (setq org-indent-mode nil))
    (org-indent-mode
     ;; mode was turned on.
-    (org-set-local 'indent-tabs-mode nil)
-    (or org-indent-strings (org-indent-initialize))
-    (org-set-local 'org-indent-initial-marker (copy-marker 1))
+    (setq-local indent-tabs-mode nil)
+    (setq-local org-indent--initial-marker (copy-marker 1))
     (when org-indent-mode-turns-off-org-adapt-indentation
-      (org-set-local 'org-adapt-indentation nil))
+      (setq-local org-adapt-indentation nil))
     (when org-indent-mode-turns-on-hiding-stars
-      (org-set-local 'org-hide-leading-stars-before-indent-mode
-                    org-hide-leading-stars)
-      (org-set-local 'org-hide-leading-stars t))
-    (org-add-hook 'filter-buffer-substring-functions
-                 (lambda (fun start end delete)
-                   (org-indent-remove-properties-from-string
-                    (funcall fun start end delete)))
-                 nil t)
-    (org-add-hook 'after-change-functions 'org-indent-refresh-maybe nil 'local)
-    (org-add-hook 'before-change-functions
-                 'org-indent-notify-modified-headline nil 'local)
+      (setq-local org-hide-leading-stars-before-indent-mode
+                 org-hide-leading-stars)
+      (setq-local org-hide-leading-stars t))
+    (org-indent--compute-prefixes)
+    (add-hook 'filter-buffer-substring-functions
+             (lambda (fun start end delete)
+               (org-indent-remove-properties-from-string
+                (funcall fun start end delete)))
+             nil t)
+    (add-hook 'after-change-functions 'org-indent-refresh-maybe nil 'local)
+    (add-hook 'before-change-functions
+             'org-indent-notify-modified-headline nil 'local)
     (and font-lock-mode (org-restart-font-lock))
     (org-indent-remove-properties (point-min) (point-max))
     ;; Submit current buffer to initialize agent.  If it's the first
@@ -205,11 +206,11 @@ during idle time."
     (kill-local-variable 'org-adapt-indentation)
     (setq org-indent-agentized-buffers
          (delq (current-buffer) org-indent-agentized-buffers))
-    (when (markerp org-indent-initial-marker)
-      (set-marker org-indent-initial-marker nil))
+    (when (markerp org-indent--initial-marker)
+      (set-marker org-indent--initial-marker nil))
     (when (boundp 'org-hide-leading-stars-before-indent-mode)
-      (org-set-local 'org-hide-leading-stars
-                    org-hide-leading-stars-before-indent-mode))
+      (setq-local org-hide-leading-stars
+                 org-hide-leading-stars-before-indent-mode))
     (remove-hook 'filter-buffer-substring-functions
                 (lambda (fun start end delete)
                   (org-indent-remove-properties-from-string
@@ -245,7 +246,7 @@ When no more buffer is being watched, the agent suppress 
itself."
   (when org-indent-agent-resume-timer
     (cancel-timer org-indent-agent-resume-timer))
   (setq org-indent-agentized-buffers
-       (org-remove-if-not #'buffer-live-p org-indent-agentized-buffers))
+       (cl-remove-if-not #'buffer-live-p org-indent-agentized-buffers))
   (cond
    ;; Job done:  kill agent.
    ((not org-indent-agentized-buffers) (cancel-timer org-indent-agent-timer))
@@ -269,46 +270,44 @@ a time value."
        (let ((interruptp
              ;; Always nil unless interrupted.
              (catch 'interrupt
-               (and org-indent-initial-marker
-                    (marker-position org-indent-initial-marker)
-                    (org-indent-add-properties org-indent-initial-marker
+               (and org-indent--initial-marker
+                    (marker-position org-indent--initial-marker)
+                    (equal (marker-buffer org-indent--initial-marker)
+                           buffer)
+                    (org-indent-add-properties org-indent--initial-marker
                                                (point-max)
                                                delay)
                     nil))))
-        (move-marker org-indent-initial-marker interruptp)
+        (move-marker org-indent--initial-marker interruptp)
         ;; Job is complete: un-agentize buffer.
         (unless interruptp
           (setq org-indent-agentized-buffers
                 (delq buffer org-indent-agentized-buffers))))))))
 
-(defsubst org-indent-set-line-properties (l w h)
+(defun org-indent-set-line-properties (level indentation &optional heading)
   "Set prefix properties on current line an move to next one.
 
-Prefix properties `line-prefix' and `wrap-prefix' in current line
-are set to, respectively, length L and W.
-
-If H is non-nil, `line-prefix' will be starred.  If H is
-`inline', the first star will have `org-warning' face.
-
-Assume point is at beginning of line."
-  (let ((line (cond
-              ((eq 'inline h)
-               (let ((stars (aref org-indent-stars
-                                  (min l org-indent-max-levels))))
-                 (and stars
-                      (if (org-bound-and-true-p org-inlinetask-show-first-star)
-                          (concat org-indent-inlinetask-first-star
-                                  (substring stars 1))
-                        stars))))
-              (h (aref org-indent-stars
-                       (min l org-indent-max-levels)))
-              (t (aref org-indent-strings
-                       (min l org-indent-max)))))
-       (wrap (aref org-indent-strings (min w org-indent-max))))
+LEVEL is the current level of heading.  INDENTATION is the
+expected indentation when wrapping line.
+
+When optional argument HEADING is non-nil, assume line is at
+a heading.  Moreover, if is is `inlinetask', the first star will
+have `org-warning' face."
+  (let* ((line (aref (pcase heading
+                      (`nil org-indent--text-line-prefixes)
+                      (`inlinetask org-indent--inlinetask-line-prefixes)
+                      (_ org-indent--heading-line-prefixes))
+                    level))
+        (wrap
+         (org-add-props
+             (concat line
+                     (if heading (concat (make-string level ?*) " ")
+                       (make-string indentation ?\s)))
+             nil 'face 'org-indent)))
     ;; Add properties down to the next line to indent empty lines.
-    (add-text-properties (point) (min (1+ (point-at-eol)) (point-max))
+    (add-text-properties (line-beginning-position) (line-beginning-position 2)
                         `(line-prefix ,line wrap-prefix ,wrap)))
-  (forward-line 1))
+  (forward-line))
 
 (defun org-indent-add-properties (beg end &optional delay)
   "Add indentation properties between BEG and END.
@@ -322,26 +321,14 @@ stopped."
     (org-with-wide-buffer
      (goto-char beg)
      (beginning-of-line)
-     ;; 1. Initialize prefix at BEG.  This is done by storing two
-     ;;    variables: INLINE-PF and PF, representing respectively
-     ;;    length of current `line-prefix' when line is inside an
-     ;;    inline task or not.
+     ;; Initialize prefix at BEG, according to current entry's level.
      (let* ((case-fold-search t)
            (limited-re (org-get-limited-outline-regexp))
-           (added-ind-per-lvl (abs (1- org-indent-indentation-per-level)))
-           (pf (save-excursion
-                 (and (ignore-errors (let ((outline-regexp limited-re))
-                                       (org-back-to-heading t)))
-                      (+ (* org-indent-indentation-per-level
-                            (- (match-end 0) (match-beginning 0) 2)) 2))))
-           (pf-inline (and (featurep 'org-inlinetask)
-                           (org-inlinetask-in-task-p)
-                           (+ (* org-indent-indentation-per-level
-                                 (1- (org-inlinetask-get-task-level))) 2)))
+           (level (or (org-current-level) 0))
            (time-limit (and delay (time-add (current-time) delay))))
-       ;; 2. For each line, set `line-prefix' and `wrap-prefix'
-       ;;    properties depending on the type of line (headline,
-       ;;    inline task, item or other).
+       ;; For each line, set `line-prefix' and `wrap-prefix'
+       ;; properties depending on the type of line (headline, inline
+       ;; task, item or other).
        (org-with-silent-modifications
        (while (and (<= (point) end) (not (eobp)))
          (cond
@@ -354,38 +341,23 @@ stopped."
           ((and delay (time-less-p time-limit (current-time)))
            (setq org-indent-agent-resume-timer
                  (run-with-idle-timer
-                  (time-add (current-idle-time)
-                            org-indent-agent-resume-delay)
+                  (time-add (current-idle-time) org-indent-agent-resume-delay)
                   nil #'org-indent-initialize-agent))
            (throw 'interrupt (point)))
           ;; Headline or inline task.
           ((looking-at org-outline-regexp)
            (let* ((nstars (- (match-end 0) (match-beginning 0) 1))
-                  (line (* added-ind-per-lvl (1- nstars)))
-                  (wrap (+ line (1+ nstars))))
-             (cond
-              ;; Headline: new value for PF.
-              ((looking-at limited-re)
-               (org-indent-set-line-properties line wrap t)
-               (setq pf wrap))
-              ;; End of inline task: PF-INLINE is now nil.
-              ((looking-at "\\*+ end[ \t]*$")
-               (org-indent-set-line-properties line wrap 'inline)
-               (setq pf-inline nil))
-              ;; Start of inline task.  Determine if it contains
-              ;; text, or if it is only one line long.  Set
-              ;; PF-INLINE accordingly.
-              (t (org-indent-set-line-properties line wrap 'inline)
-                 (setq pf-inline (and (org-inlinetask-in-task-p) wrap))))))
+                  (type (or (looking-at-p limited-re) 'inlinetask)))
+             (org-indent-set-line-properties nstars 0 type)
+             ;; At an headline, define new value for LEVEL.
+             (unless (eq type 'inlinetask) (setq level nstars))))
           ;; List item: `wrap-prefix' is set where body starts.
           ((org-at-item-p)
-           (let* ((line (or pf-inline pf 0))
-                  (wrap (+ (org-list-item-body-column (point)) line)))
-             (org-indent-set-line-properties line wrap nil)))
-          ;; Normal line: use PF-INLINE, PF or nil as prefixes.
-          (t (let* ((line (or pf-inline pf 0))
-                    (wrap (+ line (org-get-indentation))))
-               (org-indent-set-line-properties line wrap nil))))))))))
+           (org-indent-set-line-properties
+            level (org-list-item-body-column (point))))
+          ;; Regular line.
+          (t
+           (org-indent-set-line-properties level (org-get-indentation))))))))))
 
 (defun org-indent-notify-modified-headline (beg end)
   "Set `org-indent-modified-headline-flag' depending on context.
@@ -398,13 +370,14 @@ Flag will be non-nil if command is going to modify or 
delete an
 headline."
   (when org-indent-mode
     (setq org-indent-modified-headline-flag
-         (save-excursion
-           (goto-char beg)
-           (save-match-data
-             (or (and (org-at-heading-p) (< beg (match-end 0)))
-                 (re-search-forward org-outline-regexp-bol end t)))))))
-
-(defun org-indent-refresh-maybe (beg end dummy)
+         (org-with-wide-buffer
+          (goto-char beg)
+          (save-match-data
+            (or (and (org-at-heading-p) (< beg (match-end 0)))
+                (re-search-forward
+                 (org-with-limited-levels org-outline-regexp-bol) end t)))))))
+
+(defun org-indent-refresh-maybe (beg end _)
   "Refresh indentation properties in an adequate portion of buffer.
 BEG and END are the positions of the beginning and end of the
 range of inserted text.  DUMMY is an unused argument.
@@ -414,19 +387,21 @@ This function is meant to be called by 
`after-change-functions'."
     (save-match-data
       ;; If a headline was modified or inserted, set properties until
       ;; next headline.
-      (if (or org-indent-modified-headline-flag
-             (save-excursion
-               (goto-char beg)
-               (beginning-of-line)
-               (re-search-forward org-outline-regexp-bol end t)))
-         (let ((end (save-excursion
-                      (goto-char end)
-                      (org-with-limited-levels (outline-next-heading))
-                      (point))))
-           (setq org-indent-modified-headline-flag nil)
-           (org-indent-add-properties beg end))
-       ;; Otherwise, only set properties on modified area.
-       (org-indent-add-properties beg end)))))
+      (org-with-wide-buffer
+       (if (or org-indent-modified-headline-flag
+              (save-excursion
+                (goto-char beg)
+                (beginning-of-line)
+                (re-search-forward
+                 (org-with-limited-levels org-outline-regexp-bol) end t)))
+          (let ((end (save-excursion
+                       (goto-char end)
+                       (org-with-limited-levels (outline-next-heading))
+                       (point))))
+            (setq org-indent-modified-headline-flag nil)
+            (org-indent-add-properties beg end))
+        ;; Otherwise, only set properties on modified area.
+        (org-indent-add-properties beg end))))))
 
 (provide 'org-indent)
 
diff --git a/lisp/org/org-info.el b/lisp/org/org-info.el
index c8f6f06..79b9bcc 100644
--- a/lisp/org/org-info.el
+++ b/lisp/org/org-info.el
@@ -1,4 +1,4 @@
-;;; org-info.el --- Support for links to Info nodes from within Org-Mode
+;;; org-info.el --- Support for Links to Info Nodes -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,8 +24,8 @@
 ;;
 ;;; Commentary:
 
-;; This file implements links to Info nodes from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; This file implements links to Info nodes from within Org mode.
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;;; Code:
@@ -40,19 +40,20 @@
 (defvar Info-current-node)
 
 ;; Install the link type
-(org-add-link-type "info" 'org-info-open)
-(add-hook 'org-store-link-functions 'org-info-store-link)
+(org-link-set-parameters "info"
+                        :follow #'org-info-open
+                        :export #'org-info-export
+                        :store #'org-info-store-link)
 
 ;; Implementation
 (defun org-info-store-link ()
   "Store a link to an Info file and node."
   (when (eq major-mode 'Info-mode)
-    (let (link desc)
-      (setq link (concat "info:"
-                        (file-name-nondirectory Info-current-file)
-                        "#" Info-current-node))
-      (setq desc (concat (file-name-nondirectory Info-current-file)
-                        "#" Info-current-node))
+    (let ((link (concat "info:"
+                       (file-name-nondirectory Info-current-file)
+                       "#" Info-current-node))
+         (desc (concat (file-name-nondirectory Info-current-file)
+                       "#" Info-current-node)))
       (org-store-link-props :type "info" :file Info-current-file
                            :node Info-current-node
                            :link link :desc desc)
@@ -67,12 +68,76 @@
   "Follow an Info file and node link specified by NAME."
   (if (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" name)
           (string-match "\\(.*\\)" name))
-      (progn
+      (let ((filename (match-string 1 name))
+           (nodename-or-index (or (match-string 2 name) "Top")))
        (require 'info)
-        (if (match-string 2 name) ; If there isn't a node, choose "Top"
-            (Info-find-node (match-string 1 name) (match-string 2 name))
-          (Info-find-node (match-string 1 name) "Top")))
-    (message "Could not open: %s" name)))
+       ;; If nodename-or-index is invalid node name, then look it up
+       ;; in the index.
+       (condition-case nil
+           (Info-find-node filename nodename-or-index)
+         (user-error (Info-find-node filename "Top")
+                     (condition-case nil
+                         (Info-index nodename-or-index)
+                       (user-error "Could not find '%s' node or index entry"
+                                   nodename-or-index)))))
+    (user-error "Could not open: %s" name)))
+
+(defconst org-info-emacs-documents
+  '("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
+    "ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eieio" "eintr" "elisp"
+    "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell" "eudc" "eww"
+    "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info" "mairix-el"
+    "message" "mh-e" "newsticker" "nxml-mode" "octave-mode" "org" "pcl-cvs"
+    "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic" "ses" "sieve"
+    "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "url" "vip" "viper"
+    "widget" "wisent" "woman")
+  "List of emacs documents available.
+Taken from <http://www.gnu.org/software/emacs/manual/html_mono/.>")
+
+(defconst org-info-other-documents
+  '(("libc" . "http://www.gnu.org/software/libc/manual/html_mono/libc.html";)
+    ("make" . "http://www.gnu.org/software/make/manual/make.html";))
+  "Alist of documents generated from Texinfo source.
+When converting info links to HTML, links to any one of these manuals are
+converted to use these URL.")
+
+(defun org-info-map-html-url (filename)
+  "Return URL or HTML file associated to Info FILENAME.
+If FILENAME refers to an official GNU document, return a URL pointing to
+the official page for that document, e.g., use \"gnu.org\" for all Emacs
+related documents.  Otherwise, append \".html\" extension to FILENAME.
+See `org-info-emacs-documents' and `org-info-other-documents' for details."
+  (cond ((member filename org-info-emacs-documents)
+        (format "http://www.gnu.org/software/emacs/manual/html_mono/%s.html";
+                filename))
+       ((cdr (assoc filename org-info-other-documents)))
+       (t (concat filename ".html"))))
+
+(defun org-info--expand-node-name (node)
+  "Expand Info NODE to HTML cross reference."
+  ;; See (info "(texinfo) HTML Xref Node Name Expansion") for the
+  ;; expansion rule.
+  (let ((node (replace-regexp-in-string
+              "\\([ \t\n\r]+\\)\\|\\([^a-zA-Z0-9]\\)"
+              (lambda (m)
+                (if (match-end 1) "-" (format "_%04x" (string-to-char m))))
+              (org-trim node))))
+    (cond ((string= node "") "")
+         ((string-match-p "\\`[0-9]" node) (concat "g_t" node))
+         (t node))))
+
+(defun org-info-export (path desc format)
+  "Export an info link.
+See `org-link-parameters' for details about PATH, DESC and FORMAT."
+  (when (eq format 'html)
+    (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" path)
+       (string-match "\\(.*\\)" path))
+    (let ((filename (match-string 1 path))
+         (node (or (match-string 2 path) "Top")))
+      (format "<a href=\"%s#%s\">%s</a>"
+             (org-info-map-html-url filename)
+             (org-info--expand-node-name node)
+             (or desc path)))))
 
 (provide 'org-info)
 
diff --git a/lisp/org/org-inlinetask.el b/lisp/org/org-inlinetask.el
index bf4ab20..2918d40 100644
--- a/lisp/org/org-inlinetask.el
+++ b/lisp/org/org-inlinetask.el
@@ -1,4 +1,4 @@
-;;; org-inlinetask.el --- Tasks independent of outline hierarchy
+;;; org-inlinetask.el --- Tasks Independent of Outline Hierarchy -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 ;;
@@ -26,7 +26,7 @@
 ;;
 ;;; Commentary:
 ;;
-;; This module implements inline tasks in Org-mode.  Inline tasks are
+;; This module implements inline tasks in Org mode.  Inline tasks are
 ;; tasks that have all the properties of normal outline nodes,
 ;; including the ability to store meta data like scheduling dates,
 ;; TODO state, tags and properties.  However, these nodes are treated
@@ -108,7 +108,6 @@ When nil, the first star is not shown."
 
 (defvar org-odd-levels-only)
 (defvar org-keyword-time-regexp)
-(defvar org-drawer-regexp)
 (defvar org-complex-heading-regexp)
 (defvar org-property-end-re)
 
@@ -168,9 +167,9 @@ The number of levels is controlled by 
`org-inlinetask-min-level'."
           (stars-re (org-inlinetask-outline-regexp))
           (task-beg-re (concat stars-re "\\(?:.*\\)"))
           (task-end-re (concat stars-re "END[ \t]*$")))
-      (or (org-looking-at-p task-beg-re)
+      (or (looking-at-p task-beg-re)
          (and (re-search-forward "^\\*+[ \t]+" nil t)
-              (progn (beginning-of-line) (org-looking-at-p task-end-re)))))))
+              (progn (beginning-of-line) (looking-at-p task-end-re)))))))
 
 (defun org-inlinetask-goto-beginning ()
   "Go to the beginning of the inline task at point."
@@ -178,7 +177,7 @@ The number of levels is controlled by 
`org-inlinetask-min-level'."
   (let ((case-fold-search t)
        (inlinetask-re (org-inlinetask-outline-regexp)))
     (re-search-backward inlinetask-re nil t)
-    (when (org-looking-at-p (concat inlinetask-re "END[ \t]*$"))
+    (when (looking-at-p (concat inlinetask-re "END[ \t]*$"))
       (re-search-backward inlinetask-re nil t))))
 
 (defun org-inlinetask-goto-end ()
@@ -190,17 +189,16 @@ Return point."
           (inlinetask-re (org-inlinetask-outline-regexp))
           (task-end-re (concat inlinetask-re "END[ \t]*$")))
       (cond
-       ((looking-at task-end-re) (forward-line))
+       ((looking-at task-end-re))
        ((looking-at inlinetask-re)
        (forward-line)
        (cond
-        ((looking-at task-end-re) (forward-line))
+        ((looking-at task-end-re))
         ((looking-at inlinetask-re))
         ((org-inlinetask-in-task-p)
-         (re-search-forward inlinetask-re nil t)
-         (forward-line))))
-       (t (re-search-forward inlinetask-re nil t)
-         (forward-line)))
+         (re-search-forward inlinetask-re nil t))))
+       (t (re-search-forward inlinetask-re nil t)))
+      (end-of-line)
       (point))))
 
 (defun org-inlinetask-get-task-level ()
@@ -273,8 +271,7 @@ If the task has an end part, also demote it."
 
 (defvar org-indent-indentation-per-level) ; defined in org-indent.el
 
-(defface org-inlinetask
-  (org-compatible-face 'shadow '((t (:bold t))))
+(defface org-inlinetask '((t :inherit shadow))
   "Face for inlinetask headlines."
   :group 'org-faces)
 
@@ -288,7 +285,7 @@ If the task has an end part, also demote it."
                     ",\\}\\)\\(\\*\\* .*\\)"))
         ;; Virtual indentation will add the warning face on the first
         ;; star.  Thus, in that case, only hide it.
-        (start-face (if (and (org-bound-and-true-p org-indent-mode)
+        (start-face (if (and (bound-and-true-p org-indent-mode)
                              (> org-indent-indentation-per-level 1))
                         'org-hide
                       'org-warning)))
@@ -315,19 +312,36 @@ If the task has an end part, also demote it."
      ;; Nothing to show/hide.
      ((= end start))
      ;; Inlinetask was folded: expand it.
-     ((get-char-property (1+ start) 'invisible)
+     ((eq (get-char-property (1+ start) 'invisible) 'outline)
       (outline-flag-region start end nil)
       (org-cycle-hide-drawers 'children))
      (t (outline-flag-region start end t)))))
 
+(defun org-inlinetask-hide-tasks (state)
+  "Hide inline tasks in buffer when STATE is `contents' or `children'.
+This function is meant to be used in `org-cycle-hook'."
+  (pcase state
+    (`contents
+     (let ((regexp (org-inlinetask-outline-regexp)))
+       (save-excursion
+        (goto-char (point-min))
+        (while (re-search-forward regexp nil t)
+          (org-inlinetask-toggle-visibility)
+          (org-inlinetask-goto-end)))))
+    (`children
+     (save-excursion
+       (while (and (outline-next-heading) (org-inlinetask-at-task-p))
+        (org-inlinetask-toggle-visibility)
+        (org-inlinetask-goto-end))))))
+
 (defun org-inlinetask-remove-END-maybe ()
   "Remove an END line when present."
   (when (looking-at (format "\\([ \t]*\n\\)*\\*\\{%d,\\}[ \t]+END[ \t]*$"
                            org-inlinetask-min-level))
     (replace-match "")))
 
-(eval-after-load "org"
-  '(add-hook 'org-font-lock-hook 'org-inlinetask-fontify))
+(add-hook 'org-font-lock-hook 'org-inlinetask-fontify)
+(add-hook 'org-cycle-hook 'org-inlinetask-hide-tasks)
 
 (provide 'org-inlinetask)
 
diff --git a/lisp/org/org-irc.el b/lisp/org/org-irc.el
index 1243587..3a6a7f4 100644
--- a/lisp/org/org-irc.el
+++ b/lisp/org/org-irc.el
@@ -1,4 +1,4 @@
-;;; org-irc.el --- Store links to IRC sessions
+;;; org-irc.el --- Store Links to IRC Sessions -*- lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 ;;
@@ -22,8 +22,8 @@
 
 ;;; Commentary:
 
-;; This file implements links to an IRC session from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; This file implements links to an IRC session from within Org mode.
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 ;;
 ;; Please customize the variable `org-modules' to select
@@ -59,8 +59,6 @@
 (declare-function erc-server-buffer "erc" ())
 (declare-function erc-get-server-nickname-list "erc" ())
 (declare-function erc-cmd-JOIN "erc" (channel &optional key))
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
 
 (defvar org-irc-client 'erc
   "The IRC client to act on.")
@@ -73,9 +71,7 @@
 
 ;; Generic functions/config (extend these for other clients)
 
-(add-to-list 'org-store-link-functions 'org-irc-store-link)
-
-(org-add-link-type "irc" 'org-irc-visit nil)
+(org-link-set-parameters "irc" :follow #'org-irc-visit :store 
#'org-irc-store-link)
 
 (defun org-irc-visit (link)
   "Parse LINK and dispatch to the correct function based on the client found."
@@ -114,11 +110,9 @@ chars that the value AFTER with `...'"
                            (cons "[ \t]*$" "")
                            (cons (concat "^\\(.\\{" after
                                          "\\}\\).*") "\\1..."))))
-    (mapc (lambda (x)
-           (when (string-match (car x) string)
-             (setq string (replace-match (cdr x) nil nil string))))
-         replace-map)
-    string))
+    (dolist (x replace-map string)
+      (when (string-match (car x) string)
+       (setq string (replace-match (cdr x) nil nil string))))))
 
 ;; ERC specific functions
 
@@ -233,7 +227,7 @@ default."
                                      (throw 'found x))))))
                (if chan-buf
                    (progn
-                     (org-pop-to-buffer-same-window chan-buf)
+                     (pop-to-buffer-same-window chan-buf)
                      ;; if we got a nick, and they're in the chan,
                      ;; then start a chat with them
                      (let ((nick (pop link)))
@@ -244,9 +238,9 @@ default."
                                (insert (concat nick ": ")))
                            (error "%s not found in %s" nick chan-name)))))
                  (progn
-                   (org-pop-to-buffer-same-window server-buffer)
+                   (pop-to-buffer-same-window server-buffer)
                    (erc-cmd-JOIN chan-name))))
-           (org-pop-to-buffer-same-window server-buffer)))
+           (pop-to-buffer-same-window server-buffer)))
       ;; no server match, make new connection
       (erc-select :server server :port port))))
 
diff --git a/lisp/org/org-lint.el b/lisp/org/org-lint.el
new file mode 100644
index 0000000..89aed4b
--- /dev/null
+++ b/lisp/org/org-lint.el
@@ -0,0 +1,1225 @@
+;;; org-lint.el --- Linting for Org documents        -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2015-2017  Free Software Foundation
+
+;; Author: Nicolas Goaziou <address@hidden>
+;; Keywords: outlines, hypermedia, calendar, wp
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library implements linting for Org syntax.  The sole public
+;; function is `org-lint', which see.
+
+;; Internally, the library defines a new structure:
+;; `org-lint-checker', with the following slots:
+
+;;   - NAME: Unique check identifier, as a non-nil symbol that doesn't
+;;     start with an hyphen.
+;;
+;;     The check is done calling the function `org-lint-NAME' with one
+;;     mandatory argument, the parse tree describing the current Org
+;;     buffer.  Such function calls are wrapped within
+;;     a `save-excursion' and point is always at `point-min'.  Its
+;;     return value has to be an alist (POSITION MESSAGE) when
+;;     POSITION refer to the buffer position of the error, as an
+;;     integer, and MESSAGE is a string describing the error.
+
+;;   - DESCRIPTION: Summary about the check, as a string.
+
+;;   - CATEGORIES: Categories relative to the check, as a list of
+;;     symbol.  They are used for filtering when calling `org-lint'.
+;;     Checkers not explicitly associated to a category are collected
+;;     in the `default' one.
+
+;;   - TRUST: The trust level one can have in the check.  It is either
+;;     `low' or `high', depending on the heuristics implemented and
+;;     the nature of the check.  This has an indicative value only and
+;;     is displayed along reports.
+
+;; All checks have to be listed in `org-lint--checkers'.
+
+;; Results are displayed in a special "*Org Lint*" buffer with
+;; a dedicated major mode, derived from `tabulated-list-mode'.
+;;
+;; In addition to the usual key-bindings inherited from it, "C-j" and
+;; "TAB" display problematic line reported under point whereas "RET"
+;; jumps to it.  Also, "h" hides all reports similar to the current
+;; one.  Additionally, "i" removes them from subsequent reports.
+
+;; Checks currently implemented are:
+
+;;   - duplicate CUSTOM_ID properties
+;;   - duplicate NAME values
+;;   - duplicate targets
+;;   - duplicate footnote definitions
+;;   - orphaned affiliated keywords
+;;   - obsolete affiliated keywords
+;;   - missing language in src blocks
+;;   - missing back-end in export blocks
+;;   - invalid Babel call blocks
+;;   - NAME values with a colon
+;;   - deprecated export block syntax
+;;   - deprecated Babel header properties
+;;   - wrong header arguments in src blocks
+;;   - misuse of CATEGORY keyword
+;;   - "coderef" links with unknown destination
+;;   - "custom-id" links with unknown destination
+;;   - "fuzzy" links with unknown destination
+;;   - "id" links with unknown destination
+;;   - links to non-existent local files
+;;   - SETUPFILE keywords with non-existent file parameter
+;;   - INCLUDE keywords with wrong link parameter
+;;   - obsolete markup in INCLUDE keyword
+;;   - unknown items in OPTIONS keyword
+;;   - spurious macro arguments or invalid macro templates
+;;   - special properties in properties drawer
+;;   - obsolete syntax for PROPERTIES drawers
+;;   - missing definition for footnote references
+;;   - missing reference for footnote definitions
+;;   - non-footnote definitions in footnote section
+;;   - probable invalid keywords
+;;   - invalid blocks
+;;   - misplaced planning info line
+;;   - incomplete drawers
+;;   - indented diary-sexps
+;;   - obsolete QUOTE section
+;;   - obsolete "file+application" link
+;;   - blank headlines with tags
+
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'org-element)
+(require 'org-macro)
+(require 'ox)
+(require 'ob)
+
+
+;;; Checkers
+
+(cl-defstruct (org-lint-checker (:copier nil))
+  (name 'missing-checker-name)
+  (description "")
+  (categories '(default))
+  (trust 'high))                       ; `low' or `high'
+
+(defun org-lint-missing-checker-name (_)
+  (error
+   "`A checker has no `:name' property.  Please verify `org-lint--checkers'"))
+
+(defconst org-lint--checkers
+  (list
+   (make-org-lint-checker
+    :name 'duplicate-custom-id
+    :description "Report duplicates CUSTOM_ID properties"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'duplicate-name
+    :description "Report duplicate NAME values"
+    :categories '(babel link))
+   (make-org-lint-checker
+    :name 'duplicate-target
+    :description "Report duplicate targets"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'duplicate-footnote-definition
+    :description "Report duplicate footnote definitions"
+    :categories '(footnote))
+   (make-org-lint-checker
+    :name 'orphaned-affiliated-keywords
+    :description "Report orphaned affiliated keywords"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'obsolete-affiliated-keywords
+    :description "Report obsolete affiliated keywords"
+    :categories '(obsolete))
+   (make-org-lint-checker
+    :name 'deprecated-export-blocks
+    :description "Report deprecated export block syntax"
+    :categories '(obsolete export)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'deprecated-header-syntax
+    :description "Report deprecated Babel header syntax"
+    :categories '(obsolete babel)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'missing-language-in-src-block
+    :description "Report missing language in src blocks"
+    :categories '(babel))
+   (make-org-lint-checker
+    :name 'missing-backend-in-export-block
+    :description "Report missing back-end in export blocks"
+    :categories '(export))
+   (make-org-lint-checker
+    :name 'invalid-babel-call-block
+    :description "Report invalid Babel call blocks"
+    :categories '(babel))
+   (make-org-lint-checker
+    :name 'colon-in-name
+    :description "Report NAME values with a colon"
+    :categories '(babel))
+   (make-org-lint-checker
+    :name 'wrong-header-argument
+    :description "Report wrong babel headers"
+    :categories '(babel))
+   (make-org-lint-checker
+    :name 'wrong-header-value
+    :description "Report invalid value in babel headers"
+    :categories '(babel)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'deprecated-category-setup
+    :description "Report misuse of CATEGORY keyword"
+    :categories '(obsolete))
+   (make-org-lint-checker
+    :name 'invalid-coderef-link
+    :description "Report \"coderef\" links with unknown destination"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'invalid-custom-id-link
+    :description "Report \"custom-id\" links with unknown destination"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'invalid-fuzzy-link
+    :description "Report \"fuzzy\" links with unknown destination"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'invalid-id-link
+    :description "Report \"id\" links with unknown destination"
+    :categories '(link))
+   (make-org-lint-checker
+    :name 'link-to-local-file
+    :description "Report links to non-existent local files"
+    :categories '(link)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'non-existent-setupfile-parameter
+    :description "Report SETUPFILE keywords with non-existent file parameter"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'wrong-include-link-parameter
+    :description "Report INCLUDE keywords with misleading link parameter"
+    :categories '(export)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'obsolete-include-markup
+    :description "Report obsolete markup in INCLUDE keyword"
+    :categories '(obsolete export)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'unknown-options-item
+    :description "Report unknown items in OPTIONS keyword"
+    :categories '(export)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'invalid-macro-argument-and-template
+    :description "Report spurious macro arguments or invalid macro templates"
+    :categories '(export)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'special-property-in-properties-drawer
+    :description "Report special properties in properties drawers"
+    :categories '(properties))
+   (make-org-lint-checker
+    :name 'obsolete-properties-drawer
+    :description "Report obsolete syntax for properties drawers"
+    :categories '(obsolete properties))
+   (make-org-lint-checker
+    :name 'undefined-footnote-reference
+    :description "Report missing definition for footnote references"
+    :categories '(footnote))
+   (make-org-lint-checker
+    :name 'unreferenced-footnote-definition
+    :description "Report missing reference for footnote definitions"
+    :categories '(footnote))
+   (make-org-lint-checker
+    :name 'extraneous-element-in-footnote-section
+    :description "Report non-footnote definitions in footnote section"
+    :categories '(footnote))
+   (make-org-lint-checker
+    :name 'invalid-keyword-syntax
+    :description "Report probable invalid keywords"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'invalid-block
+    :description "Report invalid blocks"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'misplaced-planning-info
+    :description "Report misplaced planning info line"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'incomplete-drawer
+    :description "Report probable incomplete drawers"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'indented-diary-sexp
+    :description "Report probable indented diary-sexps"
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'quote-section
+    :description "Report obsolete QUOTE section"
+    :categories '(obsolete)
+    :trust 'low)
+   (make-org-lint-checker
+    :name 'file-application
+    :description "Report obsolete \"file+application\" link"
+    :categories '(link obsolete))
+   (make-org-lint-checker
+    :name 'empty-headline-with-tags
+    :description "Report ambiguous empty headlines with tags"
+    :categories '(headline)
+    :trust 'low))
+  "List of all available checkers.")
+
+(defun org-lint--collect-duplicates
+    (ast type extract-key extract-position build-message)
+  "Helper function to collect duplicates in parse tree AST.
+
+EXTRACT-KEY is a function extracting key.  It is called with
+a single argument: the element or object.  Comparison is done
+with `equal'.
+
+EXTRACT-POSITION is a function returning position for the report.
+It is called with two arguments, the object or element, and the
+key.
+
+BUILD-MESSAGE is a function creating the report message.  It is
+called with one argument, the key used for comparison."
+  (let* (keys
+        originals
+        reports
+        (make-report
+         (lambda (position value)
+           (push (list position (funcall build-message value)) reports))))
+    (org-element-map ast type
+      (lambda (datum)
+       (let ((key (funcall extract-key datum)))
+         (cond
+          ((not key))
+          ((assoc key keys) (cl-pushnew (assoc key keys) originals)
+           (funcall make-report (funcall extract-position datum key) key))
+          (t (push (cons key (funcall extract-position datum key)) keys))))))
+    (dolist (e originals reports) (funcall make-report (cdr e) (car e)))))
+
+(defun org-lint-duplicate-custom-id (ast)
+  (org-lint--collect-duplicates
+   ast
+   'node-property
+   (lambda (property)
+     (and (eq (compare-strings "CUSTOM_ID" nil nil
+                              (org-element-property :key property) nil nil
+                              t)
+             t)
+         (org-element-property :value property)))
+   (lambda (property _) (org-element-property :begin property))
+   (lambda (key) (format "Duplicate CUSTOM_ID property \"%s\"" key))))
+
+(defun org-lint-duplicate-name (ast)
+  (org-lint--collect-duplicates
+   ast
+   org-element-all-elements
+   (lambda (datum) (org-element-property :name datum))
+   (lambda (datum name)
+     (goto-char (org-element-property :begin datum))
+     (re-search-forward
+      (format "^[ \t]*#\\+[A-Za-z]+: +%s *$" (regexp-quote name)))
+     (match-beginning 0))
+   (lambda (key) (format "Duplicate NAME \"%s\"" key))))
+
+(defun org-lint-duplicate-target (ast)
+  (org-lint--collect-duplicates
+   ast
+   'target
+   (lambda (target) (org-split-string (org-element-property :value target)))
+   (lambda (target _) (org-element-property :begin target))
+   (lambda (key)
+     (format "Duplicate target <<%s>>" (mapconcat #'identity key " ")))))
+
+(defun org-lint-duplicate-footnote-definition (ast)
+  (org-lint--collect-duplicates
+   ast
+   'footnote-definition
+   (lambda (definition)  (org-element-property :label definition))
+   (lambda (definition _) (org-element-property :post-affiliated definition))
+   (lambda (key) (format "Duplicate footnote definition \"%s\"" key))))
+
+(defun org-lint-orphaned-affiliated-keywords (ast)
+  ;; Ignore orphan RESULTS keywords, which could be generated from
+  ;; a source block returning no value.
+  (let ((keywords (cl-set-difference org-element-affiliated-keywords
+                                    '("RESULT" "RESULTS")
+                                    :test #'equal)))
+    (org-element-map ast 'keyword
+      (lambda (k)
+       (let ((key (org-element-property :key k)))
+         (and (or (let ((case-fold-search t))
+                    (string-match-p "\\`ATTR_[-_A-Za-z0-9]+\\'" key))
+                  (member key keywords))
+              (list (org-element-property :post-affiliated k)
+                    (format "Orphaned affiliated keyword: \"%s\"" key))))))))
+
+(defun org-lint-obsolete-affiliated-keywords (_)
+  (let ((regexp (format "^[ \t]*#\\+%s:"
+                       (regexp-opt '("DATA" "LABEL" "RESNAME" "SOURCE"
+                                     "SRCNAME" "TBLNAME" "RESULT" "HEADERS")
+                                   t)))
+       reports)
+    (while (re-search-forward regexp nil t)
+      (let ((key (upcase (match-string-no-properties 1))))
+       (when (< (point)
+                (org-element-property :post-affiliated (org-element-at-point)))
+         (push
+          (list (line-beginning-position)
+                (format
+                 "Obsolete affiliated keyword: \"%s\".  Use \"%s\" instead"
+                 key
+                 (pcase key
+                   ("HEADERS" "HEADER")
+                   ("RESULT" "RESULTS")
+                   (_ "NAME"))))
+          reports))))
+    reports))
+
+(defun org-lint-deprecated-export-blocks (ast)
+  (let ((deprecated '("ASCII" "BEAMER" "HTML" "LATEX" "MAN" "MARKDOWN" "MD"
+                     "ODT" "ORG" "TEXINFO")))
+    (org-element-map ast 'special-block
+      (lambda (b)
+       (let ((type (org-element-property :type b)))
+         (when (member-ignore-case type deprecated)
+           (list
+            (org-element-property :post-affiliated b)
+            (format
+             "Deprecated syntax for export block.  Use \"BEGIN_EXPORT %s\" \
+instead"
+             type))))))))
+
+(defun org-lint-deprecated-header-syntax (ast)
+  (let* ((deprecated-babel-properties
+         (mapcar (lambda (arg) (symbol-name (car arg)))
+                 org-babel-common-header-args-w-values))
+        (deprecated-re
+         (format "\\`%s[ \t]" (regexp-opt deprecated-babel-properties t))))
+    (org-element-map ast '(keyword node-property)
+      (lambda (datum)
+       (let ((key (org-element-property :key datum)))
+         (pcase (org-element-type datum)
+           (`keyword
+            (let ((value (org-element-property :value datum)))
+              (and (string= key "PROPERTY")
+                   (string-match deprecated-re value)
+                   (list (org-element-property :begin datum)
+                         (format "Deprecated syntax for \"%s\".  \
+Use header-args instead"
+                                 (match-string-no-properties 1 value))))))
+           (`node-property
+            (and (member-ignore-case key deprecated-babel-properties)
+                 (list
+                  (org-element-property :begin datum)
+                  (format "Deprecated syntax for \"%s\".  \
+Use :header-args: instead"
+                          key))))))))))
+
+(defun org-lint-missing-language-in-src-block (ast)
+  (org-element-map ast 'src-block
+    (lambda (b)
+      (unless (org-element-property :language b)
+       (list (org-element-property :post-affiliated b)
+             "Missing language in source block")))))
+
+(defun org-lint-missing-backend-in-export-block (ast)
+  (org-element-map ast 'export-block
+    (lambda (b)
+      (unless (org-element-property :type b)
+       (list (org-element-property :post-affiliated b)
+             "Missing back-end in export block")))))
+
+(defun org-lint-invalid-babel-call-block (ast)
+  (org-element-map ast 'babel-call
+    (lambda (b)
+      (cond
+       ((not (org-element-property :call b))
+       (list (org-element-property :post-affiliated b)
+             "Invalid syntax in babel call block"))
+       ((let ((h (org-element-property :end-header b)))
+         (and h (string-match-p "\\`\\[.*\\]\\'" h)))
+       (list
+        (org-element-property :post-affiliated b)
+        "Babel call's end header must not be wrapped within brackets"))))))
+
+(defun org-lint-deprecated-category-setup (ast)
+  (org-element-map ast 'keyword
+    (let (category-flag)
+      (lambda (k)
+       (cond
+        ((not (string= (org-element-property :key k) "CATEGORY")) nil)
+        (category-flag
+         (list (org-element-property :post-affiliated k)
+               "Spurious CATEGORY keyword.  Set :CATEGORY: property instead"))
+        (t (setf category-flag t) nil))))))
+
+(defun org-lint-invalid-coderef-link (ast)
+  (let ((info (list :parse-tree ast)))
+    (org-element-map ast 'link
+      (lambda (link)
+       (let ((ref (org-element-property :path link)))
+         (and (equal (org-element-property :type link) "coderef")
+              (not (ignore-errors (org-export-resolve-coderef ref info)))
+              (list (org-element-property :begin link)
+                    (format "Unknown coderef \"%s\"" ref))))))))
+
+(defun org-lint-invalid-custom-id-link (ast)
+  (let ((info (list :parse-tree ast)))
+    (org-element-map ast 'link
+      (lambda (link)
+       (and (equal (org-element-property :type link) "custom-id")
+            (not (ignore-errors (org-export-resolve-id-link link info)))
+            (list (org-element-property :begin link)
+                  (format "Unknown custom ID \"%s\""
+                          (org-element-property :path link))))))))
+
+(defun org-lint-invalid-fuzzy-link (ast)
+  (let ((info (list :parse-tree ast)))
+    (org-element-map ast 'link
+      (lambda (link)
+       (and (equal (org-element-property :type link) "fuzzy")
+            (not (ignore-errors (org-export-resolve-fuzzy-link link info)))
+            (list (org-element-property :begin link)
+                  (format "Unknown fuzzy location \"%s\""
+                          (let ((path (org-element-property :path link)))
+                            (if (string-prefix-p "*" path)
+                                (substring path 1)
+                              path)))))))))
+
+(defun org-lint-invalid-id-link (ast)
+  (org-element-map ast 'link
+    (lambda (link)
+      (let ((id (org-element-property :path link)))
+       (and (equal (org-element-property :type link) "id")
+            (not (org-id-find id))
+            (list (org-element-property :begin link)
+                  (format "Unknown ID \"%s\"" id)))))))
+
+(defun org-lint-special-property-in-properties-drawer (ast)
+  (org-element-map ast 'node-property
+    (lambda (p)
+      (let ((key (org-element-property :key p)))
+       (and (member-ignore-case key org-special-properties)
+            (list (org-element-property :begin p)
+                  (format
+                   "Special property \"%s\" found in a properties drawer"
+                   key)))))))
+
+(defun org-lint-obsolete-properties-drawer (ast)
+  (org-element-map ast 'drawer
+    (lambda (d)
+      (when (equal (org-element-property :drawer-name d) "PROPERTIES")
+       (let ((section (org-element-lineage d '(section))))
+         (unless (org-element-map section 'property-drawer #'identity nil t)
+           (list (org-element-property :post-affiliated d)
+                 (if (save-excursion
+                       (goto-char (org-element-property :post-affiliated d))
+                       (forward-line -1)
+                       (or (org-at-heading-p) (org-at-planning-p)))
+                     "Incorrect contents for PROPERTIES drawer"
+                   "Incorrect location for PROPERTIES drawer"))))))))
+
+(defun org-lint-link-to-local-file (ast)
+  (org-element-map ast 'link
+    (lambda (l)
+      (when (equal (org-element-property :type l) "file")
+       (let ((file (org-link-unescape (org-element-property :path l))))
+         (and (not (file-remote-p file))
+              (not (file-exists-p file))
+              (list (org-element-property :begin l)
+                    (format (if (org-element-lineage l '(link))
+                                "Link to non-existent image file \"%s\"\
+ in link description"
+                              "Link to non-existent local file \"%s\"")
+                            file))))))))
+
+(defun org-lint-non-existent-setupfile-parameter (ast)
+  (org-element-map ast 'keyword
+    (lambda (k)
+      (when (equal (org-element-property :key k) "SETUPFILE")
+       (let ((file (org-unbracket-string
+                    "\"" "\""
+                    (org-element-property :value k))))
+         (and (not (file-remote-p file))
+              (not (file-exists-p file))
+              (list (org-element-property :begin k)
+                    (format "Non-existent setup file \"%s\"" file))))))))
+
+(defun org-lint-wrong-include-link-parameter (ast)
+  (org-element-map ast 'keyword
+    (lambda (k)
+      (when (equal (org-element-property :key k) "INCLUDE")
+       (let* ((value (org-element-property :value k))
+              (path
+               (and (string-match "^\\(\".+\"\\|\\S-+\\)[ \t]*" value)
+                    (save-match-data
+                      (org-unbracket-string "\"" "\"" (match-string 1 
value))))))
+         (if (not path)
+             (list (org-element-property :post-affiliated k)
+                   "Missing location argument in INCLUDE keyword")
+           (let* ((file (org-string-nw-p
+                         (if (string-match "::\\(.*\\)\\'" path)
+                             (substring path 0 (match-beginning 0))
+                           path)))
+                  (search (and (not (equal file path))
+                               (org-string-nw-p (match-string 1 path)))))
+             (if (and file
+                      (not (file-remote-p file))
+                      (not (file-exists-p file)))
+                 (list (org-element-property :post-affiliated k)
+                       "Non-existent file argument in INCLUDE keyword")
+               (let* ((visiting (if file (find-buffer-visiting file)
+                                  (current-buffer)))
+                      (buffer (or visiting (find-file-noselect file))))
+                 (unwind-protect
+                     (with-current-buffer buffer
+                       (when (and search
+                                  (not
+                                   (ignore-errors
+                                     (let ((org-link-search-inhibit-query t))
+                                       (org-link-search search nil t)))))
+                         (list (org-element-property :post-affiliated k)
+                               (format
+                                "Invalid search part \"%s\" in INCLUDE keyword"
+                                search))))
+                   (unless visiting (kill-buffer buffer))))))))))))
+
+(defun org-lint-obsolete-include-markup (ast)
+  (let ((regexp (format "\\`\\(?:\".+\"\\|\\S-+\\)[ \t]+%s"
+                       (regexp-opt
+                        '("ASCII" "BEAMER" "HTML" "LATEX" "MAN" "MARKDOWN" "MD"
+                          "ODT" "ORG" "TEXINFO")
+                        t))))
+    (org-element-map ast 'keyword
+      (lambda (k)
+       (when (equal (org-element-property :key k) "INCLUDE")
+         (let ((case-fold-search t)
+               (value (org-element-property :value k)))
+           (when (string-match regexp value)
+             (let ((markup (match-string-no-properties 1 value)))
+               (list (org-element-property :post-affiliated k)
+                     (format "Obsolete markup \"%s\" in INCLUDE keyword.  \
+Use \"export %s\" instead"
+                             markup
+                             markup))))))))))
+
+(defun org-lint-unknown-options-item (ast)
+  (let ((allowed (delq nil
+                      (append
+                       (mapcar (lambda (o) (nth 2 o)) org-export-options-alist)
+                       (cl-mapcan
+                        (lambda (b)
+                          (mapcar (lambda (o) (nth 2 o))
+                                  (org-export-backend-options b)))
+                        org-export-registered-backends))))
+       reports)
+    (org-element-map ast 'keyword
+      (lambda (k)
+       (when (string= (org-element-property :key k) "OPTIONS")
+         (let ((value (org-element-property :value k))
+               (start 0))
+           (while (string-match "\\(.+?\\):\\((.*?)\\|\\S-*\\)[ \t]*"
+                                value
+                                start)
+             (setf start (match-end 0))
+             (let ((item (match-string 1 value)))
+               (unless (member item allowed)
+                 (push (list (org-element-property :post-affiliated k)
+                             (format "Unknown OPTIONS item \"%s\"" item))
+                       reports))))))))
+    reports))
+
+(defun org-lint-invalid-macro-argument-and-template (ast)
+  (let ((extract-placeholders
+        (lambda (template)
+          (let ((start 0)
+                args)
+            (while (string-match "\\$\\([1-9][0-9]*\\)" template start)
+              (setf start (match-end 0))
+              (push (string-to-number (match-string 1 template)) args))
+            (sort (org-uniquify args) #'<))))
+       reports)
+    ;; Check arguments for macro templates.
+    (org-element-map ast 'keyword
+      (lambda (k)
+       (when (string= (org-element-property :key k) "MACRO")
+         (let* ((value (org-element-property :value k))
+                (name (and (string-match "^\\S-+" value)
+                           (match-string 0 value)))
+                (template (and name
+                               (org-trim (substring value (match-end 0))))))
+           (cond
+            ((not name)
+             (push (list (org-element-property :post-affiliated k)
+                         "Missing name in MACRO keyword")
+                   reports))
+            ((not (org-string-nw-p template))
+             (push (list (org-element-property :post-affiliated k)
+                         "Missing template in macro \"%s\"" name)
+                   reports))
+            (t
+             (unless (let ((args (funcall extract-placeholders template)))
+                       (equal (number-sequence 1 (or (org-last args) 0)) args))
+               (push (list (org-element-property :post-affiliated k)
+                           (format "Unused placeholders in macro \"%s\""
+                                   name))
+                     reports))))))))
+    ;; Check arguments for macros.
+    (org-macro-initialize-templates)
+    (let ((templates (append
+                     (mapcar (lambda (m) (cons m "$1"))
+                             '("author" "date" "email" "title" "results"))
+                     org-macro-templates)))
+      (org-element-map ast 'macro
+       (lambda (macro)
+         (let* ((name (org-element-property :key macro))
+                (template (cdr (assoc-string name templates t))))
+           (if (not template)
+               (push (list (org-element-property :begin macro)
+                           (format "Undefined macro \"%s\"" name))
+                     reports)
+             (let ((arg-numbers (funcall extract-placeholders template)))
+               (when arg-numbers
+                 (let ((spurious-args
+                        (nthcdr (apply #'max arg-numbers)
+                                (org-element-property :args macro))))
+                   (when spurious-args
+                     (push
+                      (list (org-element-property :begin macro)
+                            (format "Unused argument%s in macro \"%s\": %s"
+                                    (if (> (length spurious-args) 1) "s" "")
+                                    name
+                                    (mapconcat (lambda (a) (format "\"%s\"" a))
+                                               spurious-args
+                                               ", ")))
+                      reports))))))))))
+    reports))
+
+(defun org-lint-undefined-footnote-reference (ast)
+  (let ((definitions (org-element-map ast 'footnote-definition
+                      (lambda (f) (org-element-property :label f)))))
+    (org-element-map ast 'footnote-reference
+      (lambda (f)
+       (let ((label (org-element-property :label f)))
+         (and label
+              (not (member label definitions))
+              (list (org-element-property :begin f)
+                    (format "Missing definition for footnote [%s]"
+                            label))))))))
+
+(defun org-lint-unreferenced-footnote-definition (ast)
+  (let ((references (org-element-map ast 'footnote-reference
+                     (lambda (f) (org-element-property :label f)))))
+    (org-element-map ast 'footnote-definition
+      (lambda (f)
+       (let ((label (org-element-property :label f)))
+         (and label
+              (not (member label references))
+              (list (org-element-property :post-affiliated f)
+                    (format "No reference for footnote definition [%s]"
+                            label))))))))
+
+(defun org-lint-colon-in-name (ast)
+  (org-element-map ast org-element-all-elements
+    (lambda (e)
+      (let ((name (org-element-property :name e)))
+       (and name
+            (string-match-p ":" name)
+            (list (progn
+                    (goto-char (org-element-property :begin e))
+                    (re-search-forward
+                     (format "^[ \t]*#\\+\\w+: +%s *$" (regexp-quote name)))
+                    (match-beginning 0))
+                  (format
+                   "Name \"%s\" contains a colon; Babel cannot use it as input"
+                   name)))))))
+
+(defun org-lint-misplaced-planning-info (_)
+  (let ((case-fold-search t)
+       reports)
+    (while (re-search-forward org-planning-line-re nil t)
+      (unless (memq (org-element-type (org-element-at-point))
+                   '(comment-block example-block export-block planning
+                                   src-block verse-block))
+       (push (list (line-beginning-position) "Misplaced planning info line")
+             reports)))
+    reports))
+
+(defun org-lint-incomplete-drawer (_)
+  (let (reports)
+    (while (re-search-forward org-drawer-regexp nil t)
+      (let ((name (org-trim (match-string-no-properties 0)))
+           (element (org-element-at-point)))
+       (pcase (org-element-type element)
+         ((or `drawer `property-drawer)
+          (goto-char (org-element-property :end element))
+          nil)
+         ((or `comment-block `example-block `export-block `src-block
+              `verse-block)
+          nil)
+         (_
+          (push (list (line-beginning-position)
+                      (format "Possible incomplete drawer \"%s\"" name))
+                reports)))))
+    reports))
+
+(defun org-lint-indented-diary-sexp (_)
+  (let (reports)
+    (while (re-search-forward "^[ \t]+%%(" nil t)
+      (unless (memq (org-element-type (org-element-at-point))
+                   '(comment-block diary-sexp example-block export-block
+                                   src-block verse-block))
+       (push (list (line-beginning-position) "Possible indented diary-sexp")
+             reports)))
+    reports))
+
+(defun org-lint-invalid-block (_)
+  (let ((case-fold-search t)
+       (regexp "^[ \t]*#\\+\\(BEGIN\\|END\\)\\(?::\\|_[^[:space:]]*\\)?[ \t]*")
+       reports)
+    (while (re-search-forward regexp nil t)
+      (let ((name (org-trim (buffer-substring-no-properties
+                            (line-beginning-position) (line-end-position)))))
+       (cond
+        ((and (string-prefix-p "END" (match-string 1) t)
+              (not (eolp)))
+         (push (list (line-beginning-position)
+                     (format "Invalid block closing line \"%s\"" name))
+               reports))
+        ((not (memq (org-element-type (org-element-at-point))
+                    '(center-block comment-block dynamic-block example-block
+                                   export-block quote-block special-block
+                                   src-block verse-block)))
+         (push (list (line-beginning-position)
+                     (format "Possible incomplete block \"%s\""
+                             name))
+               reports)))))
+    reports))
+
+(defun org-lint-invalid-keyword-syntax (_)
+  (let ((regexp "^[ \t]*#\\+\\([^[:space:]:]*\\)\\(?: \\|$\\)")
+       (exception-re
+        (format "[ \t]*#\\+%s\\(\\[.*\\]\\)?:\\(?: \\|$\\)"
+                (regexp-opt org-element-dual-keywords)))
+       reports)
+    (while (re-search-forward regexp nil t)
+      (let ((name (match-string-no-properties 1)))
+       (unless (or (string-prefix-p "BEGIN" name t)
+                   (string-prefix-p "END" name t)
+                   (save-excursion
+                     (beginning-of-line)
+                     (let ((case-fold-search t)) (looking-at exception-re))))
+         (push (list (match-beginning 0)
+                     (format "Possible missing colon in keyword \"%s\"" name))
+               reports))))
+    reports))
+
+(defun org-lint-extraneous-element-in-footnote-section (ast)
+  (org-element-map ast 'headline
+    (lambda (h)
+      (and (org-element-property :footnote-section-p h)
+          (org-element-map (org-element-contents h)
+              (cl-remove-if
+               (lambda (e)
+                 (memq e '(comment comment-block footnote-definition
+                                   property-drawer section)))
+               org-element-all-elements)
+            (lambda (e)
+              (not (and (eq (org-element-type e) 'headline)
+                        (org-element-property :commentedp e))))
+            nil t '(footnote-definition property-drawer))
+          (list (org-element-property :begin h)
+                "Extraneous elements in footnote section are not exported")))))
+
+(defun org-lint-quote-section (ast)
+  (org-element-map ast '(headline inlinetask)
+    (lambda (h)
+      (let ((title (org-element-property :raw-value h)))
+       (and (or (string-prefix-p "QUOTE " title)
+                (string-prefix-p (concat org-comment-string " QUOTE ") title))
+            (list (org-element-property :begin h)
+                  "Deprecated QUOTE section"))))))
+
+(defun org-lint-file-application (ast)
+  (org-element-map ast 'link
+    (lambda (l)
+      (let ((app (org-element-property :application l)))
+       (and app
+            (list (org-element-property :begin l)
+                  (format "Deprecated \"file+%s\" link type" app)))))))
+
+(defun org-lint-wrong-header-argument (ast)
+  (let* ((reports)
+        (verify
+         (lambda (datum language headers)
+           (let ((allowed
+                  ;; If LANGUAGE is specified, restrict allowed
+                  ;; headers to both LANGUAGE-specific and default
+                  ;; ones.  Otherwise, accept headers from any loaded
+                  ;; language.
+                  (append
+                   org-babel-header-arg-names
+                   (cl-mapcan
+                    (lambda (l)
+                      (let ((v (intern (format "org-babel-header-args:%s" l))))
+                        (and (boundp v) (mapcar #'car (symbol-value v)))))
+                    (if language (list language)
+                      (mapcar #'car org-babel-load-languages))))))
+             (dolist (header headers)
+               (let ((h (symbol-name (car header)))
+                     (p (or (org-element-property :post-affiliated datum)
+                            (org-element-property :begin datum))))
+                 (cond
+                  ((not (string-prefix-p ":" h))
+                   (push
+                    (list p
+                          (format "Missing colon in header argument \"%s\"" h))
+                    reports))
+                  ((assoc-string (substring h 1) allowed))
+                  (t (push (list p (format "Unknown header argument \"%s\"" h))
+                           reports)))))))))
+    (org-element-map ast '(babel-call inline-babel-call inline-src-block 
keyword
+                                     node-property src-block)
+      (lambda (datum)
+       (pcase (org-element-type datum)
+         ((or `babel-call `inline-babel-call)
+          (funcall verify
+                   datum
+                   nil
+                   (cl-mapcan #'org-babel-parse-header-arguments
+                              (list
+                               (org-element-property :inside-header datum)
+                               (org-element-property :end-header datum)))))
+         (`inline-src-block
+          (funcall verify
+                   datum
+                   (org-element-property :language datum)
+                   (org-babel-parse-header-arguments
+                    (org-element-property :parameters datum))))
+         (`keyword
+          (when (string= (org-element-property :key datum) "PROPERTY")
+            (let ((value (org-element-property :value datum)))
+              (when (string-match "\\`header-args\\(?::\\(\\S-+\\)\\)?\\+? *"
+                                  value)
+                (funcall verify
+                         datum
+                         (match-string 1 value)
+                         (org-babel-parse-header-arguments
+                          (substring value (match-end 0))))))))
+         (`node-property
+          (let ((key (org-element-property :key datum)))
+            (when (let ((case-fold-search t))
+                    (string-match "\\`HEADER-ARGS\\(?::\\(\\S-+\\)\\)?\\+?"
+                                  key))
+              (funcall verify
+                       datum
+                       (match-string 1 key)
+                       (org-babel-parse-header-arguments
+                        (org-element-property :value datum))))))
+         (`src-block
+          (funcall verify
+                   datum
+                   (org-element-property :language datum)
+                   (cl-mapcan #'org-babel-parse-header-arguments
+                              (cons (org-element-property :parameters datum)
+                                    (org-element-property :header datum))))))))
+    reports))
+
+(defun org-lint-wrong-header-value (ast)
+  (let (reports)
+    (org-element-map ast
+       '(babel-call inline-babel-call inline-src-block src-block)
+      (lambda (datum)
+       (let* ((type (org-element-type datum))
+              (language (org-element-property :language datum))
+              (allowed-header-values
+               (append (and language
+                            (let ((v (intern (concat "org-babel-header-args:"
+                                                     language))))
+                              (and (boundp v) (symbol-value v))))
+                       org-babel-common-header-args-w-values))
+              (datum-header-values
+               (org-babel-parse-header-arguments
+                (org-trim
+                 (pcase type
+                   (`src-block
+                    (mapconcat
+                     #'identity
+                     (cons (org-element-property :parameters datum)
+                           (org-element-property :header datum))
+                     " "))
+                   (`inline-src-block
+                    (or (org-element-property :parameters datum) ""))
+                   (_
+                    (concat
+                     (org-element-property :inside-header datum)
+                     " "
+                     (org-element-property :end-header datum))))))))
+         (dolist (header datum-header-values)
+           (let ((allowed-values
+                  (cdr (assoc-string (substring (symbol-name (car header)) 1)
+                                     allowed-header-values))))
+             (unless (memq allowed-values '(:any nil))
+               (let ((values (cdr header))
+                     groups-alist)
+                 (dolist (v (if (stringp values) (org-split-string values)
+                              (list values)))
+                   (let ((valid-value nil))
+                     (catch 'exit
+                       (dolist (group allowed-values)
+                         (cond
+                          ((not (funcall
+                                 (if (stringp v) #'assoc-string #'assoc)
+                                 v group))
+                           (when (memq :any group)
+                             (setf valid-value t)
+                             (push (cons group v) groups-alist)))
+                          ((assq group groups-alist)
+                           (push
+                            (list
+                             (or (org-element-property :post-affiliated datum)
+                                 (org-element-property :begin datum))
+                             (format
+                              "Forbidden combination in header \"%s\": %s, %s"
+                              (car header)
+                              (cdr (assq group groups-alist))
+                              v))
+                            reports)
+                           (throw 'exit nil))
+                          (t (push (cons group v) groups-alist)
+                             (setf valid-value t))))
+                       (unless valid-value
+                         (push
+                          (list
+                           (or (org-element-property :post-affiliated datum)
+                               (org-element-property :begin datum))
+                           (format "Unknown value \"%s\" for header \"%s\""
+                                   v
+                                   (car header)))
+                          reports))))))))))))
+    reports))
+
+(defun org-lint-empty-headline-with-tags (ast)
+  (org-element-map ast '(headline inlinetask)
+    (lambda (h)
+      (let ((title (org-element-property :raw-value h)))
+       (and (string-match-p "\\`:[[:alnum:address@hidden:]+:\\'" title)
+            (list (org-element-property :begin h)
+                  (format "Headline containing only tags is ambiguous: %S"
+                          title)))))))
+
+
+;;; Reports UI
+
+(defvar org-lint--report-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map tabulated-list-mode-map)
+    (define-key map (kbd "RET") 'org-lint--jump-to-source)
+    (define-key map (kbd "TAB") 'org-lint--show-source)
+    (define-key map (kbd "C-j") 'org-lint--show-source)
+    (define-key map (kbd "h") 'org-lint--hide-checker)
+    (define-key map (kbd "i") 'org-lint--ignore-checker)
+    map)
+  "Local keymap for `org-lint--report-mode' buffers.")
+
+(define-derived-mode org-lint--report-mode tabulated-list-mode "OrgLint"
+  "Major mode used to display reports emitted during linting.
+\\{org-lint--report-mode-map}"
+  (setf tabulated-list-format
+       `[("Line" 6
+          (lambda (a b)
+            (< (string-to-number (aref (cadr a) 0))
+               (string-to-number (aref (cadr b) 0))))
+          :right-align t)
+         ("Trust" 5 t)
+         ("Warning" 0 t)])
+  (tabulated-list-init-header))
+
+(defun org-lint--generate-reports (buffer checkers)
+  "Generate linting report for BUFFER.
+
+CHECKERS is the list of checkers used.
+
+Return an alist (ID [LINE TRUST DESCRIPTION CHECKER]), suitable
+for `tabulated-list-printer'."
+  (with-current-buffer buffer
+    (save-excursion
+      (goto-char (point-min))
+      (let ((ast (org-element-parse-buffer))
+           (id 0)
+           (last-line 1)
+           (last-pos 1))
+       ;; Insert unique ID for each report.  Replace buffer positions
+       ;; with line numbers.
+       (mapcar
+        (lambda (report)
+          (list
+           (cl-incf id)
+           (apply #'vector
+                  (cons
+                   (progn
+                     (goto-char (car report))
+                     (beginning-of-line)
+                     (prog1 (number-to-string
+                             (cl-incf last-line
+                                      (count-lines last-pos (point))))
+                       (setf last-pos (point))))
+                   (cdr report)))))
+        ;; Insert trust level in generated reports.  Also sort them
+        ;; by buffer position in order to optimize lines computation.
+        (sort (cl-mapcan
+               (lambda (c)
+                 (let ((trust (symbol-name (org-lint-checker-trust c))))
+                   (mapcar
+                    (lambda (report)
+                      (list (car report) trust (nth 1 report) c))
+                    (save-excursion
+                      (funcall
+                       (intern (format "org-lint-%s"
+                                       (org-lint-checker-name c)))
+                       ast)))))
+               checkers)
+              #'car-less-than-car))))))
+
+(defvar-local org-lint--source-buffer nil
+  "Source buffer associated to current report buffer.")
+
+(defvar-local org-lint--local-checkers nil
+  "List of checkers used to build current report.")
+
+(defun org-lint--refresh-reports ()
+  (setq tabulated-list-entries
+       (org-lint--generate-reports org-lint--source-buffer
+                                   org-lint--local-checkers))
+  (tabulated-list-print))
+
+(defun org-lint--current-line ()
+  "Return current report line, as a number."
+  (string-to-number (aref (tabulated-list-get-entry) 0)))
+
+(defun org-lint--current-checker (&optional entry)
+  "Return current report checker.
+When optional argument ENTRY is non-nil, use this entry instead
+of current one."
+  (aref (if entry (nth 1 entry) (tabulated-list-get-entry)) 3))
+
+(defun org-lint--display-reports (source checkers)
+  "Display linting reports for buffer SOURCE.
+CHECKERS is the list of checkers used."
+  (let ((buffer (get-buffer-create "*Org Lint*")))
+    (with-current-buffer buffer
+      (org-lint--report-mode)
+      (setf org-lint--source-buffer source)
+      (setf org-lint--local-checkers checkers)
+      (org-lint--refresh-reports)
+      (tabulated-list-print)
+      (add-hook 'tabulated-list-revert-hook #'org-lint--refresh-reports nil t))
+    (pop-to-buffer buffer)))
+
+(defun org-lint--jump-to-source ()
+  "Move to source line that generated the report at point."
+  (interactive)
+  (let ((l (org-lint--current-line)))
+    (switch-to-buffer-other-window org-lint--source-buffer)
+    (org-goto-line l)
+    (org-show-set-visibility 'local)
+    (recenter)))
+
+(defun org-lint--show-source ()
+  "Show source line that generated the report at point."
+  (interactive)
+  (let ((buffer (current-buffer)))
+    (org-lint--jump-to-source)
+    (switch-to-buffer-other-window buffer)))
+
+(defun org-lint--hide-checker ()
+  "Hide all reports from checker that generated the report at point."
+  (interactive)
+  (let ((c (org-lint--current-checker)))
+    (setf tabulated-list-entries
+         (cl-remove-if (lambda (e) (equal c (org-lint--current-checker e)))
+                        tabulated-list-entries))
+    (tabulated-list-print)))
+
+(defun org-lint--ignore-checker ()
+  "Ignore all reports from checker that generated the report at point.
+Checker will also be ignored in all subsequent reports."
+  (interactive)
+  (setf org-lint--local-checkers
+       (remove (org-lint--current-checker) org-lint--local-checkers))
+  (org-lint--hide-checker))
+
+
+;;; Public function
+
+;;;###autoload
+(defun org-lint (&optional arg)
+  "Check current Org buffer for syntax mistakes.
+
+By default, run all checkers.  With a `\\[universal-argument]' prefix ARG, \
+select one
+category of checkers only.  With a `\\[universal-argument] \
+\\[universal-argument]' prefix, run one precise
+checker by its name.
+
+ARG can also be a list of checker names, as symbols, to run."
+  (interactive "P")
+  (unless (derived-mode-p 'org-mode) (user-error "Not in an Org buffer"))
+  (when (called-interactively-p 'any)
+    (message "Org linting process starting..."))
+  (let ((checkers
+        (pcase arg
+          (`nil org-lint--checkers)
+          (`(4)
+           (let ((category
+                  (completing-read
+                   "Checker category: "
+                   (mapcar #'org-lint-checker-categories org-lint--checkers)
+                   nil t)))
+             (cl-remove-if-not
+              (lambda (c)
+                (assoc-string (org-lint-checker-categories c) category))
+              org-lint--checkers)))
+          (`(16)
+           (list
+            (let ((name (completing-read
+                         "Checker name: "
+                         (mapcar #'org-lint-checker-name org-lint--checkers)
+                         nil t)))
+              (catch 'exit
+                (dolist (c org-lint--checkers)
+                  (when (string= (org-lint-checker-name c) name)
+                    (throw 'exit c)))))))
+          ((pred consp)
+           (cl-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg))
+                              org-lint--checkers))
+          (_ (user-error "Invalid argument `%S' for `org-lint'" arg)))))
+    (if (not (called-interactively-p 'any))
+       (org-lint--generate-reports (current-buffer) checkers)
+      (org-lint--display-reports (current-buffer) checkers)
+      (message "Org linting process completed"))))
+
+
+(provide 'org-lint)
+;;; org-lint.el ends here
diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el
index a24c496..a3e2625 100644
--- a/lisp/org/org-list.el
+++ b/lisp/org/org-list.el
@@ -1,4 +1,4 @@
-;;; org-list.el --- Plain lists for Org-mode
+;;; org-list.el --- Plain lists for Org              -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 ;;
@@ -25,7 +25,7 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the code dealing with plain lists in Org-mode.
+;; This file contains the code dealing with plain lists in Org mode.
 
 ;; The core concept behind lists is their structure.  A structure is
 ;; a snapshot of the list, in the shape of a data tree (see
@@ -76,8 +76,7 @@
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'org-macs)
 (require 'org-compat)
 
@@ -88,59 +87,84 @@
 (defvar org-closed-string)
 (defvar org-deadline-string)
 (defvar org-description-max-indent)
-(defvar org-drawers)
+(defvar org-done-keywords)
+(defvar org-drawer-regexp)
+(defvar org-element-all-objects)
+(defvar org-inhibit-startup)
 (defvar org-odd-levels-only)
+(defvar org-outline-regexp-bol)
 (defvar org-scheduled-string)
+(defvar org-todo-line-regexp)
 (defvar org-ts-regexp)
 (defvar org-ts-regexp-both)
 
-(declare-function outline-invisible-p "outline" (&optional pos))
-(declare-function outline-flag-region "outline" (from to flag))
-(declare-function outline-next-heading "outline" ())
-(declare-function outline-previous-heading "outline" ())
-
-(declare-function org-at-heading-p "org" (&optional ignored))
-(declare-function org-before-first-heading-p "org" ())
+(declare-function org-at-heading-p "org" (&optional invisible-ok))
 (declare-function org-back-to-heading "org" (&optional invisible-ok))
+(declare-function org-before-first-heading-p "org" ())
 (declare-function org-combine-plists "org" (&rest plists))
-(declare-function org-count "org" (cl-item cl-seq))
 (declare-function org-current-level "org" ())
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-interpret-data "org-element" (data))
+(declare-function
+ org-element-lineage "org-element" (blob &optional types with-self))
+(declare-function org-element-macro-interpreter "org-element" (macro ##))
+(declare-function
+ org-element-map "org-element"
+ (data types fun &optional info first-match no-recursion with-affiliated))
+(declare-function org-element-normalize-string "org-element" (s))
+(declare-function org-element-parse-buffer "org-element"
+                 (&optional granularity visible-only))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-put-property "org-element"
+                 (element property value))
+(declare-function org-element-set-element "org-element" (old new))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-element-update-syntax "org-element" ())
 (declare-function org-entry-get "org"
                  (pom property &optional inherit literal-nil))
+(declare-function org-export-create-backend "ox" (&rest rest) t)
+(declare-function org-export-data-with-backend "ox" (data backend info))
+(declare-function org-export-get-backend "ox" (name))
+(declare-function org-export-get-environment "ox"
+                 (&optional backend subtreep ext-plist))
+(declare-function org-export-get-next-element "ox"
+                 (blob info &optional n))
+(declare-function org-export-with-backend "ox"
+                 (backend data &optional contents info))
 (declare-function org-fix-tags-on-the-fly "org" ())
 (declare-function org-get-indentation "org" (&optional line))
-(declare-function org-icompleting-read "org" (&rest args))
+(declare-function org-get-todo-state "org" ())
 (declare-function org-in-block-p "org" (names))
 (declare-function org-in-regexp "org" (re &optional nlines visually))
+(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
+(declare-function org-inlinetask-goto-end "org-inlinetask" ())
+(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
+(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
 (declare-function org-level-increment "org" ())
 (declare-function org-narrow-to-subtree "org" ())
-(declare-function org-at-heading-p "org" (&optional invisible-ok))
-(declare-function org-previous-line-empty-p "org" (&optional next))
-(declare-function org-remove-if "org" (predicate seq))
+(declare-function org-outline-level "org" ())
+(declare-function org-previous-line-empty-p "org" ())
 (declare-function org-reduced-level "org" (L))
+(declare-function org-remove-indentation "org" (code &optional n))
 (declare-function org-show-subtree "org" ())
 (declare-function org-sort-remove-invisible "org" (S))
 (declare-function org-time-string-to-seconds "org" (s))
 (declare-function org-timer-hms-to-secs "org-timer" (hms))
 (declare-function org-timer-item "org-timer" (&optional arg))
-(declare-function org-trim "org" (s))
+(declare-function org-trim "org" (s &optional keep-lead))
 (declare-function org-uniquify "org" (list))
-
-(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
-(declare-function org-inlinetask-goto-end "org-inlinetask" ())
-(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
-(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
-
-(declare-function org-export-string-as "ox"
-                 (string backend &optional body-only ext-plist))
-
+(declare-function org-invisible-p "org" (&optional pos))
+(declare-function outline-flag-region "outline" (from to flag))
+(declare-function outline-next-heading "outline" ())
+(declare-function outline-previous-heading "outline" ())
 
 
 
 ;;; Configuration variables
 
 (defgroup org-plain-lists nil
-  "Options concerning plain lists in Org-mode."
+  "Options concerning plain lists in Org mode."
   :tag "Org Plain lists"
   :group 'org-structure)
 
@@ -211,14 +235,20 @@ into
 
 (defcustom org-plain-list-ordered-item-terminator t
   "The character that makes a line with leading number an ordered list item.
-Valid values are ?. and ?\).  To get both terminators, use t."
+Valid values are ?. and ?\).  To get both terminators, use t.
+
+This variable needs to be set before org.el is loaded.  If you
+need to make a change while Emacs is running, use the customize
+interface or run the following code after updating it:
+
+  `\\[org-element-update-syntax]'"
   :group 'org-plain-lists
   :type '(choice (const :tag "dot like in \"2.\"" ?.)
                 (const :tag "paren like in \"2)\"" ?\))
-                (const :tag "both" t)))
+                (const :tag "both" t))
+  :set (lambda (var val) (set var val)
+        (when (featurep 'org-element) (org-element-update-syntax))))
 
-(define-obsolete-variable-alias 'org-alphabetical-lists
-  'org-list-allow-alphabetical "24.4") ; Since 8.0
 (defcustom org-list-allow-alphabetical nil
   "Non-nil means single character alphabetical bullets are allowed.
 
@@ -230,13 +260,12 @@ This variable needs to be set before org.el is loaded.  
If you
 need to make a change while Emacs is running, use the customize
 interface or run the following code after updating it:
 
-  (when (featurep \\='org-element) (load \"org-element\" t t))"
+  `\\[org-element-update-syntax]'"
   :group 'org-plain-lists
   :version "24.1"
   :type 'boolean
-  :set (lambda (var val)
-        (when (featurep 'org-element) (load "org-element" t t))
-        (set var val)))
+  :set (lambda (var val) (set var val)
+        (when (featurep 'org-element) (org-element-update-syntax))))
 
 (defcustom org-list-two-spaces-after-bullet-regexp nil
   "A regular expression matching bullets that should have 2 spaces after them.
@@ -250,23 +279,22 @@ spaces instead of one after the bullet in each item of 
the list."
          (const :tag "never" nil)
          (regexp)))
 
-(define-obsolete-variable-alias 'org-empty-line-terminates-plain-lists
-  'org-list-empty-line-terminates-plain-lists "24.4") ;; Since 8.0
-(defcustom org-list-empty-line-terminates-plain-lists nil
-  "Non-nil means an empty line ends all plain list levels.
-Otherwise, two of them will be necessary."
-  :group 'org-plain-lists
-  :type 'boolean)
-
 (defcustom org-list-automatic-rules '((checkbox . t)
                                      (indent . t))
   "Non-nil means apply set of rules when acting on lists.
+\\<org-mode-map>
 By default, automatic actions are taken when using
- \\[org-meta-return], \\[org-metaright], \\[org-metaleft],
- \\[org-shiftmetaright], \\[org-shiftmetaleft],
- \\[org-ctrl-c-minus], \\[org-toggle-checkbox] or
- \\[org-insert-todo-heading].  You can disable individually these
- rules by setting them to nil.  Valid rules are:
+  `\\[org-meta-return]',
+  `\\[org-metaright]',
+  `\\[org-metaleft]',
+  `\\[org-shiftmetaright]',
+  `\\[org-shiftmetaleft]',
+  `\\[org-ctrl-c-minus]',
+  `\\[org-toggle-checkbox]',
+  `\\[org-insert-todo-heading]'.
+
+You can disable individually these rules by setting them to nil.
+Valid rules are:
 
 checkbox  when non-nil, checkbox statistics is updated each time
           you either insert a new checkbox or toggle a checkbox.
@@ -286,13 +314,15 @@ indent    when non-nil, indenting or outdenting list 
top-item
 
 (defcustom org-list-use-circular-motion nil
   "Non-nil means commands implying motion in lists should be cyclic.
-
+\\<org-mode-map>
 In that case, the item following the last item is the first one,
 and the item preceding the first item is the last one.
 
-This affects the behavior of \\[org-move-item-up],
- \\[org-move-item-down], \\[org-next-item] and
- \\[org-previous-item]."
+This affects the behavior of
+  `\\[org-move-item-up]',
+  `\\[org-move-item-down]',
+  `\\[org-next-item]',
+  `\\[org-previous-item]'."
   :group 'org-plain-lists
   :version "24.1"
   :type 'boolean)
@@ -304,8 +334,6 @@ This hook runs even if checkbox rule in
 implement alternative ways of collecting statistics
 information.")
 
-(define-obsolete-variable-alias 'org-hierarchical-checkbox-statistics
-  'org-checkbox-hierarchical-statistics "24.4") ;; Since 8.0
 (defcustom org-checkbox-hierarchical-statistics t
   "Non-nil means checkbox statistics counts only the state of direct children.
 When nil, all boxes below the cookie are counted.
@@ -314,8 +342,6 @@ with the word \"recursive\" in the value."
   :group 'org-plain-lists
   :type 'boolean)
 
-(org-defvaralias 'org-description-max-indent
-  'org-list-description-max-indent) ;; Since 8.0
 (defcustom org-list-description-max-indent 20
   "Maximum indentation for the second line of a description list.
 When the indentation would be larger than this, it will become
@@ -358,8 +384,7 @@ list, obtained by prompting the user."
          (list (symbol :tag "Major mode")
                (string :tag "Format"))))
 
-(defvar org-list-forbidden-blocks '("example" "verse" "src" "ascii" "beamer"
-                                   "html" "latex" "odt")
+(defvar org-list-forbidden-blocks '("example" "verse" "src" "export")
   "Names of blocks where lists are not allowed.
 Names must be in lower case.")
 
@@ -374,10 +399,8 @@ specifically, type `block' is determined by the variable
 
 ;;; Predicates and regexps
 
-(defconst org-list-end-re (if org-list-empty-line-terminates-plain-lists "^[ 
\t]*\n"
-                           "^[ \t]*\n[ \t]*\n")
-  "Regex corresponding to the end of a list.
-It depends on `org-list-empty-line-terminates-plain-lists'.")
+(defconst org-list-end-re "^[ \t]*\n[ \t]*\n"
+  "Regex matching the end of a plain list.")
 
 (defconst org-list-full-item-re
   (concat "^[ \t]*\\(\\(?:[-+*]\\|\\(?:[0-9]+\\|[A-Za-z]\\)[.)]\\)\\(?:[ 
\t]+\\|$\\)\\)"
@@ -430,9 +453,6 @@ group 4: description tag")
     (let* ((case-fold-search t)
           (context (org-list-context))
           (lim-up (car context))
-          (drawers-re (concat "^[ \t]*:\\("
-                              (mapconcat #'regexp-quote org-drawers "\\|")
-                              "\\):[ \t]*$"))
           (inlinetask-re (and (featurep 'org-inlinetask)
                               (org-inlinetask-outline-regexp)))
           (item-re (org-item-re))
@@ -476,7 +496,7 @@ group 4: description tag")
               ((and (looking-at "^[ \t]*#\\+end_")
                     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
               ((and (looking-at "^[ \t]*:END:")
-                    (re-search-backward drawers-re lim-up t))
+                    (re-search-backward org-drawer-regexp lim-up t))
                (beginning-of-line))
               ((and inlinetask-re (looking-at inlinetask-re))
                (org-inlinetask-goto-beginning)
@@ -547,11 +567,7 @@ Contexts `block' and `invalid' refer to 
`org-list-forbidden-blocks'."
             (lim-down (or (save-excursion (outline-next-heading)) 
(point-max))))
         ;; Is point inside a drawer?
         (let ((end-re "^[ \t]*:END:")
-              ;; Can't use org-drawers-regexp as this function might
-              ;; be called in buffers not in Org mode.
-              (beg-re (concat "^[ \t]*:\\("
-                              (mapconcat #'regexp-quote org-drawers "\\|")
-                              "\\):[ \t]*$")))
+              (beg-re org-drawer-regexp))
           (when (save-excursion
                   (and (not (looking-at beg-re))
                        (not (looking-at end-re))
@@ -635,9 +651,6 @@ Assume point is at an item."
           (lim-down (nth 1 context))
           (text-min-ind 10000)
           (item-re (org-item-re))
-          (drawers-re (concat "^[ \t]*:\\("
-                              (mapconcat #'regexp-quote org-drawers "\\|")
-                              "\\):[ \t]*$"))
           (inlinetask-re (and (featurep 'org-inlinetask)
                               (org-inlinetask-outline-regexp)))
           (beg-cell (cons (point) (org-get-indentation)))
@@ -654,7 +667,7 @@ Assume point is at an item."
                       (match-string-no-properties 2) ; counter
                       (match-string-no-properties 3) ; checkbox
                       ;; Description tag.
-                      (and (save-match-data (string-match "[-+*]" bullet))
+                      (and (string-match-p "[-+*]" bullet)
                            (match-string-no-properties 4)))))))
           (end-before-blank
            (function
@@ -700,7 +713,7 @@ Assume point is at an item."
               ((and (looking-at "^[ \t]*#\\+end_")
                     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
               ((and (looking-at "^[ \t]*:END:")
-                    (re-search-backward drawers-re lim-up t))
+                    (re-search-backward org-drawer-regexp lim-up t))
                (beginning-of-line))
               ((and inlinetask-re (looking-at inlinetask-re))
                (org-inlinetask-goto-beginning)
@@ -766,7 +779,7 @@ Assume point is at an item."
              (cond
               ((and (looking-at "^[ \t]*#\\+begin_")
                     (re-search-forward "^[ \t]*#\\+end_" lim-down t)))
-              ((and (looking-at drawers-re)
+              ((and (looking-at org-drawer-regexp)
                     (re-search-forward "^[ \t]*:END:" lim-down t))))
              (forward-line 1))))))
       (setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
@@ -1021,7 +1034,7 @@ Possible types are `descriptive', `ordered' and 
`unordered'.  The
 type is determined by the first item of the list."
   (let ((first (org-list-get-list-begin item struct prevs)))
     (cond
-     ((string-match "[[:alnum:]]" (org-list-get-bullet first struct)) 'ordered)
+     ((string-match-p "[[:alnum:]]" (org-list-get-bullet first struct)) 
'ordered)
      ((org-list-get-tag first struct) 'descriptive)
      (t 'unordered))))
 
@@ -1043,7 +1056,7 @@ that value."
            (let ((seq 0) (pos item) counter)
              (while (and (not (setq counter (org-list-get-counter pos struct)))
                          (setq pos (org-list-get-prev-item pos struct prevs)))
-               (incf seq))
+               (cl-incf seq))
              (if (not counter) (1+ seq)
                (cond
                 ((string-match "[A-Za-z]" counter)
@@ -1137,13 +1150,20 @@ This function modifies STRUCT."
           ;; Store overlays responsible for visibility status.  We
           ;; also need to store their boundaries as they will be
           ;; removed from buffer.
-          (overlays (cons
-                     (mapcar (lambda (ov)
-                               (list ov (overlay-start ov) (overlay-end ov)))
-                             (overlays-in beg-A end-A))
-                     (mapcar (lambda (ov)
-                               (list ov (overlay-start ov) (overlay-end ov)))
-                             (overlays-in beg-B end-B)))))
+          (overlays
+           (cons
+            (delq nil
+                  (mapcar (lambda (o)
+                            (and (>= (overlay-start o) beg-A)
+                                 (<= (overlay-end o) end-A)
+                                 (list o (overlay-start o) (overlay-end o))))
+                          (overlays-in beg-A end-A)))
+            (delq nil
+                  (mapcar (lambda (o)
+                            (and (>= (overlay-start o) beg-B)
+                                 (<= (overlay-end o) end-B)
+                                 (list o (overlay-start o) (overlay-end o))))
+                          (overlays-in beg-B end-B))))))
       ;; 1. Move effectively items in buffer.
       (goto-char beg-A)
       (delete-region beg-A end-B-no-blank)
@@ -1154,42 +1174,39 @@ This function modifies STRUCT."
       ;;    as empty spaces are not moved there.  In others words,
       ;;    item BEG-A will end with whitespaces that were at the end
       ;;    of BEG-B and the same applies to BEG-B.
-      (mapc (lambda (e)
-             (let ((pos (car e)))
-               (cond
-                ((< pos beg-A))
-                ((memq pos sub-A)
-                 (let ((end-e (nth 6 e)))
-                   (setcar e (+ pos (- end-B-no-blank end-A-no-blank)))
-                   (setcar (nthcdr 6 e)
-                           (+ end-e (- end-B-no-blank end-A-no-blank)))
-                   (when (= end-e end-A) (setcar (nthcdr 6 e) end-B))))
-                ((memq pos sub-B)
-                 (let ((end-e (nth 6 e)))
-                   (setcar e (- (+ pos beg-A) beg-B))
-                   (setcar (nthcdr 6 e) (+ end-e (- beg-A beg-B)))
-                   (when (= end-e end-B)
-                     (setcar (nthcdr 6 e)
-                             (+ beg-A size-B (- end-A end-A-no-blank))))))
-                ((< pos beg-B)
-                 (let ((end-e (nth 6 e)))
-                   (setcar e (+ pos (- size-B size-A)))
-                   (setcar (nthcdr 6 e) (+ end-e (- size-B size-A))))))))
-           struct)
-      (setq struct (sort struct (lambda (e1 e2) (< (car e1) (car e2)))))
+      (dolist (e struct)
+       (let ((pos (car e)))
+         (cond
+          ((< pos beg-A))
+          ((memq pos sub-A)
+           (let ((end-e (nth 6 e)))
+             (setcar e (+ pos (- end-B-no-blank end-A-no-blank)))
+             (setcar (nthcdr 6 e)
+                     (+ end-e (- end-B-no-blank end-A-no-blank)))
+             (when (= end-e end-A) (setcar (nthcdr 6 e) end-B))))
+          ((memq pos sub-B)
+           (let ((end-e (nth 6 e)))
+             (setcar e (- (+ pos beg-A) beg-B))
+             (setcar (nthcdr 6 e) (+ end-e (- beg-A beg-B)))
+             (when (= end-e end-B)
+               (setcar (nthcdr 6 e)
+                       (+ beg-A size-B (- end-A end-A-no-blank))))))
+          ((< pos beg-B)
+           (let ((end-e (nth 6 e)))
+             (setcar e (+ pos (- size-B size-A)))
+             (setcar (nthcdr 6 e) (+ end-e (- size-B size-A))))))))
+      (setq struct (sort struct #'car-less-than-car))
       ;; Restore visibility status, by moving overlays to their new
       ;; position.
-      (mapc (lambda (ov)
-             (move-overlay
-              (car ov)
-              (+ (nth 1 ov) (- (+ beg-B (- size-B size-A)) beg-A))
-              (+ (nth 2 ov) (- (+ beg-B (- size-B size-A)) beg-A))))
-           (car overlays))
-      (mapc (lambda (ov)
-             (move-overlay (car ov)
-                           (+ (nth 1 ov) (- beg-A beg-B))
-                           (+ (nth 2 ov) (- beg-A beg-B))))
-           (cdr overlays))
+      (dolist (ov (car overlays))
+       (move-overlay
+        (car ov)
+        (+ (nth 1 ov) (- (+ beg-B (- size-B size-A)) beg-A))
+        (+ (nth 2 ov) (- (+ beg-B (- size-B size-A)) beg-A))))
+      (dolist (ov (cdr overlays))
+       (move-overlay (car ov)
+                     (+ (nth 1 ov) (- beg-A beg-B))
+                     (+ (nth 2 ov) (- beg-A beg-B))))
       ;; Return structure.
       struct)))
 
@@ -1219,7 +1236,7 @@ some heuristics to guess the result."
                                    (point))))))))
       (cond
        ;; Trivial cases where there should be none.
-       ((or org-list-empty-line-terminates-plain-lists (not insert-blank-p)) 0)
+       ((not insert-blank-p) 0)
        ;; When `org-blank-before-new-entry' says so, it is 1.
        ((eq insert-blank-p t) 1)
        ;; `plain-list-item' is 'auto.  Count blank lines separating
@@ -1272,12 +1289,16 @@ This function modifies STRUCT."
           (beforep
            (progn
              (looking-at org-list-full-item-re)
-             ;; Do not count tag in a non-descriptive list.
-             (<= pos (if (and (match-beginning 4)
-                              (save-match-data
-                                (string-match "[.)]" (match-string 1))))
-                         (match-beginning 4)
-                       (match-end 0)))))
+             (<= pos
+                 (cond
+                  ((not (match-beginning 4)) (match-end 0))
+                  ;; Ignore tag in a non-descriptive list.
+                  ((save-match-data (string-match "[.)]" (match-string 1)))
+                   (match-beginning 4))
+                  (t (save-excursion
+                       (goto-char (match-end 4))
+                       (skip-chars-forward " \t")
+                       (point)))))))
           (split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
           (blank-nb (org-list-separating-blank-lines-number
                      pos struct prevs))
@@ -1317,7 +1338,7 @@ This function modifies STRUCT."
           (size-offset (- item-size (length text-cut))))
       ;; 4. Insert effectively item into buffer.
       (goto-char item)
-      (org-indent-to-column ind)
+      (indent-to-column ind)
       (insert body item-sep)
       ;; 5. Add new item to STRUCT.
       (mapc (lambda (e)
@@ -1459,7 +1480,7 @@ This function returns, destructively, the new list 
structure."
                      (save-excursion
                        (goto-char (org-list-get-last-item item struct prevs))
                        (point-at-eol)))
-                    ((string-match "\\`[0-9]+\\'" dest)
+                    ((string-match-p "\\`[0-9]+\\'" dest)
                      (let* ((all (org-list-get-all-items item struct prevs))
                             (len (length all))
                             (index (mod (string-to-number dest) len)))
@@ -1473,8 +1494,10 @@ This function returns, destructively, the new list 
structure."
                            (point-at-eol)))))
                     (t dest)))
         (org-M-RET-may-split-line nil)
-        ;; Store visibility.
-        (visibility (overlays-in item item-end)))
+        ;; Store inner overlays (to preserve visibility).
+        (overlays (cl-remove-if (lambda (o) (or (< (overlay-start o) item)
+                                            (> (overlay-end o) item)))
+                                 (overlays-in item item-end))))
     (cond
      ((eq dest 'delete) (org-list-delete-item item struct))
      ((eq dest 'kill)
@@ -1509,13 +1532,12 @@ This function returns, destructively, the new list 
structure."
                                                           new-end
                                                         (+ end shift)))))))
                               moved-items))
-                     (lambda (e1 e2) (< (car e1) (car e2))))))
-      ;; 2. Restore visibility.
-      (mapc (lambda (ov)
-             (move-overlay ov
-                           (+ (overlay-start ov) (- (point) item))
-                           (+ (overlay-end ov) (- (point) item))))
-           visibility)
+                     #'car-less-than-car)))
+      ;; 2. Restore inner overlays.
+      (dolist (o overlays)
+       (move-overlay o
+                     (+ (overlay-start o) (- (point) item))
+                     (+ (overlay-end o) (- (point) item))))
       ;; 3. Eventually delete extra copy of the item and clean marker.
       (prog1 (org-list-delete-item (marker-position item) struct)
        (move-marker item nil)))
@@ -1632,7 +1654,7 @@ as returned by `org-list-prevs-alist'."
           (while item
             (let ((count (org-list-get-counter item struct)))
               ;; Virtually determine current bullet
-              (if (and count (string-match "[a-zA-Z]" count))
+              (if (and count (string-match-p "[a-zA-Z]" count))
                   ;; Counters are not case-sensitive.
                   (setq ascii (string-to-char (upcase count)))
                 (setq ascii (1+ ascii)))
@@ -1861,10 +1883,9 @@ Initial position of cursor is restored after the 
changes."
         (item-re (org-item-re))
         (shift-body-ind
          (function
-          ;; Shift the indentation between END and BEG by DELTA.  If
-          ;; MAX-IND is non-nil, ensure that no line will be indented
-          ;; more than that number.  Start from the line before END.
-          (lambda (end beg delta max-ind)
+          ;; Shift the indentation between END and BEG by DELTA.
+          ;; Start from the line before END.
+          (lambda (end beg delta)
             (goto-char end)
             (skip-chars-backward " \r\t\n")
             (beginning-of-line)
@@ -1876,10 +1897,8 @@ Initial position of cursor is restored after the 
changes."
                ((and inlinetask-re (looking-at inlinetask-re))
                 (org-inlinetask-goto-beginning))
                ;; Shift only non-empty lines.
-               ((org-looking-at-p "^[ \t]*\\S-")
-                (let ((i (org-get-indentation)))
-                  (org-indent-line-to
-                   (if max-ind (min (+ i delta) max-ind) (+ i delta))))))
+               ((looking-at-p "^[ \t]*\\S-")
+                (indent-line-to (+ (org-get-indentation) delta))))
               (forward-line -1)))))
          (modify-item
           (function
@@ -1934,37 +1953,53 @@ Initial position of cursor is restored after the 
changes."
            ;; belongs to: it is the last item (ITEM-UP), whose
            ;; ending is further than the position we're
            ;; interested in.
-           (let ((item-up (assoc-default end-pos acc-end '>)))
+           (let ((item-up (assoc-default end-pos acc-end #'>)))
              (push (cons end-pos item-up) end-list)))
          (push (cons end-pos pos) acc-end)))
       ;; 2. Slice the items into parts that should be shifted by the
       ;;    same amount of indentation.  Each slice follow the pattern
-      ;;    (END BEG DELTA MAX-IND-OR-NIL).  Slices are returned in
-      ;;    reverse order.
+      ;;    (END BEG DELTA).  Slices are returned in reverse order.
       (setq all-ends (sort (append (mapcar #'car itm-shift)
                                   (org-uniquify (mapcar #'car end-list)))
-                          '<))
+                          #'<)
+           acc-end (nreverse acc-end))
       (while (cdr all-ends)
        (let* ((up (pop all-ends))
               (down (car all-ends))
               (itemp (assq up struct))
-              (item (if itemp up (cdr (assq up end-list))))
-              (ind (cdr (assq item itm-shift)))
-              ;; If we're not at an item, there's a child of the item
-              ;; point belongs to above.  Make sure this slice isn't
-              ;; moved within that child by specifying a maximum
-              ;; indentation.
-              (max-ind (and (not itemp)
-                            (+ (org-list-get-ind item struct)
-                               (length (org-list-get-bullet item struct))
-                               org-list-indent-offset))))
-         (push (list down up ind max-ind) sliced-struct)))
+              (delta
+               (if itemp (cdr (assq up itm-shift))
+                 ;; If we're not at an item, there's a child of the
+                 ;; item point belongs to above.  Make sure the less
+                 ;; indented line in this slice has the same column
+                 ;; as that child.
+                 (let* ((child (cdr (assq up acc-end)))
+                        (ind (org-list-get-ind child struct))
+                        (min-ind most-positive-fixnum))
+                   (save-excursion
+                     (goto-char up)
+                     (while (< (point) down)
+                       ;; Ignore empty lines.  Also ignore blocks and
+                       ;; drawers contents.
+                       (unless (looking-at-p "[ \t]*$")
+                         (setq min-ind (min (org-get-indentation) min-ind))
+                         (cond
+                          ((and (looking-at "#\\+BEGIN\\(:\\|_\\S-+\\)")
+                                (re-search-forward
+                                 (format "^[ \t]*#\\+END%s[ \t]*$"
+                                         (match-string 1))
+                                 down t)))
+                          ((and (looking-at org-drawer-regexp)
+                                (re-search-forward "^[ \t]*:END:[ \t]*$"
+                                                   down t)))))
+                       (forward-line)))
+                   (- ind min-ind)))))
+         (push (list down up delta) sliced-struct)))
       ;; 3. Shift each slice in buffer, provided delta isn't 0, from
       ;;    end to beginning.  Take a special action when beginning is
       ;;    at item bullet.
       (dolist (e sliced-struct)
-       (unless (and (zerop (nth 2 e)) (not (nth 3 e)))
-         (apply shift-body-ind e))
+       (unless (zerop (nth 2 e)) (apply shift-body-ind e))
        (let* ((beg (nth 1 e))
               (cell (assq beg struct)))
          (unless (or (not cell) (equal cell (assq beg old-struct)))
@@ -2060,16 +2095,27 @@ Possible values are: `folded', `children' or `subtree'. 
 See
 
 (defun org-list-item-body-column (item)
   "Return column at which body of ITEM should start."
-  (let (bpos bcol tpos tcol)
-    (save-excursion
-      (goto-char item)
-      (looking-at "[ \t]*\\(\\S-+\\)\\(.*[ \t]+::\\)?\\([ \t]+\\|$\\)")
-      (setq bpos (match-beginning 1) tpos (match-end 0)
-           bcol (progn (goto-char bpos) (current-column))
-           tcol (progn (goto-char tpos) (current-column)))
-      (when (> tcol (+ bcol org-description-max-indent))
-       (setq tcol (+ bcol 5))))
-    tcol))
+  (save-excursion
+    (goto-char item)
+    (if (save-excursion
+         (end-of-line)
+         (re-search-backward
+          "[ \t]::\\([ \t]\\|$\\)" (line-beginning-position) t))
+       ;; Descriptive list item.  Body starts after item's tag, if
+       ;; possible.
+       (let ((start (1+ (- (match-beginning 1) (line-beginning-position))))
+             (ind (org-get-indentation)))
+         (if (> start (+ ind org-list-description-max-indent))
+             (+ ind 5)
+           start))
+      ;; Regular item.  Body starts after bullet.
+      (looking-at "[ \t]*\\(\\S-+\\)")
+      (+ (progn (goto-char (match-end 1)) (current-column))
+        (if (and org-list-two-spaces-after-bullet-regexp
+                 (string-match-p org-list-two-spaces-after-bullet-regexp
+                                 (match-string 1)))
+            2
+          1)))))
 
 
 
@@ -2210,7 +2256,7 @@ item is invisible."
     (unless (or (not itemp)
                (save-excursion
                  (goto-char itemp)
-                 (outline-invisible-p)))
+                 (org-invisible-p)))
       (if (save-excursion
            (goto-char itemp)
            (org-at-item-timer-p))
@@ -2325,9 +2371,6 @@ in subtree, ignoring drawers."
           block-item
           lim-up
           lim-down
-          (drawer-re (concat "^[ \t]*:\\("
-                             (mapconcat #'regexp-quote org-drawers "\\|")
-                             "\\):[ \t]*$"))
           (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string
                               "\\|" org-deadline-string
                               "\\|" org-closed-string
@@ -2349,7 +2392,8 @@ in subtree, ignoring drawers."
              ;; time-stamps (scheduled, etc.).
              (let ((limit (save-excursion (outline-next-heading) (point))))
                (forward-line 1)
-               (while (or (looking-at drawer-re) (looking-at keyword-re))
+               (while (or (looking-at org-drawer-regexp)
+                          (looking-at keyword-re))
                  (if (looking-at keyword-re)
                      (forward-line 1)
                    (re-search-forward "^[ \t]*:END:" limit nil)))
@@ -2388,7 +2432,7 @@ in subtree, ignoring drawers."
               (parents (org-list-parents-alist struct))
               (prevs (org-list-prevs-alist struct))
               (bottom (copy-marker (org-list-get-bottom-point struct)))
-              (items-to-toggle (org-remove-if
+              (items-to-toggle (cl-remove-if
                                 (lambda (e) (or (< e lim-up) (> e lim-down)))
                                 (mapcar #'car struct))))
          (mapc (lambda (e) (org-list-set-checkbox
@@ -2439,130 +2483,129 @@ in subtree, ignoring drawers."
 
 (defun org-update-checkbox-count (&optional all)
   "Update the checkbox statistics in the current section.
+
 This will find all statistic cookies like [57%] and [6/12] and
 update them with the current numbers.
 
 With optional prefix argument ALL, do this for the whole buffer."
   (interactive "P")
-  (save-excursion
-    (let ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
-         (box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ 
\t]+\\(?:address@hidden(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ 
\t]*\\)?\\(\\[[- X]\\]\\)")
+  (org-with-wide-buffer
+   (let* ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
+         (box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ \t]+\
+\\(?:address@hidden(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?\\(\\[[- 
X]\\]\\)")
          (recursivep
           (or (not org-checkbox-hierarchical-statistics)
               (string-match "\\<recursive\\>"
                             (or (org-entry-get nil "COOKIE_DATA") ""))))
-         (bounds (if all
-                     (cons (point-min) (point-max))
-                   (cons (or (ignore-errors (org-back-to-heading t) (point))
-                             (point-min))
-                         (save-excursion (outline-next-heading) (point)))))
+         (within-inlinetask (and (not all)
+                                 (featurep 'org-inlinetask)
+                                 (org-inlinetask-in-task-p)))
+         (end (cond (all (point-max))
+                    (within-inlinetask
+                     (save-excursion (outline-next-heading) (point)))
+                    (t (save-excursion
+                         (org-with-limited-levels (outline-next-heading))
+                         (point)))))
          (count-boxes
-          (function
-           ;; Return number of checked boxes and boxes of all types
-           ;; in all structures in STRUCTS.  If RECURSIVEP is
-           ;; non-nil, also count boxes in sub-lists.  If ITEM is
-           ;; nil, count across the whole structure, else count only
-           ;; across subtree whose ancestor is ITEM.
-           (lambda (item structs recursivep)
-             (let ((c-on 0) (c-all 0))
-               (mapc
-                (lambda (s)
-                  (let* ((pre (org-list-prevs-alist s))
-                         (par (org-list-parents-alist s))
-                         (items
-                          (cond
-                           ((and recursivep item) (org-list-get-subtree item 
s))
-                           (recursivep (mapcar #'car s))
-                           (item (org-list-get-children item s par))
-                           (t (org-list-get-all-items
-                               (org-list-get-top-point s) s pre))))
-                         (cookies (delq nil (mapcar
-                                             (lambda (e)
-                                               (org-list-get-checkbox e s))
-                                             items))))
-                    (setq c-all (+ (length cookies) c-all)
-                          c-on (+ (org-count "[X]" cookies) c-on))))
-                structs)
-               (cons c-on c-all)))))
-         (backup-end 1)
-         cookies-list structs-bak)
-      (goto-char (car bounds))
-      ;; 1. Build an alist for each cookie found within BOUNDS.  The
-      ;;    key will be position at beginning of cookie and values
-      ;;    ending position, format of cookie, and a cell whose car is
-      ;;    number of checked boxes to report, and cdr total number of
-      ;;    boxes.
-      (while (re-search-forward cookie-re (cdr bounds) t)
-       (catch 'skip
-         (save-excursion
-           (push
-            (list
-             (match-beginning 1)       ; cookie start
-             (match-end 1)             ; cookie end
-             (match-string 2)          ; percent?
-             (cond                     ; boxes count
-              ;; Cookie is at an heading, but specifically for todo,
-              ;; not for checkboxes: skip it.
-              ((and (org-at-heading-p)
-                    (string-match "\\<todo\\>"
-                                  (downcase
-                                   (or (org-entry-get nil "COOKIE_DATA") ""))))
-               (throw 'skip nil))
-              ;; Cookie is at an heading, but all lists before next
-              ;; heading already have been read.  Use data collected
-              ;; in STRUCTS-BAK.  This should only happen when
-              ;; heading has more than one cookie on it.
-              ((and (org-at-heading-p)
-                    (<= (save-excursion (outline-next-heading) (point))
-                        backup-end))
-               (funcall count-boxes nil structs-bak recursivep))
-              ;; Cookie is at a fresh heading.  Grab structure of
-              ;; every list containing a checkbox between point and
-              ;; next headline, and save them in STRUCTS-BAK.
-              ((org-at-heading-p)
-               (setq backup-end (save-excursion
-                                  (outline-next-heading) (point))
-                     structs-bak nil)
-               (while (org-list-search-forward box-re backup-end 'move)
-                 (let* ((struct (org-list-struct))
-                        (bottom (org-list-get-bottom-point struct)))
-                   (push struct structs-bak)
-                   (goto-char bottom)))
-               (funcall count-boxes nil structs-bak recursivep))
-              ;; Cookie is at an item, and we already have list
-              ;; structure stored in STRUCTS-BAK.
-              ((and (org-at-item-p)
-                    (< (point-at-bol) backup-end)
-                    ;; Only lists in no special context are stored.
-                    (not (nth 2 (org-list-context))))
-               (funcall count-boxes (point-at-bol) structs-bak recursivep))
-              ;; Cookie is at an item, but we need to compute list
-              ;; structure.
-              ((org-at-item-p)
-               (let ((struct (org-list-struct)))
-                 (setq backup-end (org-list-get-bottom-point struct)
-                       structs-bak (list struct)))
-               (funcall count-boxes (point-at-bol) structs-bak recursivep))
-              ;; Else, cookie found is at a wrong place.  Skip it.
-              (t (throw 'skip nil))))
-            cookies-list))))
-      ;; 2. Apply alist to buffer, in reverse order so positions stay
-      ;;    unchanged after cookie modifications.
-      (mapc (lambda (cookie)
-             (let* ((beg (car cookie))
-                    (end (nth 1 cookie))
-                    (percentp (nth 2 cookie))
-                    (checked (car (nth 3 cookie)))
-                    (total (cdr (nth 3 cookie)))
-                    (new (if percentp
-                             (format "[%d%%]" (floor (* 100.0 checked)
-                                                     (max 1 total)))
-                           (format "[%d/%d]" checked total))))
-               (goto-char beg)
-               (insert new)
-               (delete-region (point) (+ (point) (- end beg)))
-               (when org-auto-align-tags (org-fix-tags-on-the-fly))))
+          (lambda (item structs recursivep)
+            ;; Return number of checked boxes and boxes of all types
+            ;; in all structures in STRUCTS.  If RECURSIVEP is
+            ;; non-nil, also count boxes in sub-lists.  If ITEM is
+            ;; nil, count across the whole structure, else count only
+            ;; across subtree whose ancestor is ITEM.
+            (let ((c-on 0) (c-all 0))
+              (dolist (s structs (list c-on c-all))
+                (let* ((pre (org-list-prevs-alist s))
+                       (par (org-list-parents-alist s))
+                       (items
+                        (cond
+                         ((and recursivep item) (org-list-get-subtree item s))
+                         (recursivep (mapcar #'car s))
+                         (item (org-list-get-children item s par))
+                         (t (org-list-get-all-items
+                             (org-list-get-top-point s) s pre))))
+                       (cookies (delq nil (mapcar
+                                           (lambda (e)
+                                             (org-list-get-checkbox e s))
+                                           items))))
+                  (cl-incf c-all (length cookies))
+                  (cl-incf c-on (cl-count "[X]" cookies :test #'equal)))))))
+         cookies-list cache)
+     ;; Move to start.
+     (cond (all (goto-char (point-min)))
+          (within-inlinetask (org-back-to-heading t))
+          (t (org-with-limited-levels (outline-previous-heading))))
+     ;; Build an alist for each cookie found.  The key is the position
+     ;; at beginning of cookie and values ending position, format of
+     ;; cookie, number of checked boxes to report and total number of
+     ;; boxes.
+     (while (re-search-forward cookie-re end t)
+       (let ((context (save-excursion (backward-char)
+                                     (save-match-data (org-element-context)))))
+        (when (eq (org-element-type context) 'statistics-cookie)
+          (push
+           (append
+            (list (match-beginning 1) (match-end 1) (match-end 2))
+            (let* ((container
+                    (org-element-lineage
+                     context
+                     '(drawer center-block dynamic-block inlinetask item
+                              quote-block special-block verse-block)))
+                   (beg (if container
+                            (org-element-property :contents-begin container)
+                          (save-excursion
+                            (org-with-limited-levels
+                             (outline-previous-heading))
+                            (point)))))
+              (or (cdr (assq beg cache))
+                  (save-excursion
+                    (goto-char beg)
+                    (let ((end
+                           (if container
+                               (org-element-property :contents-end container)
+                             (save-excursion
+                               (org-with-limited-levels (outline-next-heading))
+                               (point))))
+                          structs)
+                      (while (re-search-forward box-re end t)
+                        (let ((element (org-element-at-point)))
+                          (when (eq (org-element-type element) 'item)
+                            (push (org-element-property :structure element)
+                                  structs)
+                            ;; Skip whole list since we have its
+                            ;; structure anyway.
+                            (while (setq element (org-element-lineage
+                                                  element '(plain-list)))
+                              (goto-char
+                               (min (org-element-property :end element)
+                                    end))))))
+                      ;; Cache count for cookies applying to the same
+                      ;; area.  Then return it.
+                      (let ((count
+                             (funcall count-boxes
+                                      (and (eq (org-element-type container)
+                                               'item)
+                                           (org-element-property
+                                            :begin container))
+                                      structs
+                                      recursivep)))
+                        (push (cons beg count) cache)
+                        count))))))
            cookies-list))))
+     ;; Apply alist to buffer.
+     (dolist (cookie cookies-list)
+       (let* ((beg (car cookie))
+             (end (nth 1 cookie))
+             (percent (nth 2 cookie))
+             (checked (nth 3 cookie))
+             (total (nth 4 cookie)))
+        (goto-char beg)
+        (insert
+         (if percent (format "[%d%%]" (floor (* 100.0 checked)
+                                             (max 1 total)))
+           (format "[%d/%d]" checked total)))
+        (delete-region (point) (+ (point) (- end beg)))
+        (when org-auto-align-tags (org-fix-tags-on-the-fly)))))))
 
 (defun org-get-checkbox-statistics-face ()
   "Select the face for checkbox statistics.
@@ -2664,7 +2707,7 @@ Return t if successful."
                   ;; of the subtree mustn't have a child.
                   (let ((last-item (caar
                                     (reverse
-                                     (org-remove-if
+                                     (cl-remove-if
                                       (lambda (e) (>= (car e) end))
                                       struct)))))
                     (org-list-has-child-p last-item struct))))
@@ -2781,7 +2824,7 @@ Return t at each successful move."
             ((and (= ind (car org-tab-ind-state))
                   (ignore-errors (org-list-indent-item-generic 1 t struct))))
             (t (delete-region (point-at-bol) (point-at-eol))
-               (org-indent-to-column (car org-tab-ind-state))
+               (indent-to-column (car org-tab-ind-state))
                (insert (cdr org-tab-ind-state) " ")
                ;; Break cycle
                (setq this-command 'identity)))
@@ -2794,7 +2837,8 @@ Return t at each successful move."
           (t (user-error "Cannot move item"))))
        t))))
 
-(defun org-sort-list (&optional with-case sorting-type getkey-func 
compare-func)
+(defun org-sort-list
+    (&optional with-case sorting-type getkey-func compare-func interactive?)
   "Sort list items.
 The cursor may be at any item of the list that should be sorted.
 Sublists are not sorted.  Checkboxes, if any, are ignored.
@@ -2820,13 +2864,15 @@ Capital letters will reverse the sort order.
 
 If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies
 a function to be called with point at the beginning of the
-record.  It must return either a string or a number that should
-serve as the sorting key for that record.  It will then use
-COMPARE-FUNC to compare entries.
+record.  It must return a value that is compatible with COMPARE-FUNC,
+the function used to compare entries.
 
 Sorting is done against the visible part of the headlines, it
-ignores hidden links."
-  (interactive "P")
+ignores hidden links.
+
+A non-nil value for INTERACTIVE? is used to signal that this
+function is being called interactively."
+  (interactive (list current-prefix-arg nil nil nil t))
   (let* ((case-func (if with-case 'identity 'downcase))
          (struct (org-list-struct))
          (prevs (org-list-prevs-alist struct))
@@ -2838,23 +2884,31 @@ ignores hidden links."
                (message
                 "Sort plain list: [a]lpha  [n]umeric  [t]ime  [f]unc  
[x]checked  A/N/T/F/X means reversed:")
                (read-char-exclusive))))
+        (dcst (downcase sorting-type))
         (getkey-func
-         (or getkey-func
-             (and (= (downcase sorting-type) ?f)
-                  (intern (org-icompleting-read "Sort using function: "
-                                                obarray 'fboundp t nil 
nil))))))
+         (and (= dcst ?f)
+              (or getkey-func
+                  (and interactive?
+                       (org-read-function "Function for extracting keys: "))
+                  (error "Missing key extractor"))))
+        (sort-func
+         (cond
+          ((= dcst ?a) #'string<)
+          ((= dcst ?f)
+           (or compare-func
+               (and interactive?
+                    (org-read-function
+                     (concat "Function for comparing keys "
+                             "(empty for default `sort-subr' predicate): ")
+                     'allow-empty))))
+          ((= dcst ?t) #'<)
+          ((= dcst ?x) #'string<))))
     (message "Sorting items...")
     (save-restriction
       (narrow-to-region start end)
       (goto-char (point-min))
-      (let* ((dcst (downcase sorting-type))
-            (case-fold-search nil)
+      (let* ((case-fold-search nil)
             (now (current-time))
-            (sort-func (cond
-                        ((= dcst ?a) 'string<)
-                        ((= dcst ?f) compare-func)
-                        ((= dcst ?t) '<)
-                        ((= dcst ?x) 'string<)))
             (next-record (lambda ()
                            (skip-chars-forward " \r\t\n")
                            (or (eobp) (beginning-of-line))))
@@ -2908,128 +2962,249 @@ ignores hidden links."
        (run-hooks 'org-after-sorting-entries-or-items-hook)
        (message "Sorting items...done")))))
 
+(defun org-toggle-item (arg)
+  "Convert headings or normal lines to items, items to normal lines.
+If there is no active region, only the current line is considered.
+
+If the first non blank line in the region is a headline, convert
+all headlines to items, shifting text accordingly.
+
+If it is an item, convert all items to normal lines.
+
+If it is normal text, change region into a list of items.
+With a prefix argument ARG, change the region in a single item."
+  (interactive "P")
+  (let ((shift-text
+        (lambda (ind end)
+          ;; Shift text in current section to IND, from point to END.
+          ;; The function leaves point to END line.
+          (let ((min-i 1000) (end (copy-marker end)))
+            ;; First determine the minimum indentation (MIN-I) of
+            ;; the text.
+            (save-excursion
+              (catch 'exit
+                (while (< (point) end)
+                  (let ((i (org-get-indentation)))
+                    (cond
+                     ;; Skip blank lines and inline tasks.
+                     ((looking-at "^[ \t]*$"))
+                     ((looking-at org-outline-regexp-bol))
+                     ;; We can't find less than 0 indentation.
+                     ((zerop i) (throw 'exit (setq min-i 0)))
+                     ((< i min-i) (setq min-i i))))
+                  (forward-line))))
+            ;; Then indent each line so that a line indented to
+            ;; MIN-I becomes indented to IND.  Ignore blank lines
+            ;; and inline tasks in the process.
+            (let ((delta (- ind min-i)))
+              (while (< (point) end)
+                (unless (or (looking-at "^[ \t]*$")
+                            (looking-at org-outline-regexp-bol))
+                  (indent-line-to (+ (org-get-indentation) delta)))
+                (forward-line))))))
+       (skip-blanks
+        (lambda (pos)
+          ;; Return beginning of first non-blank line, starting from
+          ;; line at POS.
+          (save-excursion
+            (goto-char pos)
+            (skip-chars-forward " \r\t\n")
+            (point-at-bol))))
+       beg end)
+    ;; Determine boundaries of changes.
+    (if (org-region-active-p)
+       (setq beg (funcall skip-blanks (region-beginning))
+             end (copy-marker (region-end)))
+      (setq beg (funcall skip-blanks (point-at-bol))
+           end (copy-marker (point-at-eol))))
+    ;; Depending on the starting line, choose an action on the text
+    ;; between BEG and END.
+    (org-with-limited-levels
+     (save-excursion
+       (goto-char beg)
+       (cond
+       ;; Case 1. Start at an item: de-itemize.  Note that it only
+       ;;         happens when a region is active: `org-ctrl-c-minus'
+       ;;         would call `org-cycle-list-bullet' otherwise.
+       ((org-at-item-p)
+        (while (< (point) end)
+          (when (org-at-item-p)
+            (skip-chars-forward " \t")
+            (delete-region (point) (match-end 0)))
+          (forward-line)))
+       ;; Case 2. Start at an heading: convert to items.
+       ((org-at-heading-p)
+        (let* ((bul (org-list-bullet-string "-"))
+               (bul-len (length bul))
+               ;; Indentation of the first heading.  It should be
+               ;; relative to the indentation of its parent, if any.
+               (start-ind (save-excursion
+                            (cond
+                             ((not org-adapt-indentation) 0)
+                             ((not (outline-previous-heading)) 0)
+                             (t (length (match-string 0))))))
+               ;; Level of first heading.  Further headings will be
+               ;; compared to it to determine hierarchy in the list.
+               (ref-level (org-reduced-level (org-outline-level))))
+          (while (< (point) end)
+            (let* ((level (org-reduced-level (org-outline-level)))
+                   (delta (max 0 (- level ref-level)))
+                   (todo-state (org-get-todo-state)))
+              ;; If current headline is less indented than the first
+              ;; one, set it as reference, in order to preserve
+              ;; subtrees.
+              (when (< level ref-level) (setq ref-level level))
+              ;; Remove stars and TODO keyword.
+              (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))
+              (delete-region (point) (or (match-beginning 3)
+                                         (line-end-position)))
+              (insert bul)
+              (indent-line-to (+ start-ind (* delta bul-len)))
+              ;; Turn TODO keyword into a check box.
+              (when todo-state
+                (let* ((struct (org-list-struct))
+                       (old (copy-tree struct)))
+                  (org-list-set-checkbox
+                   (line-beginning-position)
+                   struct
+                   (if (member todo-state org-done-keywords)
+                       "[X]"
+                     "[ ]"))
+                  (org-list-write-struct struct
+                                         (org-list-parents-alist struct)
+                                         old)))
+              ;; Ensure all text down to END (or SECTION-END) belongs
+              ;; to the newly created item.
+              (let ((section-end (save-excursion
+                                   (or (outline-next-heading) (point)))))
+                (forward-line)
+                (funcall shift-text
+                         (+ start-ind (* (1+ delta) bul-len))
+                         (min end section-end)))))))
+       ;; Case 3. Normal line with ARG: make the first line of region
+       ;;         an item, and shift indentation of others lines to
+       ;;         set them as item's body.
+       (arg (let* ((bul (org-list-bullet-string "-"))
+                   (bul-len (length bul))
+                   (ref-ind (org-get-indentation)))
+              (skip-chars-forward " \t")
+              (insert bul)
+              (forward-line)
+              (while (< (point) end)
+                ;; Ensure that lines less indented than first one
+                ;; still get included in item body.
+                (funcall shift-text
+                         (+ ref-ind bul-len)
+                         (min end (save-excursion (or (outline-next-heading)
+                                                      (point)))))
+                (forward-line))))
+       ;; Case 4. Normal line without ARG: turn each non-item line
+       ;;         into an item.
+       (t
+        (while (< (point) end)
+          (unless (or (org-at-heading-p) (org-at-item-p))
+            (when (looking-at "\\([ \t]*\\)\\(\\S-\\)")
+              (replace-match
+               (concat "\\1" (org-list-bullet-string "-") "\\2"))))
+          (forward-line))))))))
 
 
 ;;; Send and receive lists
 
-(defun org-list-parse-list (&optional delete)
+(defun org-list-to-lisp (&optional delete)
   "Parse the list at point and maybe DELETE it.
 
 Return a list whose car is a symbol of list type, among
 `ordered', `unordered' and `descriptive'.  Then, each item is
-a list whose car is counter, and cdr are strings and other
-sub-lists.  Inside strings, check-boxes are replaced by
-\"[CBON]\", \"[CBOFF]\" and \"[CBTRANS]\".
+a list of strings and other sub-lists.
 
 For example, the following list:
 
-1. first item
-   + sub-item one
-   + [X] sub-item two
-   more text in first item
-2. address@hidden last item
+  1. first item
+     + sub-item one
+     + [X] sub-item two
+     more text in first item
+  2. address@hidden last item
 
-will be parsed as:
+is parsed as
 
  (ordered
-  (nil \"first item\"
-  (unordered
-    (nil \"sub-item one\")
-    (nil \"[CBON] sub-item two\"))
-  \"more text in first item\")
-  (3 \"last item\"))
-
-Point is left at list end."
-  (defvar parse-item)                   ;FIXME: Or use `cl-labels' or `letrec'.
-  (let* ((struct (org-list-struct))
-        (prevs (org-list-prevs-alist struct))
-        (parents (org-list-parents-alist struct))
-        (top (org-list-get-top-point struct))
-        (bottom (org-list-get-bottom-point struct))
-        out
-        (get-text
-         (function
-          ;; Return text between BEG and END, trimmed, with
-          ;; checkboxes replaced.
-          (lambda (beg end)
-            (let ((text (org-trim (buffer-substring beg end))))
-              (if (string-match "\\`\\[\\([-X ]\\)\\]" text)
-                  (replace-match
-                   (let ((box (match-string 1 text)))
-                     (cond
-                      ((equal box " ") "CBOFF")
-                      ((equal box "-") "CBTRANS")
-                      (t "CBON")))
-                   t nil text 1)
-                text)))))
-        (parse-sublist
-         (function
-          ;; Return a list whose car is list type and cdr a list of
-          ;; items' body.
-          (lambda (e)
-            (cons (org-list-get-list-type (car e) struct prevs)
-                  (mapcar parse-item e)))))
-        (parse-item
-         (function
-          ;; Return a list containing counter of item, if any, text
-          ;; and any sublist inside it.
-          (lambda (e)
-            (let ((start (save-excursion
-                           (goto-char e)
-                           (looking-at "[ \t]*\\S-+\\([ 
address@hidden(start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\]\\)?[ \t]*")
-                           (match-end 0)))
-                  ;; Get counter number.  For alphabetic counter, get
-                  ;; its position in the alphabet.
-                  (counter (let ((c (org-list-get-counter e struct)))
-                             (cond
-                              ((not c) nil)
-                              ((string-match "[A-Za-z]" c)
-                               (- (string-to-char (upcase (match-string 0 c)))
-                                  64))
-                              ((string-match "[0-9]+" c)
-                               (string-to-number (match-string 0 c))))))
-                  (childp (org-list-has-child-p e struct))
-                  (end (org-list-get-item-end e struct)))
-              ;; If item has a child, store text between bullet and
-              ;; next child, then recursively parse all sublists.  At
-              ;; the end of each sublist, check for the presence of
-              ;; text belonging to the original item.
-              (if childp
-                  (let* ((children (org-list-get-children e struct parents))
-                         (body (list (funcall get-text start childp))))
-                    (while children
-                      (let* ((first (car children))
-                             (sub (org-list-get-all-items first struct prevs))
-                             (last-c (car (last sub)))
-                             (last-end (org-list-get-item-end last-c struct)))
-                        (push (funcall parse-sublist sub) body)
-                        ;; Remove children from the list just parsed.
-                        (setq children (cdr (member last-c children)))
-                        ;; There is a chunk of text belonging to the
-                        ;; item if last child doesn't end where next
-                        ;; child starts or where item ends.
-                        (unless (= (or (car children) end) last-end)
-                          (push (funcall get-text
-                                         last-end (or (car children) end))
-                                body))))
-                    (cons counter (nreverse body)))
-                (list counter (funcall get-text start end))))))))
+  (\"first item\"
+   (unordered
+    (\"sub-item one\")
+    (\"[X] sub-item two\"))
+   \"more text in first item\")
+  (\"address@hidden last item\"))
+
+Point is left at list's end."
+  (letrec ((struct (org-list-struct))
+          (prevs (org-list-prevs-alist struct))
+          (parents (org-list-parents-alist struct))
+          (top (org-list-get-top-point struct))
+          (bottom (org-list-get-bottom-point struct))
+          (trim
+           (lambda (text)
+             ;; Remove indentation and final newline from TEXT.
+             (org-remove-indentation
+              (if (string-match-p "\n\\'" text)
+                  (substring text 0 -1)
+                text))))
+          (parse-sublist
+           (lambda (e)
+             ;; Return a list whose car is list type and cdr a list
+             ;; of items' body.
+             (cons (org-list-get-list-type (car e) struct prevs)
+                   (mapcar parse-item e))))
+          (parse-item
+           (lambda (e)
+             ;; Return a list containing counter of item, if any,
+             ;; text and any sublist inside it.
+             (let* ((end (org-list-get-item-end e struct))
+                    (children (org-list-get-children e struct parents))
+                    (body
+                     (save-excursion
+                       (goto-char e)
+                       (looking-at "[ \t]*\\S-+[ \t]*")
+                       (list
+                        (funcall
+                         trim
+                         (concat
+                          (make-string (string-width (match-string 0)) ?\s)
+                          (buffer-substring-no-properties
+                           (match-end 0) (or (car children) end))))))))
+               (while children
+                 (let* ((child (car children))
+                        (sub (org-list-get-all-items child struct prevs))
+                        (last-in-sub (car (last sub))))
+                   (push (funcall parse-sublist sub) body)
+                   ;; Remove whole sub-list from children.
+                   (setq children (cdr (memq last-in-sub children)))
+                   ;; There is a chunk of text belonging to the item
+                   ;; if last child doesn't end where next child
+                   ;; starts or where item ends.
+                   (let ((sub-end (org-list-get-item-end last-in-sub struct))
+                         (next (or (car children) end)))
+                     (when (/= sub-end next)
+                       (push (funcall
+                              trim
+                              (buffer-substring-no-properties sub-end next))
+                             body)))))
+               (nreverse body)))))
     ;; Store output, take care of cursor position and deletion of
     ;; list, then return output.
-    (setq out (funcall parse-sublist (org-list-get-all-items top struct 
prevs)))
-    (goto-char top)
-    (when delete
-      (delete-region top bottom)
-      (when (and (not (looking-at "[ \t]*$")) (looking-at org-list-end-re))
-       (replace-match "")))
-    out))
+    (prog1 (funcall parse-sublist (org-list-get-all-items top struct prevs))
+      (goto-char top)
+      (when delete
+       (delete-region top bottom)
+       (when (and (not (looking-at "[ \t]*$")) (looking-at org-list-end-re))
+         (replace-match ""))))))
 
 (defun org-list-make-subtree ()
   "Convert the plain list at point into a subtree."
   (interactive)
   (if (not (ignore-errors (goto-char (org-in-item-p))))
       (error "Not in a list")
-    (let ((list (save-excursion (org-list-parse-list t))))
+    (let ((list (save-excursion (org-list-to-lisp t))))
       (insert (org-list-to-subtree list)))))
 
 (defun org-list-insert-radio-list ()
@@ -3055,11 +3230,13 @@ for this list."
   (catch 'exit
     (unless (org-at-item-p) (error "Not at a list item"))
     (save-excursion
-      (re-search-backward "#\\+ORGLST" nil t)
-      (unless (looking-at "#\\+ORGLST:[ \t]+SEND[ \t]+\\(\\S-+\\)[ 
\t]+\\(\\S-+\\)")
-       (if maybe (throw 'exit nil)
-         (error "Don't know how to transform this list"))))
-    (let* ((name (match-string 1))
+      (let ((case-fold-search t))
+       (re-search-backward "^[ \t]*#\\+ORGLST:" nil t)
+       (unless (looking-at
+                "[ \t]*#\\+ORGLST:[ \t]+SEND[ \t]+\\(\\S-+\\)[ \t]+\\([^ 
\t\n]+\\)")
+         (if maybe (throw 'exit nil)
+           (error "Don't know how to transform this list")))))
+    (let* ((name (regexp-quote (match-string 1)))
           (transform (intern (match-string 2)))
           (bottom-point
            (save-excursion
@@ -3071,220 +3248,342 @@ for this list."
              (re-search-backward "#\\+ORGLST" nil t)
              (re-search-forward (org-item-beginning-re) bottom-point t)
              (match-beginning 0)))
-          (plain-list (buffer-substring-no-properties top-point bottom-point))
-          beg)
+          (plain-list (save-excursion
+                        (goto-char top-point)
+                        (org-list-to-lisp))))
       (unless (fboundp transform)
        (error "No such transformation function %s" transform))
       (let ((txt (funcall transform plain-list)))
-       ;; Find the insertion place
+       ;; Find the insertion(s) place(s).
        (save-excursion
          (goto-char (point-min))
-         (unless (re-search-forward
-                  (concat "BEGIN RECEIVE ORGLST +"
-                          name
-                          "\\([ \t]\\|$\\)")
-                   nil t)
-           (error "Don't know where to insert translated list"))
-         (goto-char (match-beginning 0))
-         (beginning-of-line 2)
-         (setq beg (point))
-         (unless (re-search-forward (concat "END RECEIVE ORGLST +" name) nil t)
-           (error "Cannot find end of insertion region"))
-         (delete-region beg (point-at-bol))
-         (goto-char beg)
-         (insert txt "\n")))
-      (message "List converted and installed at receiver location"))))
-
-(defsubst org-list-item-trim-br (item)
-  "Trim line breaks in a list ITEM."
-  (setq item (replace-regexp-in-string "\n +" " " item)))
+         (let ((receiver-count 0)
+               (begin-re (format "BEGIN +RECEIVE +ORGLST +%s\\([ \t]\\|$\\)"
+                                 name))
+               (end-re (format "END +RECEIVE +ORGLST +%s\\([ \t]\\|$\\)"
+                               name)))
+           (while (re-search-forward begin-re nil t)
+             (cl-incf receiver-count)
+             (let ((beg (line-beginning-position 2)))
+               (unless (re-search-forward end-re nil t)
+                 (user-error "Cannot find end of receiver location at %d" beg))
+               (beginning-of-line)
+               (delete-region beg (point))
+               (insert txt "\n")))
+           (cond
+            ((> receiver-count 1)
+             (message "List converted and installed at receiver locations"))
+            ((= receiver-count 1)
+             (message "List converted and installed at receiver location"))
+            (t (user-error "No valid receiver location found")))))))))
 
 (defun org-list-to-generic (list params)
-  "Convert a LIST parsed through `org-list-parse-list' to other formats.
-Valid parameters PARAMS are:
-
-:ustart            String to start an unordered list
-:uend      String to end an unordered list
-
-:ostart            String to start an ordered list
-:oend      String to end an ordered list
-
-:dstart            String to start a descriptive list
-:dend      String to end a descriptive list
-:dtstart    String to start a descriptive term
-:dtend     String to end a descriptive term
-:ddstart    String to start a description
-:ddend     String to end a description
-
-:splice            When set to t, return only list body lines, don't wrap
-           them into :[u/o]start and :[u/o]end.  Default is nil.
-
-:istart            String to start a list item.
-:icount     String to start an item with a counter.
-:iend      String to end a list item
-:isep      String to separate items
-:lsep      String to separate sublists
-:csep      String to separate text from a sub-list
-
-:cboff      String to insert for an unchecked check-box
-:cbon       String to insert for a checked check-box
-:cbtrans    String to insert for a check-box in transitional state
-
-:nobr       Non-nil means remove line breaks in lists items.
-
-Alternatively, each parameter can also be a form returning
-a string.  These sexp can use keywords `counter' and `depth',
-representing respectively counter associated to the current
-item, and depth of the current sub-list, starting at 0.
-Obviously, `counter' is only available for parameters applying to
-items."
-  (interactive)
-  (let* ((p params)
-        (splicep (plist-get p :splice))
-        (ostart (plist-get p :ostart))
-        (oend (plist-get p :oend))
-        (ustart (plist-get p :ustart))
-        (uend (plist-get p :uend))
-        (dstart (plist-get p :dstart))
-        (dend (plist-get p :dend))
-        (dtstart (plist-get p :dtstart))
-        (dtend (plist-get p :dtend))
-        (ddstart (plist-get p :ddstart))
-        (ddend (plist-get p :ddend))
-        (istart (plist-get p :istart))
-        (icount (plist-get p :icount))
-        (iend (plist-get p :iend))
-        (isep (plist-get p :isep))
-        (lsep (plist-get p :lsep))
-        (csep (plist-get p :csep))
-        (cbon (plist-get p :cbon))
-        (cboff (plist-get p :cboff))
-        (cbtrans (plist-get p :cbtrans))
-        (nobr (plist-get p :nobr))
-        export-sublist                 ; for byte-compiler
-        (export-item
-         (function
-          ;; Export an item ITEM of type TYPE, at DEPTH.  First
-          ;; string in item is treated in a special way as it can
-          ;; bring extra information that needs to be processed.
-          (lambda (item type depth)
-            (let* ((counter (pop item))
-                   (fmt (concat
-                         (cond
-                          ((eq type 'descriptive)
-                           ;; Stick DTSTART to ISTART by
-                           ;; left-trimming the latter.
-                           (concat (let ((s (eval istart)))
-                                     (or (and (string-match "[ \t\n\r]+\\'" s)
-                                              (replace-match "" t t s))
-                                         istart))
-                                   "%s" (eval ddend)))
-                          ((and counter (eq type 'ordered))
-                           (concat (eval icount) "%s"))
-                          (t (concat (eval istart) "%s")))
-                         (eval iend)))
-                   (first (car item)))
-              ;; Replace checkbox if any is found.
-              (cond
-               ((string-match "\\[CBON\\]" first)
-                (setq first (replace-match cbon t t first)))
-               ((string-match "\\[CBOFF\\]" first)
-                (setq first (replace-match cboff t t first)))
-               ((string-match "\\[CBTRANS\\]" first)
-                (setq first (replace-match cbtrans t t first))))
-              ;; Replace line breaks if required
-              (when nobr (setq first (org-list-item-trim-br first)))
-              ;; Insert descriptive term if TYPE is `descriptive'.
-              (when (eq type 'descriptive)
-                (let* ((complete (string-match "^\\(.*\\)[ \t]+::" first))
-                       (term (if complete
-                                 (save-match-data
-                                   (org-trim (match-string 1 first)))
-                               "???"))
-                       (desc (if complete
-                                 (org-trim (substring first (match-end 0)))
-                               first)))
-                  (setq first (concat (eval dtstart) term (eval dtend)
-                                      (eval ddstart) desc))))
-              (setcar item first)
-              (format fmt
-                      (mapconcat (lambda (e)
-                                   (if (stringp e) e
-                                     (funcall export-sublist e (1+ depth))))
-                                 item (or (eval csep) "")))))))
-        (export-sublist
-         (function
-          ;; Export sublist SUB at DEPTH.
-          (lambda (sub depth)
-            (let* ((type (car sub))
-                   (items (cdr sub))
-                   (fmt (concat (cond
-                                 (splicep "%s")
-                                 ((eq type 'ordered)
-                                  (concat (eval ostart) "%s" (eval oend)))
-                                 ((eq type 'descriptive)
-                                  (concat (eval dstart) "%s" (eval dend)))
-                                 (t (concat (eval ustart) "%s" (eval uend))))
-                                (eval lsep))))
-              (format fmt (mapconcat (lambda (e)
-                                       (funcall export-item e type depth))
-                                     items (or (eval isep) ""))))))))
-    (concat (funcall export-sublist list 0) "\n")))
-
-(defun org-list-to-latex (list &optional _params)
+  "Convert a LIST parsed through `org-list-to-lisp' to a custom format.
+
+LIST is a list as returned by `org-list-to-lisp', which see.
+PARAMS is a property list of parameters used to tweak the output
+format.
+
+Valid parameters are:
+
+:backend, :raw
+
+  Export back-end used as a basis to transcode elements of the
+  list, when no specific parameter applies to it.  It is also
+  used to translate its contents.  You can prevent this by
+  setting :raw property to a non-nil value.
+
+:splice
+
+  When non-nil, only export the contents of the top most plain
+  list, effectively ignoring its opening and closing lines.
+
+:ustart, :uend
+
+  Strings to start and end an unordered list.  They can also be
+  set to a function returning a string or nil, which will be
+  called with the depth of the list, counting from 1.
+
+:ostart, :oend
+
+  Strings to start and end an ordered list.  They can also be set
+  to a function returning a string or nil, which will be called
+  with the depth of the list, counting from 1.
+
+:dstart, :dend
+
+  Strings to start and end a descriptive list.  They can also be
+  set to a function returning a string or nil, which will be
+  called with the depth of the list, counting from 1.
+
+:dtstart, :dtend, :ddstart, :ddend
+
+  Strings to start and end a descriptive term.
+
+:istart, :iend
+
+  Strings to start or end a list item, and to start a list item
+  with a counter.  They can also be set to a function returning
+  a string or nil, which will be called with the depth of the
+  item, counting from 1.
+
+:icount
+
+  Strings to start a list item with a counter.  It can also be
+  set to a function returning a string or nil, which will be
+  called with two arguments: the depth of the item, counting from
+  1, and the counter.  Its value, when non-nil, has precedence
+  over `:istart'.
+
+:isep
+
+  String used to separate items.  It can also be set to
+  a function returning a string or nil, which will be called with
+  the depth of the items, counting from 1.  It always start on
+  a new line.
+
+:cbon, :cboff, :cbtrans
+
+  String to insert, respectively, an un-checked check-box,
+  a checked check-box and a check-box in transitional state."
+  (require 'ox)
+  (let* ((backend (plist-get params :backend))
+        (custom-backend
+         (org-export-create-backend
+          :parent (or backend 'org)
+          :transcoders
+          `((plain-list . ,(org-list--to-generic-plain-list params))
+            (item . ,(org-list--to-generic-item params))
+            (macro . (lambda (m c i) (org-element-macro-interpreter m nil))))))
+        data info)
+    ;; Write LIST back into Org syntax and parse it.
+    (with-temp-buffer
+      (let ((org-inhibit-startup t)) (org-mode))
+      (letrec ((insert-list
+               (lambda (l)
+                 (dolist (i (cdr l))
+                   (funcall insert-item i (car l)))))
+              (insert-item
+               (lambda (i type)
+                 (let ((start (point)))
+                   (insert (if (eq type 'ordered) "1. " "- "))
+                   (dolist (e i)
+                     (if (consp e) (funcall insert-list e)
+                       (insert e)
+                       (insert "\n")))
+                   (beginning-of-line)
+                   (save-excursion
+                     (let ((ind (if (eq type 'ordered) 3 2)))
+                       (while (> (point) start)
+                         (unless (looking-at-p "[ \t]*$")
+                           (indent-to ind))
+                         (forward-line -1))))))))
+       (funcall insert-list list))
+      (setf data
+           (org-element-map (org-element-parse-buffer) 'plain-list
+             #'identity nil t))
+      (setf info (org-export-get-environment backend nil params)))
+    (when (and backend (symbolp backend) (not (org-export-get-backend 
backend)))
+      (user-error "Unknown :backend value"))
+    (unless backend (require 'ox-org))
+    ;; When`:raw' property has a non-nil value, turn all objects back
+    ;; into Org syntax.
+    (when (and backend (plist-get params :raw))
+      (org-element-map data org-element-all-objects
+       (lambda (object)
+         (org-element-set-element
+          object (org-element-interpret-data object)))))
+    ;; We use a low-level mechanism to export DATA so as to skip all
+    ;; usual pre-processing and post-processing, i.e., hooks, filters,
+    ;; Babel code evaluation, include keywords and macro expansion,
+    ;; and filters.
+    (let ((output (org-export-data-with-backend data custom-backend info)))
+      ;; Remove final newline.
+      (if (org-string-nw-p output) (substring-no-properties output 0 -1) ""))))
+
+(defun org-list--depth (element)
+  "Return the level of ELEMENT within current plain list.
+ELEMENT is either an item or a plain list."
+  (cl-count-if (lambda (ancestor) (eq (org-element-type ancestor) 'plain-list))
+              (org-element-lineage element nil t)))
+
+(defun org-list--trailing-newlines (string)
+  "Return the number of trailing newlines in STRING."
+  (with-temp-buffer
+    (insert string)
+    (skip-chars-backward " \t\n")
+    (count-lines (line-beginning-position 2) (point-max))))
+
+(defun org-list--generic-eval (value &rest args)
+  "Evaluate VALUE according to its type.
+VALUE is either nil, a string or a function.  In the latter case,
+it is called with arguments ARGS."
+  (cond ((null value) nil)
+       ((stringp value) value)
+       ((functionp value) (apply value args))
+       (t (error "Wrong value: %s" value))))
+
+(defun org-list--to-generic-plain-list (params)
+  "Return a transcoder for `plain-list' elements.
+PARAMS is a plist used to tweak the behavior of the transcoder."
+  (let ((ustart (plist-get params :ustart))
+       (uend (plist-get params :uend))
+       (ostart (plist-get params :ostart))
+       (oend (plist-get params :oend))
+       (dstart (plist-get params :dstart))
+       (dend (plist-get params :dend))
+       (splice (plist-get params :splice))
+       (backend (plist-get params :backend)))
+    (lambda (plain-list contents info)
+      (let* ((type (org-element-property :type plain-list))
+            (depth (org-list--depth plain-list))
+            (start (and (not splice)
+                        (org-list--generic-eval
+                         (pcase type
+                           (`ordered ostart)
+                           (`unordered ustart)
+                           (_ dstart))
+                         depth)))
+            (end (and (not splice)
+                      (org-list--generic-eval
+                       (pcase type
+                         (`ordered oend)
+                         (`unordered uend)
+                         (_ dend))
+                       depth))))
+       ;; Make sure trailing newlines in END appear in the output by
+       ;; setting `:post-blank' property to their number.
+       (when end
+         (org-element-put-property
+          plain-list :post-blank (org-list--trailing-newlines end)))
+       ;; Build output.
+       (concat (and start (concat start "\n"))
+               (if (or start end splice (not backend))
+                   contents
+                 (org-export-with-backend backend plain-list contents info))
+               end)))))
+
+(defun org-list--to-generic-item (params)
+  "Return a transcoder for `item' elements.
+PARAMS is a plist used to tweak the behavior of the transcoder."
+  (let ((backend (plist-get params :backend))
+       (istart (plist-get params :istart))
+       (iend (plist-get params :iend))
+       (isep (plist-get params :isep))
+       (icount (plist-get params :icount))
+       (cboff (plist-get params :cboff))
+       (cbon  (plist-get params :cbon))
+       (cbtrans (plist-get params :cbtrans))
+       (dtstart (plist-get params :dtstart))
+       (dtend (plist-get params :dtend))
+       (ddstart (plist-get params :ddstart))
+       (ddend (plist-get params :ddend)))
+    (lambda (item contents info)
+      (let* ((type
+             (org-element-property :type (org-element-property :parent item)))
+            (tag (org-element-property :tag item))
+            (depth (org-list--depth item))
+            (separator (and (org-export-get-next-element item info)
+                            (org-list--generic-eval isep depth)))
+            (closing (pcase (org-list--generic-eval iend depth)
+                       ((or `nil `"") "\n")
+                       ((and (guard separator) s)
+                        (if (equal (substring s -1) "\n") s (concat s "\n")))
+                       (s s))))
+       ;; When a closing line or a separator is provided, make sure
+       ;; its trailing newlines are taken into account when building
+       ;; output.  This is done by setting `:post-blank' property to
+       ;; the number of such lines in the last line to be added.
+       (let ((last-string (or separator closing)))
+         (when last-string
+           (org-element-put-property
+            item
+            :post-blank
+            (max (1- (org-list--trailing-newlines last-string)) 0))))
+       ;; Build output.
+       (concat
+        (let ((c (org-element-property :counter item)))
+          (if c (org-list--generic-eval icount depth c)
+            (org-list--generic-eval istart depth)))
+        (let ((body
+               (if (or istart iend icount cbon cboff cbtrans (not backend)
+                       (and (eq type 'descriptive)
+                            (or dtstart dtend ddstart ddend)))
+                   (concat
+                    (pcase (org-element-property :checkbox item)
+                      (`on cbon)
+                      (`off cboff)
+                      (`trans cbtrans))
+                    (and tag
+                         (concat dtstart
+                                 (if backend
+                                     (org-export-data-with-backend
+                                      tag backend info)
+                                   (org-element-interpret-data tag))
+                                 dtend))
+                    (and tag ddstart)
+                    (if (= (length contents) 0) "" (substring contents 0 -1))
+                    (and tag ddend))
+                 (org-export-with-backend backend item contents info))))
+          ;; Remove final newline.
+          (if (equal body "") ""
+            (substring (org-element-normalize-string body) 0 -1)))
+        closing
+        separator)))))
+
+(defun org-list-to-latex (list &optional params)
   "Convert LIST into a LaTeX list.
-LIST is as string representing the list to transform, as Org
-syntax.  Return converted list as a string."
+LIST is a parsed plain list, as returned by `org-list-to-lisp'.
+PARAMS is a property list with overruling parameters for
+`org-list-to-generic'.  Return converted list as a string."
   (require 'ox-latex)
-  (org-export-string-as list 'latex t))
+  (org-list-to-generic list (org-combine-plists '(:backend latex) params)))
 
-(defun org-list-to-html (list)
+(defun org-list-to-html (list &optional params)
   "Convert LIST into a HTML list.
-LIST is as string representing the list to transform, as Org
-syntax.  Return converted list as a string."
+LIST is a parsed plain list, as returned by `org-list-to-lisp'.
+PARAMS is a property list with overruling parameters for
+`org-list-to-generic'.  Return converted list as a string."
   (require 'ox-html)
-  (org-export-string-as list 'html t))
+  (org-list-to-generic list (org-combine-plists '(:backend html) params)))
 
-(defun org-list-to-texinfo (list &optional _params)
+(defun org-list-to-texinfo (list &optional params)
   "Convert LIST into a Texinfo list.
-LIST is as string representing the list to transform, as Org
-syntax.  Return converted list as a string."
+LIST is a parsed plain list, as returned by `org-list-to-lisp'.
+PARAMS is a property list with overruling parameters for
+`org-list-to-generic'.  Return converted list as a string."
   (require 'ox-texinfo)
-  (org-export-string-as list 'texinfo t))
+  (org-list-to-generic list (org-combine-plists '(:backend texinfo) params)))
 
 (defun org-list-to-subtree (list &optional params)
   "Convert LIST into an Org subtree.
-LIST is as returned by `org-list-parse-list'.  PARAMS is a property list
-with overruling parameters for `org-list-to-generic'."
-  (defvar get-stars) (defvar org--blankp)
-  (let* ((rule (cdr (assq 'heading org-blank-before-new-entry)))
+LIST is as returned by `org-list-to-lisp'.  PARAMS is a property
+list with overruling parameters for `org-list-to-generic'."
+  (let* ((blank (pcase (cdr (assq 'heading org-blank-before-new-entry))
+                 (`t t)
+                 (`auto (save-excursion
+                          (org-with-limited-levels (outline-previous-heading))
+                          (org-previous-line-empty-p)))))
         (level (org-reduced-level (or (org-current-level) 0)))
-        (org--blankp (or (eq rule t)
-                    (and (eq rule 'auto)
-                         (save-excursion
-                           (outline-previous-heading)
-                           (org-previous-line-empty-p)))))
-        (get-stars ;FIXME: Can't rename without renaming it in org.el as well!
-         (function
-          ;; Return the string for the heading, depending on depth D
-          ;; of current sub-list.
-          (lambda (d)
-            (let ((oddeven-level (+ level d 1)))
-              (concat (make-string (if org-odd-levels-only
-                                       (1- (* 2 oddeven-level))
-                                     oddeven-level)
-                                   ?*)
-                      " "))))))
+        (make-stars
+         (lambda (depth)
+           ;; Return the string for the heading, depending on DEPTH
+           ;; of current sub-list.
+           (let ((oddeven-level (+ level depth)))
+             (concat (make-string (if org-odd-levels-only
+                                      (1- (* 2 oddeven-level))
+                                    oddeven-level)
+                                  ?*)
+                     " ")))))
     (org-list-to-generic
      list
      (org-combine-plists
-      '(:splice t
-        :dtstart " " :dtend " "
-        :istart (funcall get-stars depth)
-        :icount (funcall get-stars depth)
-        :isep (if org--blankp "\n\n" "\n")
-        :csep (if org--blankp "\n\n" "\n")
-        :cbon "DONE" :cboff "TODO" :cbtrans "TODO")
+      (list :splice t
+           :istart make-stars
+           :icount make-stars
+           :dtstart " " :dtend " "
+           :isep (if blank "\n\n" "\n")
+           :cbon "DONE " :cboff "TODO " :cbtrans "TODO ")
       params))))
 
 (provide 'org-list)
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index f4919d1..3dc9c54 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -1,4 +1,4 @@
-;;; org-macro.el --- Macro Replacement Code for Org Mode
+;;; org-macro.el --- Macro Replacement Code for Org  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
 
@@ -30,6 +30,10 @@
 ;; `org-macro-initialize-templates', which recursively calls
 ;; `org-macro--collect-macros' in order to read setup files.
 
+;; Argument in macros are separated with commas. Proper escaping rules
+;; are implemented in `org-macro-escape-arguments' and arguments can
+;; be extracted from a string with `org-macro-extract-arguments'.
+
 ;; Along with macros defined through #+MACRO: keyword, default
 ;; templates include the following hard-coded macros:
 ;; {{{time(format-string)}}}, {{{property(node-property)}}},
@@ -39,19 +43,25 @@
 ;; {{{email}}} and {{{title}}} macros.
 
 ;;; Code:
+(require 'cl-lib)
 (require 'org-macs)
+(require 'org-compat)
 
-(declare-function org-element-at-point "org-element" (&optional keep-trail))
+(declare-function org-element-at-point "org-element" ())
 (declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-macro-parser "org-element" ())
 (declare-function org-element-property "org-element" (property element))
 (declare-function org-element-type "org-element" (element))
-(declare-function org-remove-double-quotes "org" (s))
-(declare-function org-mode "org" ())
 (declare-function org-file-contents "org" (file &optional noerror))
+(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
+(declare-function org-mode "org" ())
+(declare-function vc-backend "vc-hooks" (f))
+(declare-function vc-call "vc-hooks" (fun file &rest args) t)
+(declare-function vc-exec-after "vc-dispatcher" (code))
 
 ;;; Variables
 
-(defvar org-macro-templates nil
+(defvar-local org-macro-templates nil
   "Alist containing all macro templates in current buffer.
 Associations are in the shape of (NAME . TEMPLATE) where NAME
 stands for macro's name and template for its replacement value,
@@ -59,48 +69,48 @@ both as strings.  This is an internal variable.  Do not set 
it
 directly, use instead:
 
   #+MACRO: name template")
-(make-variable-buffer-local 'org-macro-templates)
-
 
 ;;; Functions
 
 (defun org-macro--collect-macros ()
   "Collect macro definitions in current buffer and setup files.
 Return an alist containing all macro templates found."
-  (let* (collect-macros                        ; For byte-compiler.
-        (collect-macros
-         (lambda (files templates)
-           ;; Return an alist of macro templates.  FILES is a list of
-           ;; setup files names read so far, used to avoid circular
-           ;; dependencies.  TEMPLATES is the alist collected so far.
-           (let ((case-fold-search t))
-             (org-with-wide-buffer
-              (goto-char (point-min))
-              (while (re-search-forward
-                      "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t)
-                (let ((element (org-element-at-point)))
-                  (when (eq (org-element-type element) 'keyword)
-                    (let ((val (org-element-property :value element)))
-                      (if (equal (org-element-property :key element) "MACRO")
-                          ;; Install macro in TEMPLATES.
-                          (when (string-match
-                                 "^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" val)
-                            (let* ((name (match-string 1 val))
-                                   (template (or (match-string 2 val) ""))
-                                   (old-cell (assoc name templates)))
-                              (if old-cell (setcdr old-cell template)
-                                (push (cons name template) templates))))
-                        ;; Enter setup file.
-                        (let ((file (expand-file-name
-                                     (org-remove-double-quotes val))))
-                          (unless (member file files)
-                            (with-temp-buffer
-                              (org-mode)
-                              (insert (org-file-contents file 'noerror))
-                              (setq templates
-                                    (funcall collect-macros (cons file files)
-                                             templates)))))))))))
-             templates))))
+  (letrec ((collect-macros
+           (lambda (files templates)
+             ;; Return an alist of macro templates.  FILES is a list
+             ;; of setup files names read so far, used to avoid
+             ;; circular dependencies.  TEMPLATES is the alist
+             ;; collected so far.
+             (let ((case-fold-search t))
+               (org-with-wide-buffer
+                (goto-char (point-min))
+                (while (re-search-forward
+                        "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t)
+                  (let ((element (org-element-at-point)))
+                    (when (eq (org-element-type element) 'keyword)
+                      (let ((val (org-element-property :value element)))
+                        (if (equal (org-element-property :key element) "MACRO")
+                            ;; Install macro in TEMPLATES.
+                            (when (string-match
+                                   "^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" 
val)
+                              (let* ((name (match-string 1 val))
+                                     (template (or (match-string 2 val) ""))
+                                     (old-cell (assoc name templates)))
+                                (if old-cell (setcdr old-cell template)
+                                  (push (cons name template) templates))))
+                          ;; Enter setup file.
+                          (let ((file (expand-file-name
+                                       (org-unbracket-string "\"" "\"" val))))
+                            (unless (member file files)
+                              (with-temp-buffer
+                                (setq default-directory
+                                      (file-name-directory file))
+                                (org-mode)
+                                (insert (org-file-contents file 'noerror))
+                                (setq templates
+                                      (funcall collect-macros (cons file files)
+                                               templates)))))))))))
+               templates))))
     (funcall collect-macros nil nil)))
 
 (defun org-macro-initialize-templates ()
@@ -117,15 +127,26 @@ function installs the following ones: \"property\",
              (if old-template (setcdr old-template (cdr cell))
                (push cell templates))))))
     ;; Install hard-coded macros.
-    (mapc (lambda (cell) (funcall update-templates cell))
-         (list (cons "property" "(eval (org-entry-get nil \"$1\" 'selective))")
+    (mapc update-templates
+         (list (cons "property"
+                     "(eval (save-excursion
+        (let ((l \"$2\"))
+          (when (org-string-nw-p l)
+            (condition-case _
+                (let ((org-link-search-must-match-exact-headline t))
+                  (org-link-search l nil t))
+              (error
+               (error \"Macro property failed: cannot find location %s\"
+                      l)))))
+        (org-entry-get nil \"$1\" 'selective)))")
                (cons "time" "(eval (format-time-string \"$1\"))")))
     (let ((visited-file (buffer-file-name (buffer-base-buffer))))
       (when (and visited-file (file-exists-p visited-file))
-       (mapc (lambda (cell) (funcall update-templates cell))
+       (mapc update-templates
              (list (cons "input-file" (file-name-nondirectory visited-file))
                    (cons "modification-time"
-                         (format "(eval (format-time-string \"$1\" '%s))"
+                         (format "(eval (format-time-string \"$1\" (or (and 
(org-string-nw-p \"$2\") (org-macro--vc-modified-time %s)) '%s)))"
+                                 (prin1-to-string visited-file)
                                  (prin1-to-string
                                   (nth 5 (file-attributes visited-file)))))))))
     (setq org-macro-templates templates)))
@@ -154,38 +175,132 @@ default value.  Return nil if no template was found."
         ;; Return string.
         (format "%s" (or value ""))))))
 
-(defun org-macro-replace-all (templates)
+(defun org-macro-replace-all (templates &optional finalize keywords)
   "Replace all macros in current buffer by their expansion.
+
 TEMPLATES is an alist of templates used for expansion.  See
-`org-macro-templates' for a buffer-local default value."
+`org-macro-templates' for a buffer-local default value.
+
+If optional arg FINALIZE is non-nil, raise an error if a macro is
+found in the buffer with no definition in TEMPLATES.
+
+Optional argument KEYWORDS, when non-nil is a list of keywords,
+as strings, where macro expansion is allowed."
   (save-excursion
     (goto-char (point-min))
-    (let (record)
+    (let ((properties-regexp
+          (format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords)))
+         record)
       (while (re-search-forward "{{{[-A-Za-z0-9_]" nil t)
-       (let ((object (org-element-context)))
-         (when (eq (org-element-type object) 'macro)
-           (let* ((value (org-macro-expand object templates))
-                  (begin (org-element-property :begin object))
-                  (signature (list begin
-                                   object
-                                   (org-element-property :args object))))
-             ;; Avoid circular dependencies by checking if the same
-             ;; macro with the same arguments is expanded at the same
-             ;; position twice.
-             (if (member signature record)
-                 (error "Circular macro expansion: %s"
-                        (org-element-property :key object))
-               (when value
-                 (push signature record)
-                 (delete-region
-                  begin
-                  ;; Preserve white spaces after the macro.
-                  (progn (goto-char (org-element-property :end object))
-                         (skip-chars-backward " \t")
-                         (point)))
-                 ;; Leave point before replacement in case of recursive
-                 ;; expansions.
-                 (save-excursion (insert value)))))))))))
+       (unless (save-match-data (org-in-commented-heading-p))
+         (let* ((datum (save-match-data (org-element-context)))
+                (type (org-element-type datum))
+                (macro
+                 (cond
+                  ((eq type 'macro) datum)
+                  ;; In parsed keywords and associated node
+                  ;; properties, force macro recognition.
+                  ((or (and (eq type 'keyword)
+                            (member (org-element-property :key datum)
+                                    keywords))
+                       (and (eq type 'node-property)
+                            (string-match-p properties-regexp
+                                            (org-element-property :key
+                                                                  datum))))
+                   (save-excursion
+                     (goto-char (match-beginning 0))
+                     (org-element-macro-parser))))))
+           (when macro
+             (let* ((value (org-macro-expand macro templates))
+                    (begin (org-element-property :begin macro))
+                    (signature (list begin
+                                     macro
+                                     (org-element-property :args macro))))
+               ;; Avoid circular dependencies by checking if the same
+               ;; macro with the same arguments is expanded at the
+               ;; same position twice.
+               (cond ((member signature record)
+                      (error "Circular macro expansion: %s"
+                             (org-element-property :key macro)))
+                     (value
+                      (push signature record)
+                      (delete-region
+                       begin
+                       ;; Preserve white spaces after the macro.
+                       (progn (goto-char (org-element-property :end macro))
+                              (skip-chars-backward " \t")
+                              (point)))
+                      ;; Leave point before replacement in case of
+                      ;; recursive expansions.
+                      (save-excursion (insert value)))
+                     (finalize
+                      (error "Undefined Org macro: %s; aborting"
+                             (org-element-property :key macro))))))))))))
+
+(defun org-macro-escape-arguments (&rest args)
+  "Build macro's arguments string from ARGS.
+ARGS are strings.  Return value is a string with arguments
+properly escaped and separated with commas.  This is the opposite
+of `org-macro-extract-arguments'."
+  (let ((s ""))
+    (dolist (arg (reverse args) (substring s 1))
+      (setq s
+           (concat
+            ","
+            (replace-regexp-in-string
+             "\\(\\\\*\\),"
+             (lambda (m)
+               (concat (make-string (1+ (* 2 (length (match-string 1 m)))) ?\\)
+                       ","))
+             ;; If a non-terminal argument ends on backslashes, make
+             ;; sure to also escape them as they will be followed by
+             ;; a comma.
+             (concat arg (and (not (equal s ""))
+                              (string-match "\\\\+\\'" arg)
+                              (match-string 0 arg)))
+             nil t)
+            s)))))
+
+(defun org-macro-extract-arguments (s)
+  "Extract macro arguments from string S.
+S is a string containing comma separated values properly escaped.
+Return a list of arguments, as strings.  This is the opposite of
+`org-macro-escape-arguments'."
+  ;; Do not use `org-split-string' since empty strings are
+  ;; meaningful here.
+  (split-string
+   (replace-regexp-in-string
+    "\\(\\\\*\\),"
+    (lambda (str)
+      (let ((len (length (match-string 1 str))))
+       (concat (make-string (/ len 2) ?\\)
+               (if (zerop (mod len 2)) "\000" ","))))
+    s nil t)
+   "\000"))
+
+(defun org-macro--vc-modified-time (file)
+  (save-window-excursion
+    (when (vc-backend file)
+      (let ((buf (get-buffer-create " *org-vc*"))
+           (case-fold-search t)
+           date)
+       (unwind-protect
+           (progn
+             (vc-call print-log file buf nil nil 1)
+             (with-current-buffer buf
+               (vc-exec-after
+                (lambda ()
+                  (goto-char (point-min))
+                  (when (re-search-forward "Date:?[ \t]*" nil t)
+                    (let ((time (parse-time-string
+                                 (buffer-substring
+                                  (point) (line-end-position)))))
+                      (when (cl-some #'identity time)
+                        (setq date (apply #'encode-time time))))))))
+             (let ((proc (get-buffer-process buf)))
+               (while (and proc (accept-process-output proc .5 nil t)))))
+         (kill-buffer buf))
+       date))))
 
 
 (provide 'org-macro)
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 64e28ce..ca47e5a 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -1,4 +1,4 @@
-;;; org-macs.el --- Top-level definitions for Org-mode
+;;; org-macs.el --- Top-level Definitions for Org -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -25,29 +25,12 @@
 ;;; Commentary:
 
 ;; This file contains macro definitions, defsubst definitions, other
-;; stuff needed for compilation and top-level forms in Org-mode, as well
-;; lots of small functions that are not org-mode specific but simply
-;; generally useful stuff.
+;; stuff needed for compilation and top-level forms in Org mode, as
+;; well lots of small functions that are not Org mode specific but
+;; simply generally useful stuff.
 
 ;;; Code:
 
-(eval-and-compile
-  (unless (fboundp 'declare-function)
-    (defmacro declare-function (fn file &optional _arglist _fileonly)
-      `(autoload ',fn ,file)))
-
-  (if (>= emacs-major-version 23)
-      (defsubst org-char-to-string(c)
-       "Defsubst to decode UTF-8 character values in emacs 23 and beyond."
-       (char-to-string c))
-    (defsubst org-char-to-string (c)
-      "Defsubst to decode UTF-8 character values in emacs 22."
-      (string (decode-char 'ucs c)))))
-
-(declare-function org-add-props "org-compat" (string plist &rest props))
-(declare-function org-string-match-p "org-compat"
-                  (regexp string &optional start))
-
 (defmacro org-with-gensyms (symbols &rest body)
   (declare (debug (sexp body)) (indent 1))
   `(let ,(mapcar (lambda (s)
@@ -55,26 +38,11 @@
                  symbols)
      ,@body))
 
-(defmacro org-called-interactively-p (&optional kind)
-  (declare (debug (&optional ("quote" symbolp)))) ;Why not just t?
-  (if (featurep 'xemacs)
-      `(interactive-p)
-    (if (or (> emacs-major-version 23)
-           (and (>= emacs-major-version 23)
-                (>= emacs-minor-version 2)))
-       ;; defined with no argument in <=23.1
-       `(with-no-warnings (called-interactively-p ,kind))
-      `(interactive-p))))
-
-(defmacro org-bound-and-true-p (var)
-  "Return the value of symbol VAR if it is bound, else nil."
-  (declare (debug (symbolp)))
-  `(and (boundp (quote ,var)) ,var))
-
 (defun org-string-nw-p (s)
-  "Is S a string with a non-white character?"
+  "Return S if S is a string containing a non-blank character.
+Otherwise, return nil."
   (and (stringp s)
-       (org-string-match-p "\\S-" s)
+       (string-match-p "[^ \r\t\n]" s)
        s))
 
 (defun org-not-nil (v)
@@ -82,25 +50,6 @@
 Otherwise return nil."
   (and v (not (equal v "nil")) v))
 
-(defun org-substitute-posix-classes (re)
-  "Substitute posix classes in regular expression RE."
-  (let ((ss re))
-    (save-match-data
-      (while (string-match "\\[:alnum:\\]" ss)
-       (setq ss (replace-match "a-zA-Z0-9" t t ss)))
-      (while (string-match "\\[:word:\\]" ss)
-       (setq ss (replace-match "a-zA-Z0-9" t t ss)))
-      (while (string-match "\\[:alpha:\\]" ss)
-       (setq ss (replace-match "a-zA-Z" t t ss)))
-      (while (string-match "\\[:punct:\\]" ss)
-       (setq ss (replace-match "address@hidden" t t ss)))
-      ss)))
-
-(defmacro org-re (s)
-  "Replace posix classes in regular expression."
-  (declare (debug (form)))
-  (if (featurep 'xemacs) `(org-substitute-posix-classes ,s) s))
-
 (defmacro org-preserve-lc (&rest body)
   (declare (debug (body)))
   (org-with-gensyms (line col)
@@ -136,19 +85,6 @@ Otherwise return nil."
         (partial-completion-mode 1))
      ,@body))
 
-;; FIXME: Slated for removal.  Current Org mode does not support Emacs < 22
-(defmacro org-maybe-intangible (props)
-  "Add (intangible t) to PROPS if Emacs version is earlier than Emacs 22.
-In Emacs 21, invisible text is not avoided by the command loop, so the
-intangible property is needed to make sure point skips this text.
-In Emacs 22, this is not necessary.  The intangible text property has
-led to problems with flyspell.  These problems are fixed in flyspell.el,
-but we still avoid setting the property in Emacs 22 and later.
-We use a macro so that the test can happen at compilation time."
-  (if (< emacs-major-version 22)
-      `(append '(intangible t) ,props)
-    props))
-
 (defmacro org-with-point-at (pom &rest body)
   "Move to buffer and point of point-or-marker POM for the duration of BODY."
   (declare (debug (form body)) (indent 1))
@@ -160,10 +96,6 @@ We use a macro so that the test can happen at compilation 
time."
          (goto-char (or ,mpom (point)))
          ,@body)))))
 
-(defmacro org-no-warnings (&rest body)
-  (declare (debug (body)))
-  (cons (if (fboundp 'with-no-warnings) 'with-no-warnings 'progn) body))
-
 (defmacro org-with-remote-undo (buffer &rest body)
   "Execute BODY while recording undo information in two buffers."
   (declare (debug (form body)) (indent 1))
@@ -199,22 +131,12 @@ We use a macro so that the test can happen at compilation 
time."
                                   org-emphasis t)
   "Properties to remove when a string without properties is wanted.")
 
-(defsubst org-match-string-no-properties (num &optional string)
-  (if (featurep 'xemacs)
-      (let ((s (match-string num string)))
-       (and s (remove-text-properties 0 (length s) org-rm-props s))
-       s)
-    (match-string-no-properties num string)))
-
 (defsubst org-no-properties (s &optional restricted)
   "Remove all text properties from string S.
 When RESTRICTED is non-nil, only remove the properties listed
 in `org-rm-props'."
-  (if (fboundp 'set-text-properties)
-      (set-text-properties 0 (length s) nil s)
-    (if restricted
-       (remove-text-properties 0 (length s) org-rm-props s)
-      (set-text-properties 0 (length s) nil s)))
+  (if restricted (remove-text-properties 0 (length s) org-rm-props s)
+    (set-text-properties 0 (length s) nil s))
   s)
 
 (defsubst org-get-alist-option (option key)
@@ -236,16 +158,6 @@ program is needed for, so that the error message can be 
more informative."
        (error "Can't find `%s'%s" cmd
               (if use (format " (%s)" use) "")))))
 
-(defsubst org-inhibit-invisibility ()
-  "Modified `buffer-invisibility-spec' for Emacs 21.
-Some ops with invisible text do not work correctly on Emacs 21.  For these
-we turn off invisibility temporarily.  Use this in a `let' form."
-  (if (< emacs-major-version 22) nil buffer-invisibility-spec))
-
-(defsubst org-set-local (var value)
-  "Make VAR local in current buffer and set it to VALUE."
-  (set (make-local-variable var) value))
-
 (defsubst org-last (list)
   "Return the last element of LIST."
   (car (last list)))
@@ -282,11 +194,11 @@ we turn off invisibility temporarily.  Use this in a 
`let' form."
        (<= (match-beginning n) pos)
        (>= (match-end n) pos)))
 
-(defun org-match-line (re)
-  "Looking-at at the beginning of the current line."
+(defun org-match-line (regexp)
+  "Match REGEXP at the beginning of the current line."
   (save-excursion
-    (goto-char (point-at-bol))
-    (looking-at re)))
+    (beginning-of-line)
+    (looking-at regexp)))
 
 (defun org-plist-delete (plist property)
   "Delete PROPERTY from PLIST.
@@ -298,13 +210,6 @@ This is in contrast to merely setting it to 0."
       (setq plist (cddr plist)))
     p))
 
-(defun org-replace-match-keep-properties (newtext &optional fixedcase
-                                                 literal string)
-  "Like `replace-match', but add the text properties found original text."
-  (setq newtext (org-add-props newtext (text-properties-at
-                                       (match-beginning 0) string)))
-  (replace-match newtext fixedcase literal string))
-
 (defmacro org-save-outline-visibility (use-markers &rest body)
   "Save and restore outline visibility around BODY.
 If USE-MARKERS is non-nil, use markers for the positions.
@@ -313,19 +218,15 @@ but it also means that the buffer should stay alive
 during the operation, because otherwise all these markers will
 point nowhere."
   (declare (debug (form body)) (indent 1))
-  (org-with-gensyms (data rtn)
-    `(let ((,data (org-outline-overlay-data ,use-markers))
-          ,rtn)
+  (org-with-gensyms (data)
+    `(let ((,data (org-outline-overlay-data ,use-markers)))
        (unwind-protect
-          (progn
-            (setq ,rtn (progn ,@body))
+          (prog1 (progn ,@body)
             (org-set-outline-overlay-data ,data))
         (when ,use-markers
-          (mapc (lambda (c)
-                  (and (markerp (car c)) (move-marker (car c) nil))
-                  (and (markerp (cdr c)) (move-marker (cdr c) nil)))
-                ,data)))
-       ,rtn)))
+          (dolist (c ,data)
+            (when (markerp (car c)) (move-marker (car c) nil))
+            (when (markerp (cdr c)) (move-marker (cdr c) nil))))))))
 
 (defmacro org-with-wide-buffer (&rest body)
   "Execute body while temporarily widening the buffer."
@@ -355,17 +256,16 @@ point nowhere."
 (defun org-get-limited-outline-regexp ()
   "Return outline-regexp with limited number of levels.
 The number of levels is controlled by `org-inlinetask-min-level'"
-  (if (or (not (derived-mode-p 'org-mode)) (not (featurep 'org-inlinetask)))
-      org-outline-regexp
-    (let* ((limit-level (1- org-inlinetask-min-level))
-          (nstars (if org-odd-levels-only (1- (* limit-level 2)) limit-level)))
-      (format "\\*\\{1,%d\\} " nstars))))
-
-(defun org-format-seconds (string seconds)
-  "Compatibility function replacing format-seconds."
-  (if (fboundp 'format-seconds)
-      (format-seconds string seconds)
-    (format-time-string string (seconds-to-time seconds))))
+  (cond ((not (derived-mode-p 'org-mode))
+        outline-regexp)
+       ((not (featurep 'org-inlinetask))
+        org-outline-regexp)
+       (t
+        (let* ((limit-level (1- org-inlinetask-min-level))
+               (nstars (if org-odd-levels-only
+                           (1- (* limit-level 2))
+                         limit-level)))
+          (format "\\*\\{1,%d\\} " nstars)))))
 
 (defmacro org-eval-in-environment (environment form)
   (declare (debug (form form)) (indent 1))
@@ -382,10 +282,27 @@ the value in cdr."
 
 ;;;###autoload
 (defmacro org-load-noerror-mustsuffix (file)
-  "Load FILE with optional arguments NOERROR and MUSTSUFFIX.  Drop the 
MUSTSUFFIX argument for XEmacs, which doesn't recognize it."
-  (if (featurep 'xemacs)
-      `(load ,file 'noerror)
-    `(load ,file 'noerror nil nil 'mustsuffix)))
+  "Load FILE with optional arguments NOERROR and MUSTSUFFIX."
+  `(load ,file 'noerror nil nil 'mustsuffix))
+
+(defun org-unbracket-string (pre post string)
+  "Remove PRE/POST from the beginning/end of STRING.
+Both PRE and POST must be pre-/suffixes of STRING, or neither is
+removed."
+  (if (and (string-prefix-p pre string)
+          (string-suffix-p post string))
+      (substring string (length pre) (- (length post)))
+    string))
+
+(defun org-read-function (prompt &optional allow-empty?)
+  "Prompt for a function.
+If ALLOW-EMPTY? is non-nil, return nil rather than raising an
+error when the user input is empty."
+  (let ((func (completing-read prompt obarray #'fboundp t)))
+    (cond ((not (string= func ""))
+          (intern func))
+         (allow-empty? nil)
+         (t (user-error "Empty input is not valid")))))
 
 (provide 'org-macs)
 
diff --git a/lisp/org/org-mhe.el b/lisp/org/org-mhe.el
index d1067cd..4142ae4 100644
--- a/lisp/org/org-mhe.el
+++ b/lisp/org/org-mhe.el
@@ -1,4 +1,4 @@
-;;; org-mhe.el --- Support for links to MH-E messages from within Org-mode
+;;; org-mhe.el --- Support for Links to MH-E Messages -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,8 +24,8 @@
 ;;
 ;;; Commentary:
 
-;; This file implements links to MH-E messages from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
+;; This file implements links to MH-E messages from within Org.
+;; Org mode loads this module by default - if this is not what you want,
 ;; configure the variable `org-modules'.
 
 ;;; Code:
@@ -74,34 +74,25 @@ supported by MH-E."
 (defvar mh-search-regexp-builder)
 
 ;; Install the link type
-(org-add-link-type "mhe" 'org-mhe-open)
-(add-hook 'org-store-link-functions 'org-mhe-store-link)
+(org-link-set-parameters "mhe" :follow #'org-mhe-open :store 
#'org-mhe-store-link)
 
 ;; Implementation
 (defun org-mhe-store-link ()
   "Store a link to an MH-E folder or message."
-  (when (or (equal major-mode 'mh-folder-mode)
-           (equal major-mode 'mh-show-mode))
+  (when (or (eq major-mode 'mh-folder-mode)
+           (eq major-mode 'mh-show-mode))
     (save-window-excursion
       (let* ((from (org-mhe-get-header "From:"))
             (to (org-mhe-get-header "To:"))
             (message-id (org-mhe-get-header "Message-Id:"))
             (subject (org-mhe-get-header "Subject:"))
             (date (org-mhe-get-header "Date:"))
-            (date-ts (and date (format-time-string
-                                (org-time-stamp-format t) (date-to-time 
date))))
-            (date-ts-ia (and date (format-time-string
-                                   (org-time-stamp-format t t)
-                                   (date-to-time date))))
             link desc)
-       (org-store-link-props :type "mh" :from from :to to
+       (org-store-link-props :type "mh" :from from :to to :date date
                              :subject subject :message-id message-id)
-       (when date
-         (org-add-link-props :date date :date-timestamp date-ts
-                             :date-timestamp-inactive date-ts-ia))
        (setq desc (org-email-link-description))
        (setq link (concat "mhe:" (org-mhe-get-message-real-folder) "#"
-                          (org-remove-angle-brackets message-id)))
+                          (org-unbracket-string "<" ">" message-id)))
        (org-add-link-props :link link :description desc)
        link))))
 
@@ -120,7 +111,7 @@ supported by MH-E."
 So if you use sequences, it will now work."
   (save-excursion
     (let* ((folder
-           (if (equal major-mode 'mh-folder-mode)
+           (if (eq major-mode 'mh-folder-mode)
                mh-current-folder
              ;; Refer to the show buffer
              mh-show-folder-buffer))
@@ -132,7 +123,7 @@ So if you use sequences, it will now work."
       ;; mh-index-data is always nil in a show buffer.
       (if (and (boundp 'mh-index-folder)
               (string= mh-index-folder (substring folder 0 end-index)))
-         (if (equal major-mode 'mh-show-mode)
+         (if (eq major-mode 'mh-show-mode)
              (save-window-excursion
                (let (pop-up-frames)
                  (when (buffer-live-p (get-buffer folder))
@@ -158,7 +149,7 @@ So if you use sequences, it will now work."
   "Return the name of the current message folder.
 Be careful if you use sequences."
   (save-excursion
-    (if (equal major-mode 'mh-folder-mode)
+    (if (eq major-mode 'mh-folder-mode)
        mh-current-folder
       ;; Refer to the show buffer
       mh-show-folder-buffer)))
@@ -167,7 +158,7 @@ Be careful if you use sequences."
   "Return the number of the current message.
 Be careful if you use sequences."
   (save-excursion
-    (if (equal major-mode 'mh-folder-mode)
+    (if (eq major-mode 'mh-folder-mode)
        (mh-get-msg-num nil)
       ;; Refer to the show buffer
       (mh-show-buffer-message-number))))
@@ -182,12 +173,12 @@ you have a better idea of how to do this then please let 
us know."
         (header-field))
     (with-current-buffer buffer
       (mh-display-msg num folder)
-      (if (equal major-mode 'mh-folder-mode)
+      (if (eq major-mode 'mh-folder-mode)
          (mh-header-display)
        (mh-show-header-display))
       (set-buffer buffer)
       (setq header-field (mh-get-header-field header))
-      (if (equal major-mode 'mh-folder-mode)
+      (if (eq major-mode 'mh-folder-mode)
          (mh-show)
        (mh-show-show))
       (org-trim header-field))))
@@ -206,13 +197,13 @@ folders."
   (if (not article)
       (mh-visit-folder (mh-normalize-folder-name folder))
     (mh-search-choose)
-    (if (equal mh-searcher 'pick)
+    (if (eq mh-searcher 'pick)
        (progn
          (setq article (org-add-angle-brackets article))
          (mh-search folder (list "--message-id" article))
          (when (and org-mhe-search-all-folders
                     (not (org-mhe-get-message-real-folder)))
-           (kill-current-buffer)
+           (kill-buffer)
            (mh-search "+" (list "--message-id" article))))
       (if mh-search-regexp-builder
          (mh-search "+" (funcall mh-search-regexp-builder
@@ -220,7 +211,7 @@ folders."
        (mh-search "+" article)))
     (if (org-mhe-get-message-real-folder)
        (mh-show-msg 1)
-      (kill-current-buffer)
+      (kill-buffer)
       (error "Message not found"))))
 
 (provide 'org-mhe)
diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el
index 34e6af1..12e6c84 100644
--- a/lisp/org/org-mobile.el
+++ b/lisp/org/org-mobile.el
@@ -1,4 +1,4 @@
-;;; org-mobile.el --- Code for asymmetric sync with a mobile device
+;;; org-mobile.el --- Code for Asymmetric Sync With a Mobile Device -*- 
lexical-binding: t; -*-
 ;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
@@ -24,21 +24,20 @@
 ;;
 ;;; Commentary:
 ;;
-;; This file contains the code to interact with Richard Moreland's iPhone
-;; application MobileOrg, as well as with the Android version by Matthew Jones.
-;; This code is documented in Appendix B of the Org-mode manual.  The code is
-;; not specific for the iPhone and Android - any external
-;; viewer/flagging/editing application that uses the same conventions could
-;; be used.
+;; This file contains the code to interact with Richard Moreland's
+;; iPhone application MobileOrg, as well as with the Android version
+;; by Matthew Jones.  This code is documented in Appendix B of the Org
+;; manual.  The code is not specific for the iPhone and Android - any
+;; external viewer/flagging/editing application that uses the same
+;; conventions could be used.
 
 (require 'org)
 (require 'org-agenda)
-;;; Code:
+(require 'cl-lib)
 
-(eval-when-compile (require 'cl))
+(defvar org-agenda-keep-restricted-file-list)
 
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
+;;; Code:
 
 (defgroup org-mobile nil
   "Options concerning support for a viewer/editor on a mobile device."
@@ -192,27 +191,6 @@ the editing types for which the mobile version should 
always dominate."
               (const heading)
               (const body))))
 
-(defcustom org-mobile-action-alist
-  '(("edit" . (org-mobile-edit data old new)))
-  "Alist with flags and actions for mobile sync.
-When flagging an entry, MobileOrg will create entries that look like
-
-  * F(action:data)  [[id:entry-id][entry title]]
-
-This alist defines that the ACTION in the parentheses of F() should mean,
-i.e. what action should be taken.  The :data part in the parenthesis is
-optional.  If present, the string after the colon will be passed to the
-action form as the `data' variable.
-The car of each elements of the alist is an actions string.  The cdr is
-an Emacs Lisp form that will be evaluated with the cursor on the headline
-of that entry.
-
-For now, it is not recommended to change this variable."
-  :group 'org-mobile
-  :type '(repeat
-         (cons (string :tag "Action flag")
-               (sexp   :tag "Action form"))))
-
 (defcustom org-mobile-checksum-binary (or (executable-find "shasum")
                                          (executable-find "sha1sum")
                                          (executable-find "md5sum")
@@ -249,6 +227,23 @@ by the mobile device, this hook should be used to copy the 
emptied
 capture file `mobileorg.org' back to the WebDAV directory, for example
 using `rsync' or `scp'.")
 
+(defconst org-mobile-action-alist '(("edit" . org-mobile-edit))
+  "Alist with flags and actions for mobile sync.
+When flagging an entry, MobileOrg will create entries that look like
+
+  * F(action:data)  [[id:entry-id][entry title]]
+
+This alist defines that the ACTION in the parentheses of F()
+should mean, i.e. what action should be taken.  The :data part in
+the parenthesis is optional.  If present, the string after the
+colon will be passed to the action function as the first argument
+variable.
+
+The car of each elements of the alist is an actions string.  The
+cdr is a function that is called with the cursor on the headline
+of that entry.  It should accept three arguments, the :data part,
+the old and new values for the entry.")
+
 (defvar org-mobile-last-flagged-files nil
   "List of files containing entries flagged in the latest pull.")
 
@@ -313,40 +308,29 @@ Also exclude files matching 
`org-mobile-files-exclude-regexp'."
 This will create the index file, copy all agenda files there, and also
 create all custom agenda views, for upload to the mobile phone."
   (interactive)
-  (let ((a-buffer (get-buffer org-agenda-buffer-name)))
-    (let ((org-agenda-curbuf-name org-agenda-buffer-name)
-         (org-agenda-buffer-name "*SUMO*")
-         (org-agenda-tag-filter org-agenda-tag-filter)
-         (org-agenda-redo-command org-agenda-redo-command))
-      (save-excursion
-       (save-restriction
-         (save-window-excursion
-           (run-hooks 'org-mobile-pre-push-hook)
-           (org-mobile-check-setup)
-           (org-mobile-prepare-file-lists)
-           (message "Creating agendas...")
-           (let ((inhibit-redisplay t)
-                 (org-agenda-files (mapcar 'car org-mobile-files-alist)))
-             (org-mobile-create-sumo-agenda))
-           (message "Creating agendas...done")
-           (org-save-all-org-buffers) ; to save any IDs created by this process
-           (message "Copying files...")
-           (org-mobile-copy-agenda-files)
-           (message "Writing index file...")
-           (org-mobile-create-index-file)
-           (message "Writing checksums...")
-           (org-mobile-write-checksums)
-           (run-hooks 'org-mobile-post-push-hook))))
-      (setq org-agenda-buffer-name org-agenda-curbuf-name
-           org-agenda-this-buffer-name org-agenda-curbuf-name))
-    (redraw-display)
-    (when (buffer-live-p a-buffer)
-      (if (not (get-buffer-window a-buffer))
-         (kill-buffer a-buffer)
-       (let ((cw (selected-window)))
-         (select-window (get-buffer-window a-buffer))
-         (org-agenda-redo)
-         (select-window cw)))))
+  (let ((org-agenda-buffer-name "*SUMO*")
+       (org-agenda-tag-filter org-agenda-tag-filter)
+       (org-agenda-redo-command org-agenda-redo-command))
+    (save-excursion
+      (save-restriction
+       (save-window-excursion
+         (run-hooks 'org-mobile-pre-push-hook)
+         (org-mobile-check-setup)
+         (org-mobile-prepare-file-lists)
+         (message "Creating agendas...")
+         (let ((inhibit-redisplay t)
+               (org-agenda-files (mapcar 'car org-mobile-files-alist)))
+           (org-mobile-create-sumo-agenda))
+         (message "Creating agendas...done")
+         (org-save-all-org-buffers) ; to save any IDs created by this process
+         (message "Copying files...")
+         (org-mobile-copy-agenda-files)
+         (message "Writing index file...")
+         (org-mobile-create-index-file)
+         (message "Writing checksums...")
+         (org-mobile-write-checksums)
+         (run-hooks 'org-mobile-post-push-hook)))))
+  (org-agenda-maybe-redo)
   (message "Files for mobile viewer staged"))
 
 (defvar org-mobile-before-process-capture-hook nil
@@ -422,10 +406,10 @@ agenda view showing the flagged items."
   (let ((files-alist (sort (copy-sequence org-mobile-files-alist)
                           (lambda (a b) (string< (cdr a) (cdr b)))))
        (def-todo (default-value 'org-todo-keywords))
-       (def-tags (default-value 'org-tag-alist))
+       (def-tags org-tag-alist)
        (target-file (expand-file-name org-mobile-index-file
                                       org-mobile-directory))
-       file link-name todo-kwds done-kwds tags drawers entry kwds dwds twds)
+       todo-kwds done-kwds tags)
     (when (stringp (car def-todo))
       (setq def-todo (list (cons 'sequence def-todo))))
     (org-agenda-prepare-buffers (mapcar 'car files-alist))
@@ -433,52 +417,36 @@ agenda view showing the flagged items."
     (setq todo-kwds (org-delete-all
                     done-kwds
                     (org-uniquify org-todo-keywords-for-agenda)))
-    (setq drawers (org-uniquify org-drawers-for-agenda))
     (setq tags (mapcar 'car (org-global-tags-completion-table
                             (mapcar 'car files-alist))))
-    (with-temp-file
-       (if org-mobile-use-encryption
-           org-mobile-encryption-tempfile
-         target-file)
-      (while (setq entry (pop def-todo))
-       (insert "#+READONLY\n")
-       (setq kwds (mapcar (lambda (x) (if (string-match "(" x)
-                                          (substring x 0 (match-beginning 0))
-                                        x))
-                          (cdr entry)))
-       (insert "#+TODO: " (mapconcat 'identity kwds " ") "\n")
-       (setq dwds (member "|" kwds)
-             twds (org-delete-all dwds kwds)
-             todo-kwds (org-delete-all twds todo-kwds)
-             done-kwds (org-delete-all dwds done-kwds)))
+    (with-temp-file (if org-mobile-use-encryption 
org-mobile-encryption-tempfile
+                     target-file)
+      (insert "#+READONLY\n")
+      (dolist (entry def-todo)
+       (let ((kwds (mapcar (lambda (x)
+                             (if (string-match "(" x)
+                                 (substring x 0 (match-beginning 0))
+                               x))
+                           (cdr entry))))
+         (insert "#+TODO: " (mapconcat #'identity kwds " ") "\n")
+         (let* ((dwds (or (member "|" kwds) (last kwds)))
+                (twds (org-delete-all dwds kwds)))
+           (setq todo-kwds (org-delete-all twds todo-kwds))
+           (setq done-kwds (org-delete-all dwds done-kwds)))))
       (when (or todo-kwds done-kwds)
        (insert "#+TODO: " (mapconcat 'identity todo-kwds " ") " | "
                (mapconcat 'identity done-kwds " ") "\n"))
-      (setq def-tags (mapcar
-                     (lambda (x)
-                       (cond ((null x) nil)
-                             ((stringp x) x)
-                             ((eq (car x) :startgroup) "{")
-                             ((eq (car x) :endgroup) "}")
-                             ((eq (car x) :grouptags) nil)
-                             ((eq (car x) :newline) nil)
-                             ((listp x) (car x))))
-                     def-tags))
-      (setq def-tags (delq nil def-tags))
+      (setq def-tags (split-string (org-tag-alist-to-string def-tags t)))
       (setq tags (org-delete-all def-tags tags))
       (setq tags (sort tags (lambda (a b) (string< (downcase a) (downcase 
b)))))
       (setq tags (append def-tags tags nil))
       (insert "#+TAGS: " (mapconcat 'identity tags " ") "\n")
-      (insert "#+DRAWERS: " (mapconcat 'identity drawers " ") "\n")
       (insert "#+ALLPRIORITIES: " org-mobile-allpriorities "\n")
       (when (file-exists-p (expand-file-name
                            org-mobile-directory "agendas.org"))
        (insert "* [[file:agendas.org][Agenda Views]]\n"))
-      (while (setq entry (pop files-alist))
-       (setq file (car entry)
-             link-name (cdr entry))
-       (insert (format "* [[file:%s][%s]]\n"
-                       link-name link-name)))
+      (pcase-dolist (`(,_ . ,link-name) files-alist)
+       (insert (format "* [[file:%s][%s]]\n" link-name link-name)))
       (push (cons org-mobile-index-file (md5 (buffer-string)))
            org-mobile-checksum-files))
     (when org-mobile-use-encryption
@@ -501,7 +469,8 @@ agenda view showing the flagged items."
            (org-mobile-encrypt-and-move file target-path)
          (copy-file file target-path 'ok-if-exists))
        (setq check (shell-command-to-string
-                    (concat org-mobile-checksum-binary " "
+                    (concat (shell-quote-argument org-mobile-checksum-binary)
+                            " "
                             (shell-quote-argument (expand-file-name file)))))
        (when (string-match "[a-fA-F0-9]\\{30,40\\}" check)
          (push (cons link-name (match-string 0 check))
@@ -663,7 +632,7 @@ The table of checksums is written to the file 
mobile-checksums."
                     m 10 "   " 'planning)
                    "\n")
            (when (setq id
-                       (if (org-bound-and-true-p
+                       (if (bound-and-true-p
                             org-mobile-force-id-on-agenda-items)
                            (org-id-get m 'create)
                          (or (org-entry-get m "ID")
@@ -679,7 +648,7 @@ The table of checksums is written to the file 
mobile-checksums."
   (org-with-point-at pom
     (concat "olp:"
            (org-mobile-escape-olp (file-name-nondirectory buffer-file-name))
-           "/"
+           ":"
            (mapconcat 'org-mobile-escape-olp
                       (org-get-outline-path)
                       "/")
@@ -823,14 +792,14 @@ If BEG and END are given, only do this in that region."
        (cnt-flag 0)
        (cnt-error 0)
        buf-list
-       id-pos org-mobile-error)
+       org-mobile-error)
 
     ;; Count the new captures
     (goto-char beg)
     (while (re-search-forward "^\\* \\(.*\\)" end t)
       (and (>= (- (match-end 1) (match-beginning 1)) 2)
           (not (equal (downcase (substring (match-string 1) 0 2)) "f("))
-          (incf cnt-new)))
+          (cl-incf cnt-new)))
 
     ;; Find and apply the edits
     (goto-char beg)
@@ -842,19 +811,21 @@ If BEG and END are given, only do this in that region."
               (id-pos (condition-case msg
                           (org-mobile-locate-entry (match-string 4))
                         (error (nth 1 msg))))
-              (bos (point-at-bol))
+              (bos (line-beginning-position))
               (eos (save-excursion (org-end-of-subtree t t)))
               (cmd (if (equal action "")
-                       '(progn
-                          (incf cnt-flag)
-                          (org-toggle-tag "FLAGGED" 'on)
-                          (and note
-                               (org-entry-put nil "THEFLAGGINGNOTE" note)))
-                     (incf cnt-edit)
+                       (let ((note (buffer-substring-no-properties
+                                    (line-beginning-position 2) eos)))
+                         (lambda (_data _old _new)
+                           (cl-incf cnt-flag)
+                           (org-toggle-tag "FLAGGED" 'on)
+                           (org-entry-put
+                            nil "THEFLAGGINGNOTE"
+                            (replace-regexp-in-string "\n" "\\\\n" note))))
+                     (cl-incf cnt-edit)
                      (cdr (assoc action org-mobile-action-alist))))
-              (note (and (equal action "")
-                         (buffer-substring (1+ (point-at-eol)) eos)))
-              (org-inhibit-logging 'note) ;; Do not take notes interactively
+              ;; Do not take notes interactively.
+              (org-inhibit-logging 'note)
               old new)
 
          (goto-char bos)
@@ -867,11 +838,11 @@ If BEG and END are given, only do this in that region."
            (if (stringp id-pos)
                (insert id-pos " ")
              (insert "BAD REFERENCE "))
-           (incf cnt-error)
+           (cl-incf cnt-error)
            (throw 'next t))
          (unless cmd
            (insert "BAD FLAG ")
-           (incf cnt-error)
+           (cl-incf cnt-error)
            (throw 'next t))
          (move-marker bos-marker (point))
          (if (re-search-forward "^** Old value[ \t]*$" eos t)
@@ -884,34 +855,28 @@ If BEG and END are given, only do this in that region."
                         (progn (outline-next-heading)
                                (if (eobp) (org-back-over-empty-lines))
                                (point)))))
-         (setq old (and old (if (string-match "\\S-" old) old nil)))
-         (setq new (and new (if (string-match "\\S-" new) new nil)))
-         (if (and note (> (length note) 0))
-             ;; Make Note into a single line, to fit into a property
-             (setq note (mapconcat 'identity
-                                   (org-split-string (org-trim note) "\n")
-                                   "\\n")))
+         (setq old (org-string-nw-p old))
+         (setq new (org-string-nw-p new))
          (unless (equal data "body")
-           (setq new (and new (org-trim new))
-                 old (and old (org-trim old))))
+           (setq new (and new (org-trim new)))
+           (setq old (and old (org-trim old))))
          (goto-char (+ 2 bos-marker))
          ;; Remember this place so that we can return
          (move-marker marker (point))
          (setq org-mobile-error nil)
-         (save-excursion
-           (condition-case msg
-               (org-with-point-at id-pos
-                 (progn
-                   (eval cmd)
-                   (unless (member data (list "delete" "archive" 
"archive-sibling" "addheading"))
-                     (if (member "FLAGGED" (org-get-tags))
-                         (add-to-list 'org-mobile-last-flagged-files
-                                      (buffer-file-name (current-buffer)))))))
-             (error (setq org-mobile-error msg))))
+         (condition-case msg
+             (org-with-point-at id-pos
+               (funcall cmd data old new)
+               (unless (member data '("delete" "archive" "archive-sibling"
+                                      "addheading"))
+                 (when (member "FLAGGED" (org-get-tags))
+                   (add-to-list 'org-mobile-last-flagged-files
+                                (buffer-file-name)))))
+           (error (setq org-mobile-error msg)))
          (when org-mobile-error
-           (org-pop-to-buffer-same-window (marker-buffer marker))
+           (pop-to-buffer-same-window (marker-buffer marker))
            (goto-char marker)
-           (incf cnt-error)
+           (cl-incf cnt-error)
            (insert (if (stringp (nth 1 org-mobile-error))
                        (nth 1 org-mobile-error)
                      "EXECUTION FAILED")
@@ -924,8 +889,8 @@ If BEG and END are given, only do this in that region."
     (save-buffer)
     (move-marker marker nil)
     (move-marker end nil)
-    (message "%d new, %d edits, %d flags, %d errors" cnt-new
-            cnt-edit cnt-flag cnt-error)
+    (message "%d new, %d edits, %d flags, %d errors"
+            cnt-new cnt-edit cnt-flag cnt-error)
     (sit-for 1)))
 
 (defun org-mobile-timestamp-buffer (buf)
@@ -1020,7 +985,7 @@ be returned that indicates what went wrong."
        ((equal new "DONEARCHIVE")
        (org-todo 'done)
        (org-archive-subtree-default))
-       ((equal new current) t) ; nothing needs to be done
+       ((equal new current) t)         ; nothing needs to be done
        ((or (equal current old)
            (eq org-mobile-force-mobile-change t)
            (memq 'todo org-mobile-force-mobile-change))
@@ -1042,33 +1007,35 @@ be returned that indicates what went wrong."
                 (or old "") (or current "")))))
 
      ((eq what 'priority)
-      (when (looking-at org-complex-heading-regexp)
-       (setq current (and (match-end 3) (substring (match-string 3) 2 3)))
-       (cond
-        ((equal current new) t) ; no action required
-        ((or (equal current old)
-             (eq org-mobile-force-mobile-change t)
-             (memq 'tags org-mobile-force-mobile-change))
-         (org-priority (and new (string-to-char new))))
-        (t (error "Priority was expected to be %s, but is %s"
-                  old current)))))
+      (let ((case-fold-search nil))
+       (when (looking-at org-complex-heading-regexp)
+         (let ((current (and (match-end 3) (substring (match-string 3) 2 3))))
+           (cond
+            ((equal current new) t)    ;no action required
+            ((or (equal current old)
+                 (eq org-mobile-force-mobile-change t)
+                 (memq 'tags org-mobile-force-mobile-change))
+             (org-priority (and new (string-to-char new))))
+            (t (error "Priority was expected to be %s, but is %s"
+                      old current)))))))
 
      ((eq what 'heading)
-      (when (looking-at org-complex-heading-regexp)
-       (setq current (match-string 4))
-       (cond
-        ((equal current new) t) ; no action required
-        ((or (equal current old)
-             (eq org-mobile-force-mobile-change t)
-             (memq 'heading org-mobile-force-mobile-change))
-         (goto-char (match-beginning 4))
-         (insert new)
-         (delete-region (point) (+ (point) (length current)))
-         (org-set-tags nil 'align))
-        (t (error "Heading changed in MobileOrg and on the computer")))))
+      (let ((case-fold-search nil))
+       (when (looking-at org-complex-heading-regexp)
+         (let ((current (match-string 4)))
+           (cond
+            ((equal current new) t)    ;no action required
+            ((or (equal current old)
+                 (eq org-mobile-force-mobile-change t)
+                 (memq 'heading org-mobile-force-mobile-change))
+             (goto-char (match-beginning 4))
+             (insert new)
+             (delete-region (point) (+ (point) (length current)))
+             (org-set-tags nil 'align))
+            (t (error "Heading changed in MobileOrg and on the computer")))))))
 
      ((eq what 'addheading)
-      (if (org-at-heading-p) ; if false we are in top-level of file
+      (if (org-at-heading-p)   ; if false we are in top-level of file
          (progn
            ;; Workaround a `org-insert-heading-respect-content' bug
            ;; which prevents correct insertion when point is invisible
@@ -1083,7 +1050,7 @@ be returned that indicates what went wrong."
      ((eq what 'refile)
       (org-copy-subtree)
       (org-with-point-at (org-mobile-locate-entry new)
-       (if (org-at-heading-p) ; if false we are in top-level of file
+       (if (org-at-heading-p)  ; if false we are in top-level of file
            (progn
              (setq level (org-get-valid-level (funcall outline-level) 1))
              (org-end-of-subtree t t)
diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el
index 7eef5c6..d6a4727 100644
--- a/lisp/org/org-mouse.el
+++ b/lisp/org/org-mouse.el
@@ -1,4 +1,4 @@
-;;; org-mouse.el --- Better mouse support for org-mode
+;;; org-mouse.el --- Better mouse support for Org -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2017 Free Software Foundation, Inc.
 
@@ -26,8 +26,8 @@
 ;;
 ;; http://orgmode.org
 ;;
-;; Org-mouse implements the following features:
-;; * following links with the left mouse button (in Emacs 22)
+;; Org mouse implements the following features:
+;; * following links with the left mouse button
 ;; * subtree expansion/collapse (org-cycle) with the left mouse button
 ;; * several context menus on the right mouse button:
 ;;    + general text
@@ -66,12 +66,12 @@
 
 ;; History:
 ;;
-;; Since version 5.10: Changes are listed in the general org-mode docs.
+;; Since version 5.10: Changes are listed in the general Org docs.
 ;;
-;; Version 5.09;; + Version number synchronization with Org-mode.
+;; Version 5.09;; + Version number synchronization with Org mode.
 ;;
 ;; Version 0.25
-;; + made compatible with org-mode 4.70 (thanks to Carsten for the patch)
+;; + made compatible with Org 4.70 (thanks to Carsten for the patch)
 ;;
 ;; Version 0.24
 ;; + minor changes to the table menu
@@ -81,7 +81,7 @@
 ;; + context menu support for org-agenda-undo & org-sort-entries
 ;;
 ;; Version 0.22
-;; + handles undo support for the agenda buffer (requires org-mode >=4.58)
+;; + handles undo support for the agenda buffer (requires Org >=4.58)
 ;;
 ;; Version 0.21
 ;; + selected text activates its context menu
@@ -105,7 +105,7 @@
 ;; + added support for checkboxes
 ;;
 ;; Version 0.15
-;; + org-mode now works with the Agenda buffer as well
+;; + Org now works with the Agenda buffer as well
 ;;
 ;; Version 0.14
 ;; + added a menu option that converts plain list items to outline items
@@ -125,7 +125,7 @@
 ;;
 ;; Version 0.10
 ;; + added a menu option to remove highlights
-;; + compatible with org-mode 4.21 now
+;; + compatible with Org 4.21 now
 ;;
 ;; Version 0.08:
 ;; + trees can be moved/promoted/demoted by dragging with the right
@@ -136,8 +136,8 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
 (require 'org)
+(require 'cl-lib)
 
 (defvar org-agenda-allow-remote-undo)
 (defvar org-agenda-undo-list)
@@ -149,6 +149,8 @@
 (declare-function org-agenda-earlier "org-agenda" (arg))
 (declare-function org-agenda-later "org-agenda" (arg))
 
+(defvar org-mouse-main-buffer nil
+  "Active buffer for mouse operations.")
 (defvar org-mouse-plain-list-regexp "\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) "
   "Regular expression that matches a plain list.")
 (defvar org-mouse-direct t
@@ -191,15 +193,14 @@ Changing this variable requires a restart of Emacs to get 
activated."
   (interactive)
   (end-of-line)
   (skip-chars-backward "\t ")
-  (when (org-looking-back ":[A-Za-z]+:" (line-beginning-position))
+  (when (looking-back ":[A-Za-z]+:" (line-beginning-position))
     (skip-chars-backward ":A-Za-z")
     (skip-chars-backward "\t ")))
 
-(defvar org-mouse-context-menu-function nil
+(defvar-local org-mouse-context-menu-function nil
   "Function to create the context menu.
 The value of this variable is the function invoked by
 `org-mouse-context-menu' as the context menu.")
-(make-variable-buffer-local 'org-mouse-context-menu-function)
 
 (defun org-mouse-show-context-menu (event prefix)
   "Invoke the context menu.
@@ -215,13 +216,12 @@ this function is called.  Otherwise, the current major 
mode menu is used."
        (when (not (org-mouse-mark-active))
          (goto-char (posn-point (event-start event)))
          (when (not (eolp)) (save-excursion (run-hooks 'post-command-hook)))
-         (let ((redisplay-dont-pause t))
-           (sit-for 0)))
+         (sit-for 0))
        (if (functionp org-mouse-context-menu-function)
            (funcall org-mouse-context-menu-function event)
          (if (fboundp 'mouse-menu-major-mode-map)
              (popup-menu (mouse-menu-major-mode-map) event prefix)
-           (org-no-warnings ; don't warn about fallback, obsolete since 23.1
+           (with-no-warnings ; don't warn about fallback, obsolete since 23.1
             (mouse-major-mode-menu event prefix)))))
     (setq this-command 'mouse-save-then-kill)
     (mouse-save-then-kill event)))
@@ -258,7 +258,7 @@ If the point is at the :beginning 
(`org-mouse-line-position') of the line,
 insert the new heading before the current line.  Otherwise, insert it
 after the current heading."
   (interactive)
-  (case (org-mouse-line-position)
+  (cl-case (org-mouse-line-position)
     (:beginning (beginning-of-line)
                (org-insert-heading))
     (t (org-mouse-next-heading)
@@ -314,10 +314,10 @@ nor a function, elements of KEYWORDS are used directly."
   (just-one-space))
 
 (defvar org-mouse-rest)
-(defun org-mouse-replace-match-and-surround (newtext &optional fixedcase
-                                                    literal string subexp)
+(defun org-mouse-replace-match-and-surround
+    (_newtext &optional _fixedcase _literal _string subexp)
   "The same as `replace-match', but surrounds the replacement with spaces."
-  (apply 'replace-match org-mouse-rest)
+  (apply #'replace-match org-mouse-rest)
   (save-excursion
     (goto-char (match-beginning (or subexp 0)))
     (just-one-space)
@@ -407,8 +407,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
          (> (match-end 0) point))))))
 
 (defun org-mouse-priority-list ()
-  (loop for priority from ?A to org-lowest-priority
-       collect (char-to-string priority)))
+  (cl-loop for priority from ?A to org-lowest-priority
+          collect (char-to-string priority)))
 
 (defun org-mouse-todo-menu (state)
   "Create the menu with TODO keywords."
@@ -460,33 +460,33 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
         (insert " [ ] "))))
 
 (defun org-mouse-agenda-type (type)
-  (case type
-    ('tags "Tags: ")
-    ('todo "TODO: ")
-    ('tags-tree "Tags tree: ")
-    ('todo-tree "TODO tree: ")
-    ('occur-tree "Occur tree: ")
-    (t "Agenda command ???")))
+  (pcase type
+    (`tags "Tags: ")
+    (`todo "TODO: ")
+    (`tags-tree "Tags tree: ")
+    (`todo-tree "TODO tree: ")
+    (`occur-tree "Occur tree: ")
+    (_ "Agenda command ???")))
 
 (defun org-mouse-list-options-menu (alloptions &optional function)
   (let ((options (save-match-data
                   (split-string (match-string-no-properties 1)))))
     (print options)
-    (loop for name in alloptions
-         collect
-         (vector name
-                 `(progn
-                    (replace-match
-                     (mapconcat 'identity
-                                (sort (if (member ',name ',options)
-                                          (delete ',name ',options)
-                                        (cons ',name ',options))
-                                      'string-lessp)
-                                " ")
-                     nil nil nil 1)
-                    (when (functionp ',function) (funcall ',function)))
-                 :style 'toggle
-                 :selected (and (member name options) t)))))
+    (cl-loop for name in alloptions
+            collect
+            (vector name
+                    `(progn
+                       (replace-match
+                        (mapconcat 'identity
+                                   (sort (if (member ',name ',options)
+                                             (delete ',name ',options)
+                                           (cons ',name ',options))
+                                         'string-lessp)
+                                   " ")
+                        nil nil nil 1)
+                       (when (functionp ',function) (funcall ',function)))
+                    :style 'toggle
+                    :selected (and (member name options) t)))))
 
 (defun org-mouse-clip-text (text maxlength)
   (if (> (length text) maxlength)
@@ -498,7 +498,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
    `("Main Menu"
      ["Show Overview" org-mouse-show-overview t]
      ["Show Headlines" org-mouse-show-headlines t]
-     ["Show All" show-all t]
+     ["Show All" outline-show-all t]
      ["Remove Highlights" org-remove-occur-highlights
       :visible org-occur-highlights]
      "--"
@@ -556,12 +556,12 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
   (let ((contextdata (assq context contextlist)))
     (when contextdata
       (save-excursion
-       (goto-char (second contextdata))
-       (re-search-forward ".*" (third contextdata))))))
+       (goto-char (nth 1 contextdata))
+       (re-search-forward ".*" (nth 2 contextdata))))))
 
 (defun org-mouse-for-each-item (funct)
-  ;; Functions called by `org-apply-on-list' need an argument
-  (let ((wrap-fun (lambda (c) (funcall funct))))
+  ;; Functions called by `org-apply-on-list' need an argument.
+  (let ((wrap-fun (lambda (_) (funcall funct))))
     (when (ignore-errors (goto-char (org-in-item-p)))
       (save-excursion (org-apply-on-list wrap-fun nil)))))
 
@@ -572,14 +572,14 @@ This means, between the beginning of line and the point."
     (skip-chars-backward " \t*") (bolp)))
 
 (defun org-mouse-insert-item (text)
-  (case (org-mouse-line-position)
-    (:beginning                        ; insert before
+  (cl-case (org-mouse-line-position)
+    (:beginning                                ; insert before
      (beginning-of-line)
      (looking-at "[ \t]*")
      (open-line 1)
-     (org-indent-to-column (- (match-end 0) (match-beginning 0)))
+     (indent-to-column (- (match-end 0) (match-beginning 0)))
      (insert "+ "))
-    (:middle                   ; insert after
+    (:middle                           ; insert after
      (end-of-line)
      (newline t)
      (indent-relative)
@@ -587,7 +587,7 @@ This means, between the beginning of line and the point."
     (:end                              ; insert text here
      (skip-chars-backward " \t")
      (kill-region (point) (point-at-eol))
-     (unless (org-looking-back org-mouse-punctuation)
+     (unless (looking-back org-mouse-punctuation (line-beginning-position))
        (insert (concat org-mouse-punctuation " ")))))
   (insert text)
   (beginning-of-line))
@@ -638,14 +638,15 @@ This means, between the beginning of line and the point."
            (progn (save-excursion (goto-char (region-beginning)) (insert "[["))
                   (save-excursion (goto-char (region-end)) (insert "]]")))]
           ["Insert Link Here" (org-mouse-yank-link ',event)]))))
-     ((save-excursion (beginning-of-line) (looking-at "#\\+STARTUP: \\(.*\\)"))
+     ((save-excursion (beginning-of-line) (looking-at "[ \t]*#\\+STARTUP: 
\\(.*\\)"))
       (popup-menu
        `(nil
         ,@(org-mouse-list-options-menu (mapcar 'car org-startup-options)
                                        'org-mode-restart))))
      ((or (eolp)
          (and (looking-at "\\(  \\|\t\\)\\(+:[0-9a-zA-Z_:]+\\)?\\(  
\\|\t\\)+$")
-              (org-looking-back "  \\|\t" (- (point) 2))))
+              (looking-back "  \\|\t" (- (point) 2)
+                            (line-beginning-position))))
       (org-mouse-popup-global-menu))
      ((funcall get-context :checkbox)
       (popup-menu
@@ -737,13 +738,13 @@ This means, between the beginning of line and the point."
         ["- 1 Month" (org-timestamp-change -1 'month)])))
      ((funcall get-context :table-special)
       (let ((mdata (match-data)))
-       (incf (car mdata) 2)
+       (cl-incf (car mdata) 2)
        (store-match-data mdata))
       (message "match: %S" (match-string 0))
       (popup-menu `(nil ,@(org-mouse-keyword-replace-menu
                           '(" " "!" "^" "_" "$" "#" "*" "'") 0
                           (lambda (mark)
-                            (case (string-to-char mark)
+                            (cl-case (string-to-char mark)
                               (?  "( ) Nothing Special")
                               (?! "(!) Column Names")
                               (?^ "(^) Field Names Above")
@@ -914,7 +915,7 @@ This means, between the beginning of line and the point."
                   ((org-footnote-at-reference-p) nil)
                   (t ad-do-it))))))
 
-(defun org-mouse-move-tree-start (event)
+(defun org-mouse-move-tree-start (_event)
   (interactive "e")
   (message "Same line: promote/demote, (***):move before, (text): make a 
child"))
 
@@ -993,7 +994,7 @@ This means, between the beginning of line and the point."
 (defvar org-mouse-cmd) ;dynamically scoped from `org-with-remote-undo'.
 
 (defun org-mouse-do-remotely (command)
-                                       ;  (org-agenda-check-no-diary)
+  ;;  (org-agenda-check-no-diary)
   (when (get-text-property (point) 'org-marker)
     (let* ((anticol (- (point-at-eol) (point)))
           (marker (get-text-property (point) 'org-marker))
@@ -1031,7 +1032,7 @@ This means, between the beginning of line and the point."
              (org-agenda-change-all-lines newhead hdmarker 'fixface))))
        t))))
 
-(defun org-mouse-agenda-context-menu (&optional event)
+(defun org-mouse-agenda-context-menu (&optional _event)
   (or (org-mouse-do-remotely 'org-mouse-context-menu)
       (popup-menu
        '("Agenda"
@@ -1093,17 +1094,17 @@ This means, between the beginning of line and the 
point."
                                        ; (setq org-agenda-mode-hook nil)
 (defvar org-agenda-mode-map)
 (add-hook 'org-agenda-mode-hook
-         #'(lambda ()
-             (setq org-mouse-context-menu-function 
'org-mouse-agenda-context-menu)
-             (org-defkey org-agenda-mode-map [mouse-3] 
'org-mouse-show-context-menu)
-             (org-defkey org-agenda-mode-map [down-mouse-3] 
'org-mouse-move-tree-start)
-             (org-defkey org-agenda-mode-map [C-mouse-4] 'org-agenda-earlier)
-             (org-defkey org-agenda-mode-map [C-mouse-5] 'org-agenda-later)
-             (org-defkey org-agenda-mode-map [drag-mouse-3]
-                         #'(lambda (event) (interactive "e")
-                             (case (org-mouse-get-gesture event)
-                               (:left (org-agenda-earlier 1))
-                               (:right (org-agenda-later 1)))))))
+         (lambda ()
+           (setq org-mouse-context-menu-function 
'org-mouse-agenda-context-menu)
+           (org-defkey org-agenda-mode-map [mouse-3] 
'org-mouse-show-context-menu)
+           (org-defkey org-agenda-mode-map [down-mouse-3] 
'org-mouse-move-tree-start)
+           (org-defkey org-agenda-mode-map [C-mouse-4] 'org-agenda-earlier)
+           (org-defkey org-agenda-mode-map [C-mouse-5] 'org-agenda-later)
+           (org-defkey org-agenda-mode-map [drag-mouse-3]
+                       (lambda (event) (interactive "e")
+                         (cl-case (org-mouse-get-gesture event)
+                           (:left (org-agenda-earlier 1))
+                           (:right (org-agenda-later 1)))))))
 
 (provide 'org-mouse)
 
diff --git a/lisp/org/org-pcomplete.el b/lisp/org/org-pcomplete.el
index 034c20e..61ec5fa 100644
--- a/lisp/org/org-pcomplete.el
+++ b/lisp/org/org-pcomplete.el
@@ -1,4 +1,4 @@
-;;; org-pcomplete.el --- In-buffer completion code
+;;; org-pcomplete.el --- In-buffer Completion Code -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 ;;
@@ -27,21 +27,17 @@
 
 ;;;; Require other packages
 
-(eval-when-compile
-  (require 'cl))
-
 (require 'org-macs)
 (require 'org-compat)
 (require 'pcomplete)
 
-(declare-function org-split-string "org" (string &optional separators))
-(declare-function org-make-org-heading-search-string "org"
-                 (&optional string))
+(declare-function org-make-org-heading-search-string "org" (&optional string))
 (declare-function org-get-buffer-tags "org" ())
 (declare-function org-get-tags "org" ())
 (declare-function org-buffer-property-keys "org"
-                 (&optional include-specials include-defaults include-columns))
-(declare-function org-entry-properties "org" (&optional pom which specific))
+                 (&optional specials defaults columns ignore-malformed))
+(declare-function org-entry-properties "org" (&optional pom which))
+(declare-function org-tag-alist-to-string "org" (alist &optional skip-key))
 
 ;;;; Customization variables
 
@@ -52,12 +48,13 @@
 
 (defvar org-drawer-regexp)
 (defvar org-property-re)
+(defvar org-current-tag-alist)
 
 (defun org-thing-at-point ()
   "Examine the thing at point and let the caller know what it is.
 The return value is a string naming the thing at point."
   (let ((beg1 (save-excursion
-               (skip-chars-backward (org-re "[:alnum:]-_@"))
+               (skip-chars-backward "[:alnum:]-_@")
                (point)))
        (beg (save-excursion
               (skip-chars-backward "a-zA-Z0-9-_:$")
@@ -93,8 +90,10 @@ The return value is a string naming the thing at point."
             (skip-chars-backward "[ \t\n]")
             ;; org-drawer-regexp matches a whole line but while
             ;; looking-back, we just ignore trailing whitespaces
-            (or (org-looking-back (substring org-drawer-regexp 0 -1))
-                (org-looking-back org-property-re))))
+            (or (looking-back (substring org-drawer-regexp 0 -1)
+                              (line-beginning-position))
+                (looking-back org-property-re
+                              (line-beginning-position)))))
       (cons "prop" nil))
      ((and (equal (char-before beg1) ?:)
           (not (equal (char-after (point-at-bol)) ?*)))
@@ -140,7 +139,6 @@ When completing for #+STARTUP, for example, this function 
returns
                pcomplete-default-completion-function))))
 
 (defvar org-options-keywords)           ; From org.el
-(defvar org-element-block-name-alist)   ; From org-element.el
 (defvar org-element-affiliated-keywords) ; From org-element.el
 (declare-function org-get-export-keywords "org" ())
 (defun pcomplete/org-mode/file-option ()
@@ -153,16 +151,19 @@ When completing for #+STARTUP, for example, this function 
returns
            (mapcar (lambda (keyword) (concat keyword ": "))
                    org-element-affiliated-keywords)
            (let (block-names)
-             (dolist (block-info org-element-block-name-alist block-names)
-               (let ((name (car block-info)))
-                 (push (format "END_%s" name) block-names)
-                 (push (concat "BEGIN_"
-                               name
-                               ;; Since language is compulsory in
-                               ;; source blocks, add a space.
-                               (and (equal name "SRC") " "))
-                       block-names)
-                 (push (format "ATTR_%s: " name) block-names))))
+             (dolist (name
+                      '("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC"
+                        "VERSE")
+                      block-names)
+               (push (format "END_%s" name) block-names)
+               (push (concat "BEGIN_"
+                             name
+                             ;; Since language is compulsory in
+                             ;; export blocks source blocks, add
+                             ;; a space.
+                             (and (member name '("EXPORT" "SRC")) " "))
+                     block-names)
+               (push (format "ATTR_%s: " name) block-names)))
            (mapcar (lambda (keyword) (concat keyword ": "))
                    (org-get-export-keywords))))
    (substring pcomplete-stub 2)))
@@ -233,20 +234,10 @@ When completing for #+STARTUP, for example, this function 
returns
                (setq opts (delete "showstars" opts)))))
            opts))))
 
-(defvar org-tag-alist)
 (defun pcomplete/org-mode/file-option/tags ()
   "Complete arguments for the #+TAGS file option."
   (pcomplete-here
-   (list
-    (mapconcat (lambda (x)
-                (cond
-                 ((eq :startgroup (car x)) "{")
-                 ((eq :endgroup (car x)) "}")
-                 ((eq :grouptags (car x)) ":")
-                 ((eq :newline (car x)) "\\n")
-                 ((cdr x) (format "%s(%c)" (car x) (cdr x)))
-                 (t (car x))))
-              org-tag-alist " "))))
+   (list (org-tag-alist-to-string org-current-tag-alist))))
 
 (defun pcomplete/org-mode/file-option/title ()
   "Complete arguments for the #+TITLE file option."
@@ -271,8 +262,8 @@ When completing for #+STARTUP, for example, this function 
returns
              "|:" "tags:" "tasks:" "<:" "todo:")
            ;; OPTION items from registered back-ends.
            (let (items)
-             (dolist (backend (org-bound-and-true-p
-                               org-export--registered-backends))
+             (dolist (backend (bound-and-true-p
+                               org-export-registered-backends))
                (dolist (option (org-export-backend-options backend))
                  (let ((item (nth 2 option)))
                    (when item (push (concat item ":") items)))))
@@ -283,7 +274,7 @@ When completing for #+STARTUP, for example, this function 
returns
   (while (pcomplete-here
          (pcomplete-uniqify-list
           (mapcar (lambda (item) (format "%s:" (car item)))
-                  (org-bound-and-true-p org-html-infojs-opts-table))))))
+                  (bound-and-true-p org-html-infojs-opts-table))))))
 
 (defun pcomplete/org-mode/file-option/bind ()
   "Complete arguments for the #+BIND file option, which are variable names."
@@ -324,26 +315,24 @@ This needs more work, to handle headings with lots of 
spaces in them."
        (save-excursion
         (goto-char (point-min))
         (let (tbl)
-          (while (re-search-forward org-todo-line-regexp nil t)
-            (push (org-make-org-heading-search-string
-                   (match-string-no-properties 3))
-                  tbl))
+          (let ((case-fold-search nil))
+            (while (re-search-forward org-todo-line-regexp nil t)
+              (push (org-make-org-heading-search-string
+                     (match-string-no-properties 3))
+                    tbl)))
           (pcomplete-uniqify-list tbl)))
        (substring pcomplete-stub 1))))
 
-(defvar org-tag-alist)
 (defun pcomplete/org-mode/tag ()
   "Complete a tag name.  Omit tags already set."
   (while (pcomplete-here
-         (mapcar (lambda (x)
-                   (concat x ":"))
+         (mapcar (lambda (x) (concat x ":"))
                  (let ((lst (pcomplete-uniqify-list
-                             (or (remove
+                             (or (remq
                                   nil
-                                  (mapcar (lambda (x)
-                                            (and (stringp (car x)) (car x)))
-                                          org-tag-alist))
-                                 (mapcar 'car (org-get-buffer-tags))))))
+                                  (mapcar (lambda (x) (org-string-nw-p (car 
x)))
+                                          org-current-tag-alist))
+                                 (mapcar #'car (org-get-buffer-tags))))))
                    (dolist (tag (org-get-tags))
                      (setq lst (delete tag lst)))
                    lst))
@@ -357,31 +346,12 @@ This needs more work, to handle headings with lots of 
spaces in them."
             (concat x ": "))
           (let ((lst (pcomplete-uniqify-list
                       (copy-sequence
-                       (org-buffer-property-keys nil t t)))))
+                       (org-buffer-property-keys nil t t t)))))
             (dolist (prop (org-entry-properties))
               (setq lst (delete (car prop) lst)))
             lst))
    (substring pcomplete-stub 1)))
 
-(defvar org-drawers)
-
-(defun pcomplete/org-mode/drawer ()
-  "Complete a drawer name."
-  (let ((spc (save-excursion
-              (move-beginning-of-line 1)
-              (looking-at "^\\([ \t]*\\):")
-              (match-string 1)))
-       (cpllist (mapcar (lambda (x) (concat x ": ")) org-drawers)))
-    (pcomplete-here cpllist
-                   (substring pcomplete-stub 1)
-                   (unless (or (not (delq
-                                     nil
-                                     (mapcar (lambda(x)
-                                               (string-match (substring 
pcomplete-stub 1) x))
-                                             cpllist)))
-                               (looking-at "[ \t]*\n.*:END:"))
-                     (save-excursion (insert "\n" spc ":END:"))))))
-
 (defun pcomplete/org-mode/block-option/src ()
   "Complete the arguments of a begin_src block.
 Complete a language in the first field, the header arguments and switches."
diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el
index 5ccfbb1..449143a 100644
--- a/lisp/org/org-plot.el
+++ b/lisp/org/org-plot.el
@@ -1,4 +1,4 @@
-;;; org-plot.el --- Support for plotting from Org-mode
+;;; org-plot.el --- Support for Plotting from Org -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 ;;
@@ -25,14 +25,14 @@
 
 ;; Borrows ideas and a couple of lines of code from org-exp.el.
 
-;; Thanks to the org-mode mailing list for testing and implementation
-;; and feature suggestions
+;; Thanks to the Org mailing list for testing and implementation and
+;; feature suggestions
 
 ;;; Code:
+
+(require 'cl-lib)
 (require 'org)
 (require 'org-table)
-(eval-when-compile
-  (require 'cl))
 
 (declare-function gnuplot-delchar-or-maybe-eof "ext:gnuplot" (arg))
 (declare-function gnuplot-mode "ext:gnuplot" ())
@@ -49,41 +49,39 @@
 (defun org-plot/add-options-to-plist (p options)
   "Parse an OPTIONS line and set values in the property list P.
 Returns the resulting property list."
-  (let (o)
-    (when options
-      (let ((op '(("type"    . :plot-type)
-                 ("script"  . :script)
-                 ("line"    . :line)
-                 ("set"     . :set)
-                 ("title"   . :title)
-                 ("ind"     . :ind)
-                 ("deps"    . :deps)
-                 ("with"    . :with)
-                 ("file"    . :file)
-                 ("labels"  . :labels)
-                 ("map"     . :map)
-                  ("timeind" . :timeind)
-                 ("timefmt" . :timefmt)))
-           (multiples '("set" "line"))
-           (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)")
-           (start 0)
-           o)
-       (while (setq o (pop op))
-         (if (member (car o) multiples) ;; keys with multiple values
-             (while (string-match
-                     (concat (regexp-quote (car o)) regexp)
-                     options start)
-               (setq start (match-end 0))
-               (setq p (plist-put p (cdr o)
-                                  (cons (car (read-from-string
-                                              (match-string 1 options)))
-                                        (plist-get p (cdr o)))))
-               p)
-           (if (string-match (concat (regexp-quote (car o)) regexp)
-                             options)
-               (setq p (plist-put p (cdr o)
-                                  (car (read-from-string
-                                        (match-string 1 options)))))))))))
+  (when options
+    (let ((op '(("type"    . :plot-type)
+               ("script"  . :script)
+               ("line"    . :line)
+               ("set"     . :set)
+               ("title"   . :title)
+               ("ind"     . :ind)
+               ("deps"    . :deps)
+               ("with"    . :with)
+               ("file"    . :file)
+               ("labels"  . :labels)
+               ("map"     . :map)
+               ("timeind" . :timeind)
+               ("timefmt" . :timefmt)))
+         (multiples '("set" "line"))
+         (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)")
+         (start 0))
+      (dolist (o op)
+       (if (member (car o) multiples) ;; keys with multiple values
+           (while (string-match
+                   (concat (regexp-quote (car o)) regexp)
+                   options start)
+             (setq start (match-end 0))
+             (setq p (plist-put p (cdr o)
+                                (cons (car (read-from-string
+                                            (match-string 1 options)))
+                                      (plist-get p (cdr o)))))
+             p)
+         (if (string-match (concat (regexp-quote (car o)) regexp)
+                           options)
+             (setq p (plist-put p (cdr o)
+                                (car (read-from-string
+                                      (match-string 1 options))))))))))
   p)
 
 (defun org-plot/goto-nearest-table ()
@@ -119,10 +117,9 @@ will be added.  Returns the resulting property list."
 Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
   (with-temp-file
       data-file
-    (make-local-variable 'org-plot-timestamp-fmt)
-    (setq org-plot-timestamp-fmt (or
-                                 (plist-get params :timefmt)
-                                 "%Y-%m-%d-%H:%M:%S"))
+    (setq-local org-plot-timestamp-fmt (or
+                                       (plist-get params :timefmt)
+                                       "%Y-%m-%d-%H:%M:%S"))
     (insert (orgtbl-to-generic
             table
             (org-combine-plists
@@ -140,7 +137,7 @@ and dependant variables."
         (deps (if (plist-member params :deps)
                   (mapcar (lambda (val) (- val 1)) (plist-get params :deps))
                 (let (collector)
-                  (dotimes (col (length (first table)))
+                  (dotimes (col (length (nth 0 table)))
                     (setf collector (cons col collector)))
                   collector)))
         (counter 0)
@@ -158,7 +155,7 @@ and dependant variables."
                          table)))
     ;; write table to gnuplot grid datafile format
     (with-temp-file data-file
-      (let ((num-rows (length table)) (num-cols (length (first table)))
+      (let ((num-rows (length table)) (num-cols (length (nth 0 table)))
            (gnuplot-row (lambda (col row value)
                           (setf col (+ 1 col)) (setf row (+ 1 row))
                           (format "%f  %f  %f\n%f  %f  %f\n"
@@ -187,9 +184,7 @@ NUM-COLS controls the number of columns plotted in a 2-d 
plot.
 Optional argument PREFACE returns only option parameters in a
 manner suitable for prepending to a user-specified script."
   (let* ((type (plist-get params :plot-type))
-        (with (if (equal type 'grid)
-                  'pm3d
-                (plist-get params :with)))
+        (with (if (eq type 'grid) 'pm3d (plist-get params :with)))
         (sets (plist-get params :set))
         (lines (plist-get params :line))
         (map (plist-get params :map))
@@ -204,68 +199,72 @@ manner suitable for prepending to a user-specified 
script."
         (x-labels (plist-get params :xlabels))
         (y-labels (plist-get params :ylabels))
         (plot-str "'%s' using %s%d%s with %s title '%s'")
-        (plot-cmd (case type
-                    ('2d "plot")
-                    ('3d "splot")
-                    ('grid "splot")))
+        (plot-cmd (pcase type
+                    (`2d "plot")
+                    (`3d "splot")
+                    (`grid "splot")))
         (script "reset")
-                                       ; ats = add-to-script
-        (ats (lambda (line) (setf script (format "%s\n%s" script line))))
+        ;; ats = add-to-script
+        (ats (lambda (line) (setf script (concat script "\n" line))))
         plot-lines)
-    (when file ;; output file
+    (when file                         ; output file
       (funcall ats (format "set term %s" (file-name-extension file)))
       (funcall ats (format "set output '%s'" file)))
-    (case type ;; type
-      ('2d ())
-      ('3d (if map (funcall ats "set map")))
-      ('grid (if map (funcall ats "set pm3d map")
-              (funcall ats "set pm3d"))))
-    (when title (funcall ats (format "set title '%s'" title))) ;; title
-    (when lines (mapc (lambda (el) (funcall ats el)) lines)) ;; line
-    (when sets ;; set
-      (mapc (lambda (el) (funcall ats (format "set %s" el))) sets))
-    (when x-labels ;; x labels (xtics)
+    (pcase type                                ; type
+      (`2d ())
+      (`3d (when map (funcall ats "set map")))
+      (`grid (funcall ats (if map "set pm3d map" "set pm3d"))))
+    (when title (funcall ats (format "set title '%s'" title))) ; title
+    (mapc ats lines)                                          ; line
+    (dolist (el sets) (funcall ats (format "set %s" el)))      ; set
+    ;; Unless specified otherwise, values are TAB separated.
+    (unless (string-match-p "^set datafile separator" script)
+      (funcall ats "set datafile separator \"\\t\""))
+    (when x-labels                     ; x labels (xtics)
       (funcall ats
               (format "set xtics (%s)"
                       (mapconcat (lambda (pair)
                                    (format "\"%s\" %d" (cdr pair) (car pair)))
                                  x-labels ", "))))
-    (when y-labels ;; y labels (ytics)
+    (when y-labels                     ; y labels (ytics)
       (funcall ats
               (format "set ytics (%s)"
                       (mapconcat (lambda (pair)
                                    (format "\"%s\" %d" (cdr pair) (car pair)))
                                  y-labels ", "))))
-    (when time-ind ;; timestamp index
+    (when time-ind                     ; timestamp index
       (funcall ats "set xdata time")
       (funcall ats (concat "set timefmt \""
-                          (or timefmt ;; timefmt passed to gnuplot
+                          (or timefmt  ; timefmt passed to gnuplot
                               "%Y-%m-%d-%H:%M:%S") "\"")))
     (unless preface
-      (case type ;; plot command
-       ('2d (dotimes (col num-cols)
-              (unless (and (equal type '2d)
-                           (or (and ind (equal (+ 1 col) ind))
-                               (and deps (not (member (+ 1 col) deps)))))
+      (pcase type                      ; plot command
+       (`2d (dotimes (col num-cols)
+              (unless (and (eq type '2d)
+                           (or (and ind (equal (1+ col) ind))
+                               (and deps (not (member (1+ col) deps)))))
                 (setf plot-lines
                       (cons
                        (format plot-str data-file
                                (or (and ind (> ind 0)
-                                         (not text-ind)
-                                         (format "%d:" ind)) "")
-                               (+ 1 col)
+                                        (not text-ind)
+                                        (format "%d:" ind)) "")
+                               (1+ col)
                                (if text-ind (format ":xticlabel(%d)" ind) "")
                                with
-                               (or (nth col col-labels) (format "%d" (+ 1 
col))))
+                               (or (nth col col-labels)
+                                   (format "%d" (1+ col))))
                        plot-lines)))))
-       ('3d
+       (`3d
         (setq plot-lines (list (format "'%s' matrix with %s title ''"
                                        data-file with))))
-       ('grid
+       (`grid
         (setq plot-lines (list (format "'%s' with %s title ''"
                                        data-file with)))))
       (funcall ats
-              (concat plot-cmd " " (mapconcat 'identity (reverse plot-lines) 
",\\\n    "))))
+              (concat plot-cmd " " (mapconcat #'identity
+                                              (reverse plot-lines)
+                                              ",\\\n    "))))
     script))
 
 ;;-----------------------------------------------------------------------------
@@ -279,59 +278,59 @@ line directly before or after the table."
   (require 'gnuplot)
   (save-window-excursion
     (delete-other-windows)
-    (when (get-buffer "*gnuplot*") ;; reset *gnuplot* if it already running
+    (when (get-buffer "*gnuplot*") ; reset *gnuplot* if it already running
       (with-current-buffer "*gnuplot*"
-       (goto-char (point-max))
-       (gnuplot-delchar-or-maybe-eof nil)))
+       (goto-char (point-max))))
     (org-plot/goto-nearest-table)
-    ;; set default options
-    (mapc
-     (lambda (pair)
-       (unless (plist-member params (car pair))
-        (setf params (plist-put params (car pair) (cdr pair)))))
-     org-plot/gnuplot-default-options)
+    ;; Set default options.
+    (dolist (pair org-plot/gnuplot-default-options)
+      (unless (plist-member params (car pair))
+       (setf params (plist-put params (car pair) (cdr pair)))))
     ;; collect table and table information
     (let* ((data-file (make-temp-file "org-plot"))
           (table (org-table-to-lisp))
-          (num-cols (length (if (eq (first table) 'hline) (second table)
-                              (first table)))))
-      (while (equal 'hline (first table)) (setf table (cdr table)))
-      (when (equal (second table) 'hline)
-       (setf params (plist-put params :labels (first table))) ;; headers to 
labels
-       (setf table (delq 'hline (cdr table)))) ;; clean non-data from table
-      ;; collect options
+          (num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table)
+                              (nth 0 table)))))
+      (run-with-idle-timer 0.1 nil #'delete-file data-file)
+      (while (eq 'hline (car table)) (setf table (cdr table)))
+      (when (eq (cadr table) 'hline)
+       (setf params
+             (plist-put params :labels (nth 0 table))) ; headers to labels
+       (setf table (delq 'hline (cdr table)))) ; clean non-data from table
+      ;; Collect options.
       (save-excursion (while (and (equal 0 (forward-line -1))
                                  (looking-at "[[:space:]]*#\\+"))
                        (setf params (org-plot/collect-options params))))
-      ;; dump table to datafile (very different for grid)
-      (case (plist-get params :plot-type)
-       ('2d   (org-plot/gnuplot-to-data table data-file params))
-       ('3d   (org-plot/gnuplot-to-data table data-file params))
-       ('grid (let ((y-labels (org-plot/gnuplot-to-grid-data
+      ;; Dump table to datafile (very different for grid).
+      (pcase (plist-get params :plot-type)
+       (`2d   (org-plot/gnuplot-to-data table data-file params))
+       (`3d   (org-plot/gnuplot-to-data table data-file params))
+       (`grid (let ((y-labels (org-plot/gnuplot-to-grid-data
                                table data-file params)))
                 (when y-labels (plist-put params :ylabels y-labels)))))
-      ;; check for timestamp ind column
-      (let ((ind (- (plist-get params :ind) 1)))
-       (when (and (>= ind 0) (equal '2d (plist-get params :plot-type)))
+      ;; Check for timestamp ind column.
+      (let ((ind (1- (plist-get params :ind))))
+       (when (and (>= ind 0) (eq '2d (plist-get params :plot-type)))
          (if (= (length
                  (delq 0 (mapcar
                           (lambda (el)
-                            (if (string-match org-ts-regexp3 el)
-                                0 1))
-                          (mapcar (lambda (row) (nth ind row)) table)))) 0)
+                            (if (string-match org-ts-regexp3 el) 0 1))
+                          (mapcar (lambda (row) (nth ind row)) table))))
+                0)
              (plist-put params :timeind t)
-           ;; check for text ind column
+           ;; Check for text ind column.
            (if (or (string= (plist-get params :with) "hist")
                    (> (length
                        (delq 0 (mapcar
                                 (lambda (el)
                                   (if (string-match org-table-number-regexp el)
                                       0 1))
-                                (mapcar (lambda (row) (nth ind row)) table)))) 
0))
+                                (mapcar (lambda (row) (nth ind row)) table))))
+                      0))
                (plist-put params :textind t)))))
-      ;; write script
+      ;; Write script.
       (with-temp-buffer
-       (if (plist-get params :script) ;; user script
+       (if (plist-get params :script)  ; user script
            (progn (insert
                     (org-plot/gnuplot-script data-file num-cols params t))
                    (insert "\n")
@@ -339,14 +338,12 @@ line directly before or after the table."
                    (goto-char (point-min))
                    (while (re-search-forward "$datafile" nil t)
                      (replace-match data-file nil nil)))
-         (insert
-          (org-plot/gnuplot-script data-file num-cols params)))
-       ;; graph table
+         (insert (org-plot/gnuplot-script data-file num-cols params)))
+       ;; Graph table.
        (gnuplot-mode)
        (gnuplot-send-buffer-to-gnuplot))
-      ;; cleanup
-      (bury-buffer (get-buffer "*gnuplot*"))
-      (run-with-idle-timer 0.1 nil (lambda () (delete-file data-file))))))
+      ;; Cleanup.
+      (bury-buffer (get-buffer "*gnuplot*")))))
 
 (provide 'org-plot)
 
diff --git a/lisp/org/org-protocol.el b/lisp/org/org-protocol.el
index 4bd83be..8254356 100644
--- a/lisp/org/org-protocol.el
+++ b/lisp/org/org-protocol.el
@@ -1,4 +1,4 @@
-;;; org-protocol.el --- Intercept calls from emacsclient to trigger custom 
actions.
+;;; org-protocol.el --- Intercept Calls from Emacsclient to Trigger Custom 
Actions -*- lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 ;;
@@ -49,7 +49,7 @@
 ;;   4.) Try this from the command line (adjust the URL as needed):
 ;;
 ;;       $ emacsclient \
-;;         
org-protocol://store-link://http:%2F%2Flocalhost%2Findex.html/The%20title
+;;         
org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title
 ;;
 ;;   5.) Optionally add custom sub-protocols and handlers:
 ;;
@@ -60,7 +60,7 @@
 ;;
 ;;       A "sub-protocol" will be found in URLs like this:
 ;;
-;;           org-protocol://sub-protocol://data
+;;           org-protocol://sub-protocol?key=val&key2=val2
 ;;
 ;; If it works, you can now setup other applications for using this feature.
 ;;
@@ -81,12 +81,12 @@
 ;;   * `org-protocol-open-source' uses the sub-protocol \"open-source\" and 
maps
 ;;     URLs to local filenames defined in `org-protocol-project-alist'.
 ;;
-;;   * `org-protocol-store-link' stores an Org-link (if Org-mode is present) 
and
+;;   * `org-protocol-store-link' stores an Org link (if Org is present) and
 ;;     pushes the browsers URL to the `kill-ring' for yanking.  This handler is
 ;;     triggered through the sub-protocol \"store-link\".
 ;;
 ;;   * Call `org-protocol-capture' by using the sub-protocol \"capture\".  If
-;;     Org-mode is loaded, Emacs will pop-up a capture buffer and fill the
+;;     Org is loaded, Emacs will pop-up a capture buffer and fill the
 ;;     template with the data provided.  I.e. the browser's URL is inserted as 
an
 ;;     Org-link of which the page title will be the description part.  If text
 ;;     was select in the browser, that text will be the body of the entry.
@@ -94,20 +94,20 @@
 ;; You may use the same bookmark URL for all those standard handlers and just
 ;; adjust the sub-protocol used:
 ;;
-;;     location.href='org-protocol://sub-protocol://'+
-;;           encodeURIComponent(location.href)+'/'+
-;;           encodeURIComponent(document.title)+'/'+
+;;     location.href='org-protocol://sub-protocol?url='+
+;;           encodeURIComponent(location.href)+'&title='+
+;;           encodeURIComponent(document.title)+'&body='+
 ;;           encodeURIComponent(window.getSelection())
 ;;
 ;; The handler for the sub-protocol \"capture\" detects an optional template
 ;; char that, if present, triggers the use of a special template.
 ;; Example:
 ;;
-;;     location.href='org-protocol://sub-protocol://x/'+ ...
+;;     location.href='org-protocol://capture?template=x'+ ...
 ;;
-;;  use template ?x.
+;;  uses template ?x.
 ;;
-;; Note, that using double slashes is optional from org-protocol.el's point of
+;; Note that using double slashes is optional from org-protocol.el's point of
 ;; view because emacsclient squashes the slashes to one.
 ;;
 ;;
@@ -116,25 +116,12 @@
 ;;; Code:
 
 (require 'org)
-(eval-when-compile
-  (require 'cl))
 
 (declare-function org-publish-get-project-from-filename "ox-publish"
                  (filename &optional up))
 (declare-function server-edit "server" (&optional arg))
 
-(define-obsolete-function-alias
-  'org-protocol-unhex-compound 'org-link-unescape-compound
-  "2011-02-17")
-
-(define-obsolete-function-alias
-  'org-protocol-unhex-string 'org-link-unescape
-  "2011-02-17")
-
-(define-obsolete-function-alias
-  'org-protocol-unhex-single-byte-sequence
-  'org-link-unescape-single-byte-sequence
-  "2011-02-17")
+(defvar org-capture-link-is-already-stored)
 
 (defgroup org-protocol nil
   "Intercept calls from emacsclient to trigger custom actions.
@@ -225,27 +212,36 @@ Each element of this list must be of the form:
 
   (module-name :protocol protocol :function func :kill-client nil)
 
-protocol - protocol to detect in a filename without trailing colon and slashes.
-           See rfc1738 section 2.1 for more on this.
-           If you define a protocol \"my-protocol\", 
`org-protocol-check-filename-for-protocol'
-           will search filenames for \"org-protocol:/my-protocol:/\"
-           and trigger your action for every match. `org-protocol' is defined 
in
-           `org-protocol-the-protocol'.  Double and triple slashes are 
compressed
-           to one by emacsclient.
-
-function - function that handles requests with protocol and takes exactly one
-           argument: the filename with all protocols stripped.  If the function
-           returns nil, emacsclient and -server do nothing.  Any non-nil return
-           value is considered a valid filename and thus passed to the server.
-
-           `org-protocol.el provides some support for handling those filenames,
-           if you stay with the conventions used for the standard handlers in
-           `org-protocol-protocol-alist-default'.  See 
`org-protocol-split-data'.
+protocol - protocol to detect in a filename without trailing
+           colon and slashes.  See rfc1738 section 2.1 for more
+           on this.  If you define a protocol \"my-protocol\",
+           `org-protocol-check-filename-for-protocol' will search
+           filenames for \"org-protocol:/my-protocol\" and
+           trigger your action for every match.  `org-protocol'
+           is defined in `org-protocol-the-protocol'.  Double and
+           triple slashes are compressed to one by emacsclient.
+
+function - function that handles requests with protocol and takes
+           one argument.  If a new-style link (key=val&key2=val2)
+           is given, the argument will be a property list with
+           the values from the link.  If an old-style link is
+           given (val1/val2), the argument will be the filename
+           with all protocols stripped.
+
+           If the function returns nil, emacsclient and -server
+           do nothing.  Any non-nil return value is considered a
+           valid filename and thus passed to the server.
+
+           `org-protocol.el' provides some support for handling
+           old-style filenames, if you follow the conventions
+           used for the standard handlers in
+           `org-protocol-protocol-alist-default'.  See
+           `org-protocol-parse-parameters'.
 
 kill-client - If t, kill the client immediately, once the sub-protocol is
            detected.  This is necessary for actions that can be interrupted by
-           `C-g' to avoid dangling emacsclients.  Note, that all other command
-           line arguments but the this one will be discarded, greedy handlers
+           `C-g' to avoid dangling emacsclients.  Note that all other command
+           line arguments but the this one will be discarded.  Greedy handlers
            still receive the whole list of arguments though.
 
 Here is an example:
@@ -269,7 +265,7 @@ string with two characters."
 
 (defcustom org-protocol-data-separator "/+\\|\\?"
   "The default data separator to use.
-   This should be a single regexp string."
+This should be a single regexp string."
   :group 'org-protocol
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -278,21 +274,20 @@ string with two characters."
 ;;; Helper functions:
 
 (defun org-protocol-sanitize-uri (uri)
-  "emacsclient compresses double and triple slashes.
-Slashes are sanitized to double slashes here."
+  "Sanitize slashes to double-slashes in URI.
+Emacsclient compresses double and triple slashes."
   (when (string-match "^\\([a-z]+\\):/" uri)
     (let* ((splitparts (split-string uri "/+")))
       (setq uri (concat (car splitparts) "//" (mapconcat 'identity (cdr 
splitparts) "/")))))
   uri)
 
 (defun org-protocol-split-data (data &optional unhexify separator)
-  "Split what an org-protocol handler function gets as only argument.
-DATA is that one argument.  DATA is split at each occurrence of
-SEPARATOR (regexp).  If no SEPARATOR is specified or SEPARATOR is
-nil, assume \"/+\".  The results of that splitting are returned
-as a list.  If UNHEXIFY is non-nil, hex-decode each split part.
-If UNHEXIFY is a function, use that function to decode each split
-part."
+  "Split the DATA argument for an org-protocol handler function.
+If UNHEXIFY is non-nil, hex-decode each split part.  If UNHEXIFY
+is a function, use that function to decode each split part.  The
+string is split at each occurrence of SEPARATOR (regexp).  If no
+SEPARATOR is specified or SEPARATOR is nil, assume \"/+\".  The
+results of that splitting are returned as a list."
   (let* ((sep (or separator "/+\\|\\?"))
          (split-parts (split-string data sep)))
     (if unhexify
@@ -302,23 +297,25 @@ part."
       split-parts)))
 
 (defun org-protocol-flatten-greedy (param-list &optional strip-path 
replacement)
-  "Greedy handlers might receive a list like this from emacsclient:
- ((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\"))
-where \"/dir/\" is the absolute path to emacsclients working directory.  This
+  "Transform PARAM-LIST into a flat list for greedy handlers.
+
+Greedy handlers might receive a list like this from emacsclient:
+\((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\"))
+where \"/dir/\" is the absolute path to emacsclient's working directory.  This
 function transforms it into a flat list using `org-protocol-flatten' and
 transforms the elements of that list as follows:
 
-If strip-path is non-nil, remove the \"/dir/\" prefix from all members of
+If STRIP-PATH is non-nil, remove the \"/dir/\" prefix from all members of
 param-list.
 
-If replacement is string, replace the \"/dir/\" prefix with it.
+If REPLACEMENT is string, replace the \"/dir/\" prefix with it.
 
 The first parameter, the one that contains the protocols, is always changed.
 Everything up to the end of the protocols is stripped.
 
 Note, that this function will always behave as if
 `org-protocol-reverse-list-of-files' was set to t and the returned list will
-reflect that.  I.e. emacsclients first parameter will be the first one in the
+reflect that.  emacsclient's first parameter will be the first one in the
 returned list."
   (let* ((l (org-protocol-flatten (if org-protocol-reverse-list-of-files
                                      param-list
@@ -345,50 +342,106 @@ returned list."
          ret)
       l)))
 
-(defun org-protocol-flatten (l)
-  "Greedy handlers might receive a list like this from emacsclient:
- ((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\"))
+(defun org-protocol-flatten (list)
+  "Transform LIST into a flat list.
+
+Greedy handlers might receive a list like this from emacsclient:
+\((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\"))
 where \"/dir/\" is the absolute path to emacsclients working directory.
 This function transforms it into a flat list."
-  (if (null l) ()
-    (if (listp l)
-       (append (org-protocol-flatten (car l)) (org-protocol-flatten (cdr l)))
-      (list l))))
-
+  (if (null list) ()
+    (if (listp list)
+       (append (org-protocol-flatten (car list)) (org-protocol-flatten (cdr 
list)))
+      (list list))))
+
+(defun org-protocol-parse-parameters (info &optional new-style default-order)
+  "Return a property list of parameters from INFO.
+If NEW-STYLE is non-nil, treat INFO as a query string (ex:
+url=URL&title=TITLE).  If old-style links are used (ex:
+org-protocol://store-link/url/title), assign them to attributes
+following DEFAULT-ORDER.
+
+If no DEFAULT-ORDER is specified, return the list of values.
+
+If INFO is already a property list, return it unchanged."
+  (if (listp info)
+      info
+    (if new-style
+       (let ((data (org-protocol-convert-query-to-plist info))
+             result)
+         (while data
+           (setq result
+                 (append
+                  result
+                  (list
+                   (pop data)
+                   (org-link-unescape (pop data))))))
+         result)
+      (let ((data (org-protocol-split-data info t 
org-protocol-data-separator)))
+       (if default-order
+           (org-protocol-assign-parameters data default-order)
+         data)))))
+
+(defun org-protocol-assign-parameters (data default-order)
+  "Return a property list of parameters from DATA.
+Key names are taken from DEFAULT-ORDER, which should be a list of
+symbols.  If DEFAULT-ORDER is shorter than the number of values
+specified, the rest of the values are treated as :key value pairs."
+  (let (result)
+    (while default-order
+      (setq result
+           (append result
+                   (list (pop default-order)
+                         (pop data)))))
+    (while data
+      (setq result
+           (append result
+                   (list (intern (concat ":" (pop data)))
+                         (pop data)))))
+    result))
 
 ;;; Standard protocol handlers:
 
 (defun org-protocol-store-link (fname)
-  "Process an org-protocol://store-link:// style url.
+  "Process an org-protocol://store-link style url.
 Additionally store a browser URL as an org link.  Also pushes the
 link's URL to the `kill-ring'.
 
+Parameters: url, title (optional), body (optional)
+
+Old-style links such as org-protocol://store-link://URL/TITLE are
+also recognized.
+
 The location for a browser's bookmark has to look like this:
 
-  javascript:location.href=\\='org-protocol://store-link://\\='+ \\
-        encodeURIComponent(location.href)
-        encodeURIComponent(document.title)+\\='/\\='+ \\
+  javascript:location.href = \\
+      \\='org-protocol://store-link?url=\\=' + \\
+      encodeURIComponent(location.href) + \\='&title=\\=' + \\
+      encodeURIComponent(document.title);
 
-Don't use `escape()'! Use `encodeURIComponent()' instead.  The title of the 
page
-could contain slashes and the location definitely will.
+Don't use `escape()'!  Use `encodeURIComponent()' instead.  The
+title of the page could contain slashes and the location
+definitely will.
 
 The sub-protocol used to reach this function is set in
-`org-protocol-protocol-alist'."
-  (let* ((splitparts (org-protocol-split-data fname t 
org-protocol-data-separator))
-         (uri (org-protocol-sanitize-uri (car splitparts)))
-         (title (cadr splitparts))
-         orglink)
-    (if (boundp 'org-stored-links)
-       (setq org-stored-links (cons (list uri title) org-stored-links)))
+`org-protocol-protocol-alist'.
+
+FNAME should be a property list.  If not, an old-style link of the
+form URL/TITLE can also be used."
+  (let* ((splitparts (org-protocol-parse-parameters fname nil '(:url :title)))
+         (uri (org-protocol-sanitize-uri (plist-get splitparts :url)))
+         (title (plist-get splitparts :title)))
+    (when (boundp 'org-stored-links)
+      (push (list uri title) org-stored-links))
     (kill-new uri)
     (message "`%s' to insert new org-link, `%s' to insert `%s'"
-             (substitute-command-keys"\\[org-insert-link]")
-             (substitute-command-keys"\\[yank]")
+             (substitute-command-keys "`\\[org-insert-link]'")
+             (substitute-command-keys "`\\[yank]'")
              uri))
   nil)
 
 (defun org-protocol-capture (info)
-  "Process an org-protocol://capture:// style url.
+  "Process an org-protocol://capture style url with INFO.
 
 The sub-protocol used to reach this function is set in
 `org-protocol-protocol-alist'.
@@ -396,16 +449,16 @@ The sub-protocol used to reach this function is set in
 This function detects an URL, title and optional text, separated
 by `/'.  The location for a browser's bookmark looks like this:
 
-  javascript:location.href=\\='org-protocol://capture://\\='+ \\
-        encodeURIComponent(location.href)+\\='/\\=' \\
-        encodeURIComponent(document.title)+\\='/\\='+ \\
+  javascript:location.href = \\='org-protocol://capture?url=\\='+ \\
+        encodeURIComponent(location.href) + \\='&title=\\=' \\
+        encodeURIComponent(document.title) + \\='&body=\\=' + \\
         encodeURIComponent(window.getSelection())
 
 By default, it uses the character `org-protocol-default-template-key',
 which should be associated with a template in `org-capture-templates'.
-But you may prepend the encoded URL with a character and a slash like so:
+You may specify the template with a template= query parameter, like this:
 
-  javascript:location.href=\\='org-protocol://capture://b/\\='+ ...
+  javascript:location.href = \\='org-protocol://capture?template=b\\='+ ...
 
 Now template ?b will be used."
   (if (and (boundp 'org-stored-links)
@@ -414,7 +467,7 @@ Now template ?b will be used."
   nil)
 
 (defun org-protocol-convert-query-to-plist (query)
-  "Convert query string that is part of url to property list."
+  "Convert QUERY key=value pairs in the URL to a property list."
   (if query
       (apply 'append (mapcar (lambda (x)
                               (let ((c (split-string x "=")))
@@ -422,45 +475,52 @@ Now template ?b will be used."
                             (split-string query "&")))))
 
 (defun org-protocol-do-capture (info)
-  "Support `org-capture'."
-  (let* ((parts (org-protocol-split-data info t org-protocol-data-separator))
-        (template (or (and (>= 2 (length (car parts))) (pop parts))
+  "Perform the actual capture based on INFO."
+  (let* ((temp-parts (org-protocol-parse-parameters info))
+        (parts
+         (cond
+          ((and (listp info) (symbolp (car info))) info)
+          ((= (length (car temp-parts)) 1) ;; First parameter is exactly one 
character long
+           (org-protocol-assign-parameters temp-parts '(:template :url :title 
:body)))
+          (t
+           (org-protocol-assign-parameters temp-parts '(:url :title :body)))))
+        (template (or (plist-get parts :template)
                       org-protocol-default-template-key))
-        (url (org-protocol-sanitize-uri (car parts)))
-        (type (if (string-match "^\\([a-z]+\\):" url)
-                  (match-string 1 url)))
-        (title (or (cadr parts) ""))
-        (region (or (caddr parts) ""))
-        (orglink (org-make-link-string
-                  url (if (string-match "[^[:space:]]" title) title url)))
-        (query (or (org-protocol-convert-query-to-plist (cadddr parts)) ""))
+        (url (and (plist-get parts :url) (org-protocol-sanitize-uri (plist-get 
parts :url))))
+        (type (and url (if (string-match "^\\([a-z]+\\):" url)
+                           (match-string 1 url))))
+        (title (or (plist-get parts :title) ""))
+        (region (or (plist-get parts :body) ""))
+        (orglink (if url
+                     (org-make-link-string
+                      url (if (string-match "[^[:space:]]" title) title url))
+                   title))
         (org-capture-link-is-already-stored t)) ;; avoid call to org-store-link
     (setq org-stored-links
          (cons (list url title) org-stored-links))
-    (kill-new orglink)
     (org-store-link-props :type type
                          :link url
                          :description title
                          :annotation orglink
                          :initial region
-                         :query query)
+                         :query parts)
     (raise-frame)
     (funcall 'org-capture nil template)))
 
 (defun org-protocol-open-source (fname)
-  "Process an org-protocol://open-source:// style url.
+  "Process an org-protocol://open-source?url= style URL with FNAME.
 
 Change a filename by mapping URLs to local filenames as set
 in `org-protocol-project-alist'.
 
 The location for a browser's bookmark should look like this:
 
-  javascript:location.href=\\='org-protocol://open-source://\\='+ \\
+  javascript:location.href = \\='org-protocol://open-source?url=\\=' + \\
         encodeURIComponent(location.href)"
   ;; As we enter this function for a match on our protocol, the return value
   ;; defaults to nil.
   (let ((result nil)
-        (f (org-link-unescape fname)))
+        (f (plist-get (org-protocol-parse-parameters fname nil '(:url)) :url)))
     (catch 'result
       (dolist (prolist org-protocol-project-alist)
         (let* ((base-url (plist-get (cdr prolist) :base-url))
@@ -490,13 +550,12 @@ The location for a browser's bookmark should look like 
this:
                (let ((rewrites (plist-get (cdr prolist) :rewrites)))
                  (when rewrites
                    (message "Rewrites found: %S" rewrites)
-                   (mapc
-                    (lambda (rewrite)
-                      "Try to match a rewritten URL and map it to a real file."
-                      ;; Compare redirects without suffix:
-                      (if (string-match (car rewrite) f2)
-                          (throw 'result (concat wdir (cdr rewrite)))))
-                    rewrites))))
+                   (dolist (rewrite rewrites)
+                     ;; Try to match a rewritten URL and map it to
+                     ;; a real file.  Compare redirects without
+                     ;; suffix.
+                     (when (string-match-p (car rewrite) f2)
+                       (throw 'result (concat wdir (cdr rewrite))))))))
              ;; -- end of redirects --
 
               (if (file-readable-p the-file)
@@ -509,44 +568,63 @@ The location for a browser's bookmark should look like 
this:
 
 ;;; Core functions:
 
-(defun org-protocol-check-filename-for-protocol (fname restoffiles client)
-  "Detect if `org-protocol-the-protocol' and a known sub-protocol is used in 
fname.
+(defun org-protocol-check-filename-for-protocol (fname restoffiles _client)
+  "Check if `org-protocol-the-protocol' and a valid protocol are used in FNAME.
 Sub-protocols are registered in `org-protocol-protocol-alist' and
-`org-protocol-protocol-alist-default'.
-This is, how the matching is done:
+`org-protocol-protocol-alist-default'.  This is how the matching is done:
 
-  (string-match \"protocol:/+sub-protocol:/+\" ...)
+  (string-match \"protocol:/+sub-protocol\\\\(://\\\\|\\\\?\\\\)\" ...)
 
 protocol and sub-protocol are regexp-quoted.
 
-If a matching protocol is found, the protocol is stripped from fname and the
-result is passed to the protocols function as the only parameter.  If the
-function returns nil, the filename is removed from the list of filenames
-passed from emacsclient to the server.
-If the function returns a non nil value, that value is passed to the server
-as filename."
+Old-style links such as \"protocol://sub-protocol://param1/param2\" are
+also recognized.
+
+If a matching protocol is found, the protocol is stripped from
+fname and the result is passed to the protocol function as the
+first parameter.  The second parameter will be non-nil if FNAME
+uses key=val&key2=val2-type arguments, or nil if FNAME uses
+val/val2-type arguments.  If the function returns nil, the
+filename is removed from the list of filenames passed from
+emacsclient to the server.  If the function returns a non-nil
+value, that value is passed to the server as filename.
+
+If the handler function is greedy, RESTOFFILES will also be passed to it.
+
+CLIENT is ignored."
   (let ((sub-protocols (append org-protocol-protocol-alist
                               org-protocol-protocol-alist-default)))
     (catch 'fname
-      (let ((the-protocol (concat (regexp-quote org-protocol-the-protocol) 
":/+")))
+      (let ((the-protocol (concat (regexp-quote org-protocol-the-protocol)
+                                 ":/+")))
         (when (string-match the-protocol fname)
           (dolist (prolist sub-protocols)
-            (let ((proto (concat the-protocol
-                                (regexp-quote (plist-get (cdr prolist) 
:protocol)) ":/+")))
+            (let ((proto
+                  (concat the-protocol
+                          (regexp-quote (plist-get (cdr prolist) :protocol))
+                          "\\(:/+\\|\\?\\)")))
               (when (string-match proto fname)
                 (let* ((func (plist-get (cdr prolist) :function))
                        (greedy (plist-get (cdr prolist) :greedy))
                        (split (split-string fname proto))
-                       (result (if greedy restoffiles (cadr split))))
+                       (result (if greedy restoffiles (cadr split)))
+                      (new-style (string= (match-string 1 fname) "?")))
                   (when (plist-get (cdr prolist) :kill-client)
                    (message "Greedy org-protocol handler.  Killing client.")
                    (server-edit))
                   (when (fboundp func)
                     (unless greedy
-                      (throw 'fname (funcall func result)))
-                    (funcall func result)
+                      (throw 'fname
+                            (if new-style
+                                (funcall func (org-protocol-parse-parameters
+                                               result new-style))
+                              (warn "Please update your Org Protocol handler \
+to deal with new-style links.")
+                              (funcall func result))))
+                   ;; Greedy protocol handlers are responsible for
+                   ;; parsing their own filenames.
+                   (funcall func result)
                     (throw 'fname t))))))))
-      ;; (message "fname: %s" fname)
       fname)))
 
 (defadvice server-visit-files (before org-protocol-detect-protocol-server 
activate)
@@ -572,16 +650,18 @@ as filename."
 ;;; Org specific functions:
 
 (defun org-protocol-create-for-org ()
-  "Create a org-protocol project for the current file's Org-mode project.
+  "Create a Org protocol project for the current file's project.
 The visited file needs to be part of a publishing project in
 `org-publish-project-alist' for this to work.  The function
 delegates most of the work to `org-protocol-create'."
   (interactive)
-  (require 'org-publish)
+  (require 'ox-publish)
   (let ((all (or (org-publish-get-project-from-filename buffer-file-name))))
     (if all (org-protocol-create (cdr all))
-      (message "Not in an org-project.  Did mean %s?"
-               (substitute-command-keys"\\[org-protocol-create]")))))
+      (message "%s"
+              (substitute-command-keys
+               "Not in an Org project.  \
+Did you mean `\\[org-protocol-create]'?")))))
 
 (defun org-protocol-create (&optional project-plist)
   "Create a new org-protocol project interactively.
@@ -600,19 +680,18 @@ the cdr of an element in `org-publish-project-alist', 
reuse
         (working-suffix (if (plist-get project-plist :base-extension)
                             (concat "." (plist-get project-plist 
:base-extension))
                           ".org"))
-        (worglet-buffer nil)
         (insert-default-directory t)
         (minibuffer-allow-text-properties nil))
 
     (setq base-url (read-string "Base URL of published content: " base-url nil 
base-url t))
-    (if (not (string-match "\\/$" base-url))
-        (setq base-url (concat base-url "/")))
+    (or (string-suffix-p "/" base-url)
+       (setq base-url (concat base-url "/")))
 
     (setq working-dir
           (expand-file-name
            (read-directory-name "Local working directory: " working-dir 
working-dir t)))
-    (if (not (string-match "\\/$" working-dir))
-        (setq working-dir (concat working-dir "/")))
+    (or (string-suffix-p "/" working-dir)
+       (setq working-dir (concat working-dir "/")))
 
     (setq strip-suffix
           (read-string
diff --git a/lisp/org/org-rmail.el b/lisp/org/org-rmail.el
index 80bfce9..31c59a1 100644
--- a/lisp/org/org-rmail.el
+++ b/lisp/org/org-rmail.el
@@ -1,4 +1,4 @@
-;;; org-rmail.el --- Support for links to Rmail messages from within Org-mode
+;;; org-rmail.el --- Support for Links to Rmail Messages -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,9 +24,9 @@
 ;;
 ;;; Commentary:
 
-;; This file implements links to Rmail messages from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
-;; configure the variable `org-modules'.
+;; This file implements links to Rmail messages from within Org mode.
+;; Org mode loads this module by default - if this is not what you
+;; want, configure the variable `org-modules'.
 
 ;;; Code:
 
@@ -36,13 +36,14 @@
 (declare-function rmail-show-message  "rmail" (&optional n no-summary))
 (declare-function rmail-what-message  "rmail" (&optional pos))
 (declare-function rmail-toggle-header "rmail" (&optional arg))
+(declare-function rmail               "rmail" (&optional file-name-arg))
 (declare-function rmail-widen         "rmail" ())
 (defvar rmail-current-message)  ; From rmail.el
 (defvar rmail-header-style)     ; From rmail.el
+(defvar rmail-file-name)        ; From rmail.el
 
 ;; Install the link type
-(org-add-link-type "rmail" 'org-rmail-open)
-(add-hook 'org-store-link-functions 'org-rmail-store-link)
+(org-link-set-parameters "rmail" :follow #'org-rmail-open :store 
#'org-rmail-store-link)
 
 ;; Implementation
 (defun org-rmail-store-link ()
@@ -63,20 +64,11 @@
               (to (mail-fetch-field "to"))
               (subject (mail-fetch-field "subject"))
               (date (mail-fetch-field "date"))
-              (date-ts (and date (format-time-string
-                                  (org-time-stamp-format t)
-                                  (date-to-time date))))
-              (date-ts-ia (and date (format-time-string
-                                     (org-time-stamp-format t t)
-                                     (date-to-time date))))
               desc link)
          (org-store-link-props
-          :type "rmail" :from from :to to
+          :type "rmail" :from from :to to :date date
           :subject subject :message-id message-id)
-         (when date
-           (org-add-link-props :date date :date-timestamp date-ts
-                               :date-timestamp-inactive date-ts-ia))
-         (setq message-id (org-remove-angle-brackets message-id))
+         (setq message-id (org-unbracket-string "<" ">" message-id))
          (setq desc (org-email-link-description))
          (setq link (concat "rmail:" folder "#" message-id))
          (org-add-link-props :link link :description desc)
diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el
index 4eb8a53..0e04d4b 100644
--- a/lisp/org/org-src.el
+++ b/lisp/org/org-src.el
@@ -1,4 +1,4 @@
-;;; org-src.el --- Source code examples in Org
+;;; org-src.el --- Source code examples in Org       -*- lexical-binding: t; 
-*-
 ;;
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 ;;
@@ -26,43 +26,33 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the code dealing with source code examples in Org-mode.
+;; This file contains the code dealing with source code examples in
+;; Org mode.
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'org-macs)
 (require 'org-compat)
 (require 'ob-keys)
 (require 'ob-comint)
-(eval-when-compile
-  (require 'cl))
 
+(declare-function org-base-buffer "org" (buffer))
 (declare-function org-do-remove-indentation "org" (&optional n))
-(declare-function org-at-table.el-p "org" ())
-(declare-function org-in-src-block-p "org" (&optional inside))
-(declare-function org-in-block-p "org" (names))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-class "org-element" (datum &optional parent))
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-lineage "org-element"
+                 (blob &optional types with-self))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-footnote-goto-definition "org-footnote"
+                 (label &optional location))
 (declare-function org-get-indentation "org" (&optional line))
 (declare-function org-switch-to-buffer-other-window "org" (&rest args))
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
-(declare-function org-base-buffer "org" (buffer))
+(declare-function org-trim "org" (s &optional keep-lead))
 
-(defcustom org-edit-src-region-extra nil
-  "Additional regexps to identify regions for editing with `org-edit-src-code'.
-For examples see the function `org-edit-src-find-region-and-lang'.
-The regular expression identifying the begin marker should end with a newline,
-and the regexp marking the end line should start with a newline, to make sure
-there are kept outside the narrowed region."
-  :group 'org-edit-structure
-  :type '(repeat
-         (list
-          (regexp :tag "begin regexp")
-          (regexp :tag "end regexp")
-          (choice :tag "language"
-                  (string :tag "specify")
-                  (integer :tag "from match group")
-                  (const :tag "from `lang' element")
-                  (const :tag "from `style' element")))))
+(defvar org-inhibit-startup)
 
 (defcustom org-edit-src-turn-on-auto-save nil
   "Non-nil means turn `auto-save-mode' on when editing a source block.
@@ -117,28 +107,29 @@ These are the regions where each line starts with a 
colon."
 
 (defcustom org-src-preserve-indentation nil
   "If non-nil preserve leading whitespace characters on export.
+\\<org-mode-map>
 If non-nil leading whitespace characters in source code blocks
 are preserved on export, and when switching between the org
-buffer and the language mode edit buffer.  If this variable is nil
-then, after editing with \\[org-edit-src-code], the
-minimum (across-lines) number of leading whitespace characters
-are removed from all lines, and the code block is uniformly
-indented according to the value of `org-edit-src-content-indentation'."
+buffer and the language mode edit buffer.
+
+When this variable is nil, after editing with `\\[org-edit-src-code]',
+the minimum (across-lines) number of leading whitespace characters
+are removed from all lines, and the code block is uniformly indented
+according to the value of `org-edit-src-content-indentation'."
   :group 'org-edit-structure
   :type 'boolean)
 
 (defcustom org-edit-src-content-indentation 2
   "Indentation for the content of a source code block.
+
 This should be the number of spaces added to the indentation of the #+begin
 line in order to compute the indentation of the block content after
-editing it with \\[org-edit-src-code].  Has no effect if
-`org-src-preserve-indentation' is non-nil."
+editing it with `\\[org-edit-src-code]'.
+
+It has no effect if `org-src-preserve-indentation' is non-nil."
   :group 'org-edit-structure
   :type 'integer)
 
-(defvar org-src-strip-leading-and-trailing-blank-lines nil
-  "If non-nil, blank lines are removed when exiting the code edit buffer.")
-
 (defcustom org-edit-src-persistent-message t
   "Non-nil means show persistent exit help message while editing src examples.
 The message is shown in the header-line, which will be created in the
@@ -146,6 +137,17 @@ first line of the window showing the editing buffer."
   :group 'org-edit-structure
   :type 'boolean)
 
+(defcustom org-src-ask-before-returning-to-edit-buffer t
+  "Non-nil means ask before switching to an existing edit buffer.
+If nil, when `org-edit-src-code' is used on a block that already
+has an active edit buffer, it will switch to that edit buffer
+immediately; otherwise it will ask whether you want to return to
+the existing edit buffer."
+  :group 'org-edit-structure
+  :version "24.4"
+  :package-version '(Org . "8.0")
+  :type 'boolean)
+
 (defcustom org-src-window-setup 'reorganize-frame
   "How the source code edit buffer should be displayed.
 Possible values for this option are:
@@ -167,10 +169,10 @@ other-frame       Use `switch-to-buffer-other-frame' to 
display edit buffer.
 
 (defvar org-src-mode-hook nil
   "Hook run after Org switched a source code snippet to its Emacs mode.
-This hook will run
-
-- when editing a source code snippet with `\\[org-src-mode-map]'.
-- When formatting a source code snippet for export with htmlize.
+\\<org-mode-map>
+This hook will run:
+- when editing a source code snippet with `\\[org-edit-special]'
+- when formatting a source code snippet for export with htmlize.
 
 You may want to use this hook for example to turn off `outline-minor-mode'
 or similar things which you want to have when editing a source code file,
@@ -180,7 +182,7 @@ but which mess up the display of a snippet in Org exported 
files.")
   '(("ocaml" . tuareg) ("elisp" . emacs-lisp) ("ditaa" . artist)
     ("asymptote" . asy) ("dot" . fundamental) ("sqlite" . sql)
     ("calc" . fundamental) ("C" . c) ("cpp" . c++) ("C++" . c++)
-    ("screen" . shell-script))
+    ("screen" . shell-script) ("shell" . sh) ("bash" . sh))
   "Alist mapping languages to their major mode.
 The key is the language name, the value is the string that should
 be inserted as the name of the major mode.  For many languages this is
@@ -194,451 +196,383 @@ For example, there is no ocaml-mode in Emacs, but the 
mode to use is
           (string "Language name")
           (symbol "Major mode"))))
 
-;;; Editing source examples
+(defcustom org-src-block-faces nil
+  "Alist of faces to be used for source-block.
+Each element is a cell of the format
 
-(defvar org-src-mode-map (make-sparse-keymap))
-(define-key org-src-mode-map "\C-c'" 'org-edit-src-exit)
-(define-key org-src-mode-map "\C-c\C-k" 'org-edit-src-abort)
-(define-key org-src-mode-map "\C-x\C-s" 'org-edit-src-save)
+     (\"language\" FACE)
 
-(defvar org-edit-src-force-single-line nil)
-(defvar org-edit-src-from-org-mode nil)
-(defvar org-edit-src-allow-write-back-p t)
-(defvar org-edit-src-picture nil)
-(defvar org-edit-src-beg-marker nil)
-(defvar org-edit-src-end-marker nil)
-(defvar org-edit-src-overlay nil)
-(defvar org-edit-src-block-indentation nil)
-(defvar org-edit-src-saved-temp-window-config nil)
+Where FACE is either a defined face or an anonymous face.
 
-(defcustom org-src-ask-before-returning-to-edit-buffer t
-  "If nil, when org-edit-src code is used on a block that already
-has an active edit buffer, it will switch to that edit buffer
-immediately; otherwise it will ask whether you want to return to
-the existing edit buffer."
-  :group 'org-edit-structure
-  :version "24.4"
-  :package-version '(Org . "8.0")
-  :type 'boolean)
-
-(defvar org-src-babel-info nil)
+For instance, the following value would color the background of
+emacs-lisp source blocks and python source blocks in purple and
+green, respectability.
 
-(define-minor-mode org-src-mode
-  "Minor mode for language major mode buffers generated by org.
-This minor mode is turned on in two situations:
-- when editing a source code snippet with `\\[org-src-mode-map]'.
-- When formatting a source code snippet for export with htmlize.
-There is a mode hook, and keybindings for `org-edit-src-exit' and
-`org-edit-src-save'")
-
-(defvar org-edit-src-code-timer nil)
-(defvar org-inhibit-startup)
+    \\='((\"emacs-lisp\" (:background \"#EEE2FF\"))
+      (\"python\" (:background \"#e5ffb8\")))"
+  :group 'org-edit-structure
+  :type '(repeat (list (string :tag "language")
+                       (choice
+                        (face :tag "Face")
+                        (sexp :tag "Anonymous face"))))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
 
-(defun org-edit-src-code (&optional context code edit-buffer-name)
-  "Edit the source CODE block at point.
-The code is copied to a separate buffer and the appropriate mode
-is turned on.  When done, exit with \\[org-edit-src-exit].  This will
-remove the original code in the Org buffer, and replace it with the
-edited version.  An optional argument CONTEXT is used by \\[org-edit-src-save]
-when calling this function.  See `org-src-window-setup' to configure
-the display of windows containing the Org buffer and the code buffer."
-  (interactive)
-  (if (not (or (org-in-block-p '("src" "example" "latex" "html"))
-              (org-at-table.el-p)))
-      (user-error "Not in a source code or example block")
-    (unless (eq context 'save)
-      (setq org-edit-src-saved-temp-window-config 
(current-window-configuration)))
-    (let* ((mark (and (org-region-active-p) (mark)))
-          (case-fold-search t)
-          (info
-           ;; If the src region consists in no lines, we insert a blank
-           ;; line.
-           (let* ((temp (org-edit-src-find-region-and-lang))
-                  (beg (nth 0 temp))
-                  (end (nth 1 temp)))
-             (if (>= end beg) temp
-               (goto-char beg)
-               (insert "\n")
-               (org-edit-src-find-region-and-lang))))
-          (full-info (org-babel-get-src-block-info 'light))
-          (org-mode-p (derived-mode-p 'org-mode)) ;; derived-mode-p is 
reflexive
-          (beg (make-marker))
-          ;; Move marker with inserted text for case when src block is
-          ;; just one empty line, i.e. beg == end.
-          (end (copy-marker (make-marker) t))
-          (allow-write-back-p (null code))
-          block-nindent total-nindent ovl lang lang-f single buffer msg
-          begline markline markcol line col transmitted-variables)
-      (setq beg (move-marker beg (nth 0 info))
-           end (move-marker end (nth 1 info))
-           msg (if allow-write-back-p
-                    "Edit, then exit with C-c ' (C-c and single quote) -- C-c 
C-k to abort"
-                 "Exit with C-c ' (C-c and single quote) -- C-c C-k to abort")
-           code (or code (buffer-substring-no-properties beg end))
-           lang (or (cdr (assoc (nth 2 info) org-src-lang-modes))
-                    (nth 2 info))
-           lang (if (symbolp lang) (symbol-name lang) lang)
-           single (nth 3 info)
-           block-nindent (nth 5 info)
-           lang-f (intern (concat lang "-mode"))
-           begline (save-excursion (goto-char beg) (org-current-line))
-           transmitted-variables
-           `((org-edit-src-content-indentation
-              ,org-edit-src-content-indentation)
-             (org-edit-src-force-single-line ,single)
-             (org-edit-src-from-org-mode ,org-mode-p)
-             (org-edit-src-allow-write-back-p ,allow-write-back-p)
-             (org-src-preserve-indentation ,org-src-preserve-indentation)
-             (org-src-babel-info ,(org-babel-get-src-block-info 'light))
-             (org-coderef-label-format
-              ,(or (nth 4 info) org-coderef-label-format))
-             (org-edit-src-beg-marker ,beg)
-             (org-edit-src-end-marker ,end)
-             (org-edit-src-block-indentation ,block-nindent)))
-      (if (and mark (>= mark beg) (<= mark (1+ end)))
-         (save-excursion (goto-char (min mark end))
-                         (setq markline (org-current-line)
-                               markcol (current-column))))
-      (if (equal lang-f 'table.el-mode)
-         (setq lang-f (lambda ()
-                        (text-mode)
-                        (if (org-bound-and-true-p flyspell-mode)
-                            (flyspell-mode -1))
-                        (table-recognize)
-                        (org-set-local 'org-edit-src-content-indentation 0))))
-      (unless (functionp lang-f)
-       (error "No such language mode: %s" lang-f))
-      (save-excursion
-       (if (> (point) end) (goto-char end))
-       (setq line (org-current-line)
-             col (current-column)))
-      (if (and (setq buffer (org-edit-src-find-buffer beg end))
-              (or (eq context 'save)
-                  (if org-src-ask-before-returning-to-edit-buffer
-                      (y-or-n-p "Return to existing edit buffer ([n] will 
revert changes)? ") t)))
-         (org-src-switch-to-buffer buffer 'return)
-       (when buffer
-         (with-current-buffer buffer
-           (if (boundp 'org-edit-src-overlay)
-               (delete-overlay org-edit-src-overlay)))
-         (kill-buffer buffer))
-       (setq buffer (generate-new-buffer
-                     (or edit-buffer-name
-                         (org-src-construct-edit-buffer-name (buffer-name) 
lang))))
-       (setq ovl (make-overlay beg end))
-       (overlay-put ovl 'edit-buffer buffer)
-       (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer 
editing this segment")
-       (overlay-put ovl 'face 'secondary-selection)
-       (overlay-put ovl
-                    'keymap
-                    (let ((map (make-sparse-keymap)))
-                      (define-key map [mouse-1] 'org-edit-src-continue)
-                      map))
-       (overlay-put ovl :read-only "Leave me alone")
-       (setq transmitted-variables
-             (append transmitted-variables `((org-edit-src-overlay ,ovl))))
-       (org-src-switch-to-buffer buffer 'edit)
-       (if (eq single 'macro-definition)
-           (setq code (replace-regexp-in-string "\\\\n" "\n" code t t)))
-       (insert code)
-       (remove-text-properties (point-min) (point-max)
-                               '(display nil invisible nil intangible nil))
-       (unless (cadr (assq 'org-src-preserve-indentation 
transmitted-variables))
-         (setq total-nindent (or (org-do-remove-indentation) 0)))
-       (let ((org-inhibit-startup t))
-         (condition-case e
-             (funcall lang-f)
-           (error
-            (message "Language mode `%s' fails with: %S" lang-f (nth 1 e)))))
-       (dolist (pair transmitted-variables)
-         (org-set-local (car pair) (cadr pair)))
-       ;; Remove protecting commas from visible part of buffer.
-       (org-unescape-code-in-region (point-min) (point-max))
-       (when markline
-         (org-goto-line (1+ (- markline begline)))
-         (org-move-to-column
-          (if org-src-preserve-indentation markcol
-            (max 0 (- markcol total-nindent))))
-         (push-mark (point) 'no-message t)
-         (setq deactivate-mark nil))
-       (org-goto-line (1+ (- line begline)))
-       (org-move-to-column
-        (if org-src-preserve-indentation col (max 0 (- col total-nindent))))
-       (org-src-mode)
-       (set-buffer-modified-p nil)
-       (setq buffer-file-name nil)
-       (when org-edit-src-turn-on-auto-save
-         (setq buffer-auto-save-file-name
-               (concat (make-temp-name "org-src-")
-                       (format-time-string "-%Y-%d-%m") ".txt")))
-       (and org-edit-src-persistent-message
-            (org-set-local 'header-line-format msg))
-       (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
-         (when (fboundp edit-prep-func)
-           (funcall edit-prep-func full-info)))
-       (or org-edit-src-code-timer
-           (zerop org-edit-src-auto-save-idle-delay)
-           (setq org-edit-src-code-timer
-                 (run-with-idle-timer
-                  org-edit-src-auto-save-idle-delay t
-                  (lambda ()
-                    (cond
-                     ((org-string-match-p "\\`\\*Org Src" (buffer-name))
-                      (when (buffer-modified-p) (org-edit-src-save)))
-                     ((not (org-some (lambda (b)
-                                       (org-string-match-p "\\`\\*Org Src"
-                                                           (buffer-name b)))
-                                     (buffer-list)))
-                      (cancel-timer org-edit-src-code-timer)
-                      (setq org-edit-src-code-timer nil))))))))
-      t)))
+(defcustom org-src-tab-acts-natively nil
+  "If non-nil, the effect of TAB in a code block is as if it were
+issued in the language major mode buffer."
+  :type 'boolean
+  :version "24.1"
+  :group 'org-babel)
 
-(defun org-edit-src-continue (e)
-  "Continue editing source blocks." ;; Fixme: be more accurate
-  (interactive "e")
-  (mouse-set-point e)
-  (let ((buf (get-char-property (point) 'edit-buffer)))
-    (if buf (org-src-switch-to-buffer buf 'continue)
-      (error "Something is wrong here"))))
 
-(defun org-src-switch-to-buffer (buffer context)
-  (case org-src-window-setup
-    ('current-window
-     (org-pop-to-buffer-same-window buffer))
-    ('other-window
-     (switch-to-buffer-other-window buffer))
-    ('other-frame
-     (case context
-       ('exit
-       (let ((frame (selected-frame)))
-         (switch-to-buffer-other-frame buffer)
-         (delete-frame frame)))
-       ('save
-       (kill-buffer (current-buffer))
-       (org-pop-to-buffer-same-window buffer))
-       (t
-       (switch-to-buffer-other-frame buffer))))
-    ('reorganize-frame
-     (if (eq context 'edit) (delete-other-windows))
-     (org-switch-to-buffer-other-window buffer)
-     (if (eq context 'exit) (delete-other-windows)))
-    ('switch-invisibly
-     (set-buffer buffer))
-    (t
-     (message "Invalid value %s for org-src-window-setup"
-             (symbol-name org-src-window-setup))
-     (org-pop-to-buffer-same-window buffer))))
-
-(defun org-src-construct-edit-buffer-name (org-buffer-name lang)
+
+;;; Internal functions and variables
+
+(defvar org-src--allow-write-back t)
+(defvar org-src--auto-save-timer nil)
+(defvar org-src--babel-info nil)
+(defvar org-src--beg-marker nil)
+(defvar org-src--block-indentation nil)
+(defvar org-src--end-marker nil)
+(defvar org-src--from-org-mode nil)
+(defvar org-src--overlay nil)
+(defvar org-src--preserve-indentation nil)
+(defvar org-src--remote nil)
+(defvar org-src--saved-temp-window-config nil)
+(defvar org-src--source-type nil
+  "Type of element being edited, as a symbol.")
+(defvar org-src--tab-width nil
+  "Contains `tab-width' value from Org source buffer.
+However, if `indent-tabs-mode' is nil in that buffer, its value
+is 0.")
+
+(defun org-src--construct-edit-buffer-name (org-buffer-name lang)
   "Construct the buffer name for a source editing buffer."
   (concat "*Org Src " org-buffer-name "[ " lang " ]*"))
 
-(defun org-src-edit-buffer-p (&optional buffer)
-  "Test whether BUFFER (or the current buffer if BUFFER is nil)
-is a source block editing buffer."
-  (let ((buffer (org-base-buffer (or buffer (current-buffer)))))
-    (and (buffer-name buffer)
-        (string-match "\\`*Org Src " (buffer-name buffer))
-        (local-variable-p 'org-edit-src-beg-marker buffer)
-        (local-variable-p 'org-edit-src-end-marker buffer))))
-
-(defun org-edit-src-find-buffer (beg end)
-  "Find a source editing buffer that is already editing the region BEG to END."
+(defun org-src--edit-buffer (beg end)
+  "Return buffer editing area between BEG and END.
+Return nil if there is no such buffer."
   (catch 'exit
-    (mapc
-     (lambda (b)
-       (with-current-buffer b
-        (if (and (string-match "\\`*Org Src " (buffer-name))
-                 (local-variable-p 'org-edit-src-beg-marker (current-buffer))
-                 (local-variable-p 'org-edit-src-end-marker (current-buffer))
-                 (equal beg org-edit-src-beg-marker)
-                 (equal end org-edit-src-end-marker))
-            (throw 'exit (current-buffer)))))
-     (buffer-list))
-    nil))
+    (dolist (b (buffer-list))
+      (with-current-buffer b
+       (and (org-src-edit-buffer-p)
+            (= beg org-src--beg-marker)
+            (eq (marker-buffer beg) (marker-buffer org-src--beg-marker))
+            (= end org-src--end-marker)
+            (eq (marker-buffer end) (marker-buffer org-src--end-marker))
+            (throw 'exit b))))))
+
+(defun org-src--source-buffer ()
+  "Return source buffer edited by current buffer."
+  (unless (org-src-edit-buffer-p) (error "Not in a source buffer"))
+  (or (marker-buffer org-src--beg-marker)
+      (error "No source buffer available for current editing session")))
+
+(defun org-src--get-lang-mode (lang)
+  "Return major mode that should be used for LANG.
+LANG is a string, and the returned major mode is a symbol."
+  (intern
+   (concat
+    (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
+      (if (symbolp l) (symbol-name l) l))
+    "-mode")))
 
-(defun org-edit-fixed-width-region ()
-  "Edit the fixed-width ascii drawing at point.
-This must be a region where each line starts with a colon followed by
-a space character.
-An new buffer is created and the fixed-width region is copied into it,
-and the buffer is switched into `artist-mode' for editing.  When done,
-exit with \\[org-edit-src-exit].  The edited text will then replace
-the fragment in the Org-mode buffer."
-  (interactive)
-  (let ((line (org-current-line))
-       (col (current-column))
-       (case-fold-search t)
-       (msg "Edit, then exit with C-c ' (C-c and single quote) -- C-c C-k to 
abort")
-       (org-mode-p (derived-mode-p 'org-mode))
-       (beg (make-marker))
-       (end (make-marker))
-       block-nindent ovl beg1 end1 code begline buffer)
-    (beginning-of-line 1)
-    (if (looking-at "[ \t]*[^:\n \t]")
-       nil
-      (if (looking-at "[ \t]*\\(\n\\|\\'\\)")
-         (setq beg1 (point) end1 beg1)
-       (save-excursion
-         (if (re-search-backward "^[ \t]*[^: \t]" nil 'move)
-             (setq beg1 (point-at-bol 2))
-           (setq beg1 (point))))
-       (save-excursion
-         (if (re-search-forward "^[ \t]*[^: \t]" nil 'move)
-             (setq end1 (1- (match-beginning 0)))
-           (setq end1 (point))))
-       (org-goto-line line))
-      (setq beg (move-marker beg beg1)
-           end (move-marker end end1)
-           code (buffer-substring-no-properties beg end)
-           begline (save-excursion (goto-char beg) (org-current-line)))
-      (if (and (setq buffer (org-edit-src-find-buffer beg end))
-              (y-or-n-p "Return to existing edit buffer ([n] will revert 
changes)? "))
-         (org-pop-to-buffer-same-window buffer)
-       (when buffer
-         (with-current-buffer buffer
-           (if (boundp 'org-edit-src-overlay)
-               (delete-overlay org-edit-src-overlay)))
-         (kill-buffer buffer))
-       (setq buffer (generate-new-buffer
-                     (org-src-construct-edit-buffer-name
-                      (buffer-name) "Fixed Width")))
-       (setq ovl (make-overlay beg end))
-       (overlay-put ovl 'face 'secondary-selection)
-       (overlay-put ovl 'edit-buffer buffer)
-       (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer 
editing this segment")
-       (overlay-put ovl 'face 'secondary-selection)
-       (overlay-put ovl
-                    'keymap
-                    (let ((map (make-sparse-keymap)))
-                      (define-key map [mouse-1] 'org-edit-src-continue)
-                      map))
-       (overlay-put ovl :read-only "Leave me alone")
-       (org-pop-to-buffer-same-window buffer)
-       (insert code)
+(defun org-src--coordinates (pos beg end)
+  "Return coordinates of POS relatively to BEG and END.
+POS, BEG and END are buffer positions.  Return value is either
+a cons cell (LINE . COLUMN) or symbol `end'.  See also
+`org-src--goto-coordinates'."
+  (if (>= pos end) 'end
+    (org-with-wide-buffer
+     (goto-char (max beg pos))
+     (cons (count-lines beg (line-beginning-position))
+          ;; Column is relative to the end of line to avoid problems of
+          ;; comma escaping or colons appended in front of the line.
+          (- (current-column)
+             (progn (end-of-line) (current-column)))))))
+
+(defun org-src--goto-coordinates (coord beg end)
+  "Move to coordinates COORD relatively to BEG and END.
+COORD are coordinates, as returned by `org-src--coordinates',
+which see.  BEG and END are buffer positions."
+  (goto-char
+   (if (eq coord 'end) (max (1- end) beg)
+     ;; If BEG happens to be located outside of the narrowed part of
+     ;; the buffer, widen it first.
+     (org-with-wide-buffer
+      (goto-char beg)
+      (forward-line (car coord))
+      (end-of-line)
+      (org-move-to-column (max (+ (current-column) (cdr coord)) 0))
+      (point)))))
+
+(defun org-src--contents-area (datum)
+  "Return contents boundaries of DATUM.
+DATUM is an element or object.  Return a list (BEG END CONTENTS)
+where BEG and END are buffer positions and CONTENTS is a string."
+  (let ((type (org-element-type datum)))
+    (org-with-wide-buffer
+     (cond
+      ((eq type 'footnote-definition)
+       (let* ((beg (progn
+                    (goto-char (org-element-property :post-affiliated datum))
+                    (search-forward "]")))
+             (end (or (org-element-property :contents-end datum) beg)))
+        (list beg end (buffer-substring-no-properties beg end))))
+      ((eq type 'inline-src-block)
+       (let ((beg (progn (goto-char (org-element-property :begin datum))
+                        (search-forward "{" (line-end-position) t)))
+            (end (progn (goto-char (org-element-property :end datum))
+                        (search-backward "}" (line-beginning-position) t))))
+        (list beg end (buffer-substring-no-properties beg end))))
+      ((org-element-property :contents-begin datum)
+       (let ((beg (org-element-property :contents-begin datum))
+            (end (org-element-property :contents-end datum)))
+        (list beg end (buffer-substring-no-properties beg end))))
+      ((memq type '(example-block export-block src-block))
+       (list (progn (goto-char (org-element-property :post-affiliated datum))
+                   (line-beginning-position 2))
+            (progn (goto-char (org-element-property :end datum))
+                   (skip-chars-backward " \r\t\n")
+                   (line-beginning-position 1))
+            (org-element-property :value datum)))
+      ((memq type '(fixed-width table))
+       (let ((beg (org-element-property :post-affiliated datum))
+            (end (progn (goto-char (org-element-property :end datum))
+                        (skip-chars-backward " \r\t\n")
+                        (line-beginning-position 2))))
+        (list beg
+              end
+              (if (eq type 'fixed-width) (org-element-property :value datum)
+                (buffer-substring-no-properties beg end)))))
+      (t (error "Unsupported element or object: %s" type))))))
+
+(defun org-src--make-source-overlay (beg end edit-buffer)
+  "Create overlay between BEG and END positions and return it.
+EDIT-BUFFER is the buffer currently editing area between BEG and
+END."
+  (let ((overlay (make-overlay beg end)))
+    (overlay-put overlay 'face 'secondary-selection)
+    (overlay-put overlay 'edit-buffer edit-buffer)
+    (overlay-put overlay 'help-echo
+                "Click with mouse-1 to switch to buffer editing this segment")
+    (overlay-put overlay 'face 'secondary-selection)
+    (overlay-put overlay 'keymap
+                (let ((map (make-sparse-keymap)))
+                  (define-key map [mouse-1] 'org-edit-src-continue)
+                  map))
+    (let ((read-only
+          (list
+           (lambda (&rest _)
+             (user-error
+              "Cannot modify an area being edited in a dedicated buffer")))))
+      (overlay-put overlay 'modification-hooks read-only)
+      (overlay-put overlay 'insert-in-front-hooks read-only)
+      (overlay-put overlay 'insert-behind-hooks read-only))
+    overlay))
+
+(defun org-src--remove-overlay ()
+  "Remove overlay from current source buffer."
+  (when (overlayp org-src--overlay) (delete-overlay org-src--overlay)))
+
+(defun org-src--on-datum-p (datum)
+  "Non-nil when point is on DATUM.
+DATUM is an element or an object.  Consider blank lines or white
+spaces after it as being outside."
+  (and (>= (point) (org-element-property :begin datum))
+       (<= (point)
+          (org-with-wide-buffer
+           (goto-char (org-element-property :end datum))
+           (skip-chars-backward " \r\t\n")
+           (if (eq (org-element-class datum) 'element)
+               (line-end-position)
+             (point))))))
+
+(defun org-src--contents-for-write-back ()
+  "Return buffer contents in a format appropriate for write back.
+Assume point is in the corresponding edit buffer."
+  (let ((indentation-offset
+        (if org-src--preserve-indentation 0
+          (+ (or org-src--block-indentation 0)
+             (if (memq org-src--source-type '(example-block src-block))
+                 org-edit-src-content-indentation
+               0))))
+       (use-tabs? (and (> org-src--tab-width 0) t))
+       (source-tab-width org-src--tab-width)
+       (contents (org-with-wide-buffer (buffer-string)))
+       (write-back org-src--allow-write-back))
+    (with-temp-buffer
+      ;; Reproduce indentation parameters from source buffer.
+      (setq-local indent-tabs-mode use-tabs?)
+      (when (> source-tab-width 0) (setq-local tab-width source-tab-width))
+      ;; Apply WRITE-BACK function on edit buffer contents.
+      (insert (org-no-properties contents))
+      (goto-char (point-min))
+      (when (functionp write-back) (save-excursion (funcall write-back)))
+      ;; Add INDENTATION-OFFSET to every non-empty line in buffer,
+      ;; unless indentation is meant to be preserved.
+      (when (> indentation-offset 0)
+       (while (not (eobp))
+         (skip-chars-forward " \t")
+         (unless (eolp)                ;ignore blank lines
+           (let ((i (current-column)))
+             (delete-region (line-beginning-position) (point))
+             (indent-to (+ i indentation-offset))))
+         (forward-line)))
+      (buffer-string))))
+
+(defun org-src--edit-element
+    (datum name &optional major write-back contents remote)
+  "Edit DATUM contents in a dedicated buffer NAME.
+
+MAJOR is the major mode used in the edit buffer.  A nil value is
+equivalent to `fundamental-mode'.
+
+When WRITE-BACK is non-nil, assume contents will replace original
+region.  Moreover, if it is a function, apply it in the edit
+buffer, from point min, before returning the contents.
+
+When CONTENTS is non-nil, display them in the edit buffer.
+Otherwise, show DATUM contents as specified by
+`org-src--contents-area'.
+
+When REMOTE is non-nil, do not try to preserve point or mark when
+moving from the edit area to the source.
+
+Leave point in edit buffer."
+  (setq org-src--saved-temp-window-config (current-window-configuration))
+  (let* ((area (org-src--contents-area datum))
+        (beg (copy-marker (nth 0 area)))
+        (end (copy-marker (nth 1 area) t))
+        (old-edit-buffer (org-src--edit-buffer beg end))
+        (contents (or contents (nth 2 area))))
+    (if (and old-edit-buffer
+            (or (not org-src-ask-before-returning-to-edit-buffer)
+                (y-or-n-p "Return to existing edit buffer ([n] will revert 
changes)? ")))
+       ;; Move to existing buffer.
+       (org-src-switch-to-buffer old-edit-buffer 'return)
+      ;; Discard old edit buffer.
+      (when old-edit-buffer
+       (with-current-buffer old-edit-buffer (org-src--remove-overlay))
+       (kill-buffer old-edit-buffer))
+      (let* ((org-mode-p (derived-mode-p 'org-mode))
+            (source-tab-width (if indent-tabs-mode tab-width 0))
+            (type (org-element-type datum))
+            (ind (org-with-wide-buffer
+                  (goto-char (org-element-property :begin datum))
+                  (org-get-indentation)))
+            (preserve-ind
+             (and (memq type '(example-block src-block))
+                  (or (org-element-property :preserve-indent datum)
+                      org-src-preserve-indentation)))
+            ;; Store relative positions of mark (if any) and point
+            ;; within the edited area.
+            (point-coordinates (and (not remote)
+                                    (org-src--coordinates (point) beg end)))
+            (mark-coordinates (and (not remote)
+                                   (org-region-active-p)
+                                   (let ((m (mark)))
+                                     (and (>= m beg) (>= end m)
+                                          (org-src--coordinates m beg end)))))
+            ;; Generate a new edit buffer.
+            (buffer (generate-new-buffer name))
+            ;; Add an overlay on top of source.
+            (overlay (org-src--make-source-overlay beg end buffer)))
+       ;; Switch to edit buffer.
+       (org-src-switch-to-buffer buffer 'edit)
+       ;; Insert contents.
+       (insert contents)
        (remove-text-properties (point-min) (point-max)
                                '(display nil invisible nil intangible nil))
-       (setq block-nindent (or (org-do-remove-indentation) 0))
-       (cond
-        ((eq org-edit-fixed-width-region-mode 'artist-mode)
-         (fundamental-mode)
-         (artist-mode 1))
-        (t (funcall org-edit-fixed-width-region-mode)))
-       (set (make-local-variable 'org-edit-src-force-single-line) nil)
-       (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
-       (set (make-local-variable 'org-edit-src-picture) t)
-       (goto-char (point-min))
-       (while (re-search-forward "^[ \t]*: ?" nil t)
-         (replace-match ""))
-       (org-goto-line (1+ (- line begline)))
-       (org-move-to-column (max 0 (- col block-nindent 2)))
-       (org-set-local 'org-edit-src-beg-marker beg)
-       (org-set-local 'org-edit-src-end-marker end)
-       (org-set-local 'org-edit-src-overlay ovl)
-       (org-set-local 'org-edit-src-block-indentation block-nindent)
-       (org-set-local 'org-edit-src-content-indentation 0)
-       (org-set-local 'org-src-preserve-indentation nil)
-       (org-src-mode)
+       (unless preserve-ind (org-do-remove-indentation))
        (set-buffer-modified-p nil)
-       (and org-edit-src-persistent-message
-            (org-set-local 'header-line-format msg)))
-      (message "%s" msg)
-      t)))
+       (setq buffer-file-name nil)
+       ;; Start major mode.
+       (if (not major) (fundamental-mode)
+         (let ((org-inhibit-startup t))
+           (condition-case e (funcall major)
+             (error (message "Language mode `%s' fails with: %S"
+                             major (nth 1 e))))))
+       ;; Transmit buffer-local variables for exit function.  It must
+       ;; be done after initializing major mode, as this operation
+       ;; may reset them otherwise.
+       (setq-local org-src--tab-width source-tab-width)
+       (setq-local org-src--from-org-mode org-mode-p)
+       (setq-local org-src--beg-marker beg)
+       (setq-local org-src--end-marker end)
+       (setq-local org-src--remote remote)
+       (setq-local org-src--source-type type)
+       (setq-local org-src--block-indentation ind)
+       (setq-local org-src--preserve-indentation preserve-ind)
+       (setq-local org-src--overlay overlay)
+       (setq-local org-src--allow-write-back write-back)
+       ;; Start minor mode.
+       (org-src-mode)
+       ;; Move mark and point in edit buffer to the corresponding
+       ;; location.
+       (if remote
+           (progn
+             ;; Put point at first non read-only character after
+             ;; leading blank.
+             (goto-char
+              (or (text-property-any (point-min) (point-max) 'read-only nil)
+                  (point-max)))
+             (skip-chars-forward " \r\t\n"))
+         ;; Set mark and point.
+         (when mark-coordinates
+           (org-src--goto-coordinates mark-coordinates (point-min) (point-max))
+           (push-mark (point) 'no-message t)
+           (setq deactivate-mark nil))
+         (org-src--goto-coordinates
+          point-coordinates (point-min) (point-max)))))))
+
+
+
+;;; Fontification of source blocks
 
-(defun org-edit-src-find-region-and-lang ()
-  "Find the region and language for a local edit.
-Return a list with beginning and end of the region, a string representing
-the language, a switch telling if the content should be in a single line."
-  (let ((re-list
-        (append
-         org-edit-src-region-extra
-         '(
-           ("<src\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</src>" lang)
-           ("<literal\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</literal>" style)
-           ("<example>[ \t]*\n?" "\n?[ \t]*</example>" "fundamental")
-           ("<lisp>[ \t]*\n?" "\n?[ \t]*</lisp>" "emacs-lisp")
-           ("<perl>[ \t]*\n?" "\n?[ \t]*</perl>" "perl")
-           ("<python>[ \t]*\n?" "\n?[ \t]*</python>" "python")
-           ("<ruby>[ \t]*\n?" "\n?[ \t]*</ruby>" "ruby")
-           ("^[ \t]*#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n" "\n[ 
\t]*#\\+end_src" 2)
-           ("^[ \t]*#\\+begin_example.*\n" "\n[ \t]*#\\+end_example" 
"fundamental")
-           ("^[ \t]*#\\+html:" "\n" "html" single-line)
-           ("^[ \t]*#\\+begin_html.*\n" "\n[ \t]*#\\+end_html" "html")
-           ("^[ \t]*#\\+latex:" "\n" "latex" single-line)
-           ("^[ \t]*#\\+begin_latex.*\n" "\n[ \t]*#\\+end_latex" "latex")
-           ("^[ \t]*#\\+ascii:" "\n" "fundamental" single-line)
-           ("^[ \t]*#\\+begin_ascii.*\n" "\n[ \t]*#\\+end_ascii" "fundamental")
-           ("^[ \t]*#\\+macro:[ \t]+\\S-+\\( \\|$\\)"
-            "\n" "fundamental" macro-definition)
-           )))
-       (pos (point))
-       re1 re2 single beg end lang lfmt match-re1 ind entry)
-    (catch 'exit
-      (while (setq entry (pop re-list))
-       (setq re1 (car entry) re2 (nth 1 entry) lang (nth 2 entry)
-             single (nth 3 entry))
-       (save-excursion
-         (if (or (looking-at re1)
-                 (re-search-backward re1 nil t))
-             (progn
-               (setq match-re1 (match-string 0))
-               (setq beg (match-end 0)
-                     lang (org-edit-src-get-lang lang)
-                     lfmt (org-edit-src-get-label-format match-re1)
-                     ind (org-edit-src-get-indentation (match-beginning 0)))
-               (if (and (re-search-forward re2 nil t)
-                        (>= (match-end 0) pos))
-                   (throw 'exit (list beg (match-beginning 0)
-                                      lang single lfmt ind))))
-           (if (or (looking-at re2)
-                   (re-search-forward re2 nil t))
-               (progn
-                 (setq end (match-beginning 0))
-                 (if (and (re-search-backward re1 nil t)
-                          (<= (match-beginning 0) pos))
-                     (progn
-                       (setq lfmt (org-edit-src-get-label-format
-                                   (match-string 0))
-                             ind (org-edit-src-get-indentation
-                                  (match-beginning 0)))
-                       (throw 'exit
-                              (list (match-end 0) end
-                                    (org-edit-src-get-lang lang)
-                                    single lfmt ind)))))))))
-      (when (org-at-table.el-p)
-       (re-search-backward "^[\t]*[^ \t|\\+]" nil t)
-       (setq beg (1+ (point-at-eol)))
-       (goto-char beg)
-       (or (re-search-forward "^[\t]*[^ \t|\\+]" nil t)
-           (progn (goto-char (point-max)) (newline)))
-       (setq end (1- (point-at-bol)))
-       (throw 'exit (list beg end 'table.el nil nil 0))))))
-
-(defun org-edit-src-get-lang (lang)
-  "Extract the src language."
-  (let ((m (match-string 0)))
-    (cond
-     ((stringp lang) lang)
-     ((integerp lang) (match-string lang))
-     ((and (eq lang 'lang)
-          (string-match "\\<lang=\"\\([^ \t\n\"]+\\)\"" m))
-      (match-string 1 m))
-     ((and (eq lang 'style)
-          (string-match "\\<style=\"\\([^ \t\n\"]+\\)\"" m))
-      (match-string 1 m))
-     (t "fundamental"))))
-
-(defun org-edit-src-get-label-format (s)
-  "Extract the label format."
-  (save-match-data
-    (if (string-match "-l[ \t]+\\\\?\"\\([^\t\r\n\"]+\\)\\\\?\"" s)
-       (match-string 1 s))))
-
-(defun org-edit-src-get-indentation (pos)
-  "Count leading whitespace characters on line."
-  (save-match-data
-    (goto-char pos)
-    (org-get-indentation)))
+(defun org-src-font-lock-fontify-block (lang start end)
+  "Fontify code block.
+This function is called by emacs automatic fontification, as long
+as `org-src-fontify-natively' is non-nil."
+  (let ((lang-mode (org-src--get-lang-mode lang)))
+    (when (fboundp lang-mode)
+      (let ((string (buffer-substring-no-properties start end))
+           (modified (buffer-modified-p))
+           (org-buffer (current-buffer)))
+       (remove-text-properties start end '(face nil))
+       (with-current-buffer
+           (get-buffer-create
+            (format " *org-src-fontification:%s*" lang-mode))
+         (let ((inhibit-modification-hooks nil))
+           (erase-buffer)
+           ;; Add string and a final space to ensure property change.
+           (insert string " "))
+         (unless (eq major-mode lang-mode) (funcall lang-mode))
+         (org-font-lock-ensure)
+         (let ((pos (point-min)) next)
+           (while (setq next (next-property-change pos))
+             ;; Handle additional properties from font-lock, so as to
+             ;; preserve, e.g., composition.
+             (dolist (prop (cons 'face font-lock-extra-managed-props))
+               (let ((new-prop (get-text-property pos prop)))
+                 (put-text-property
+                  (+ start (1- pos)) (1- (+ start next)) prop new-prop
+                  org-buffer)))
+             (setq pos next))))
+       ;; Add Org faces.
+       (let ((src-face (nth 1 (assoc-string lang org-src-block-faces t))))
+          (when (or (facep src-face) (listp src-face))
+            (font-lock-append-text-property start end 'face src-face))
+         (font-lock-append-text-property start end 'face 'org-block))
+       (add-text-properties
+        start end
+        '(font-lock-fontified t fontified t font-lock-multiline t))
+       (set-buffer-modified-p modified)))))
+
+
+;;; Escape contents
 
 (defun org-escape-code-in-region (beg end)
   "Escape lines between BEG and END.
@@ -646,9 +580,9 @@ Escaping happens when a line starts with \"*\", \"#+\", 
\",*\" or
 \",#+\" by appending a comma to it."
   (interactive "r")
   (save-excursion
-    (goto-char beg)
-    (while (re-search-forward "^[ \t]*,?\\(\\*\\|#\\+\\)" end t)
-      (replace-match ",\\1" nil nil nil 1))))
+    (goto-char end)
+    (while (re-search-backward "^[ \t]*,?\\(\\*\\|#\\+\\)" beg t)
+      (save-excursion (replace-match ",\\1" nil nil nil 1)))))
 
 (defun org-escape-code-in-string (s)
   "Escape lines in string S.
@@ -662,9 +596,9 @@ Un-escaping happens by removing the first comma on lines 
starting
 with \",*\", \",#+\", \",,*\" and \",,#+\"."
   (interactive "r")
   (save-excursion
-    (goto-char beg)
-    (while (re-search-forward "^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" end t)
-      (replace-match "" nil nil nil 1))))
+    (goto-char end)
+    (while (re-search-backward "^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" beg t)
+      (save-excursion (replace-match "" nil nil nil 1)))))
 
 (defun org-unescape-code-in-string (s)
   "Un-escape lines in string S.
@@ -673,169 +607,82 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
   (replace-regexp-in-string
    "^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" "" s nil nil 1))
 
-(defun org-edit-src-exit (&optional context)
-  "Exit special edit and protect problematic lines."
-  (interactive)
-  (unless (org-bound-and-true-p org-edit-src-from-org-mode)
-    (error "This is not a sub-editing buffer, something is wrong"))
-  (widen)
-  (let* ((fixed-width-p (string-match "Fixed Width" (buffer-name)))
-        (beg org-edit-src-beg-marker)
-        (end org-edit-src-end-marker)
-        (ovl org-edit-src-overlay)
-        (bufstr (buffer-string))
-        (buffer (current-buffer))
-        (single (org-bound-and-true-p org-edit-src-force-single-line))
-        (macro (eq single 'macro-definition))
-        (total-nindent (+ (or org-edit-src-block-indentation 0)
-                          org-edit-src-content-indentation))
-        (preserve-indentation org-src-preserve-indentation)
-        (allow-write-back-p (org-bound-and-true-p 
org-edit-src-allow-write-back-p))
-        (delta 0) code line col indent)
-    (when allow-write-back-p
-      (unless preserve-indentation (untabify (point-min) (point-max)))
-      (if org-src-strip-leading-and-trailing-blank-lines
-         (save-excursion
-           (goto-char (point-min))
-           (if (looking-at "[ \t\n]*\n") (replace-match ""))
-           (unless macro
-             (if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match 
""))))))
-    (setq line (if (org-bound-and-true-p org-edit-src-force-single-line)
-                  1
-                (org-current-line))
-         col (current-column))
-    (when allow-write-back-p
-      (when single
-       (goto-char (point-min))
-       (if (re-search-forward "\\s-+\\'" nil t) (replace-match ""))
-       (goto-char (point-min))
-       (let ((cnt 0))
-         (while (re-search-forward "\n" nil t)
-           (setq cnt (1+ cnt))
-           (replace-match (if macro "\\n" " ") t t))
-         (when (and macro (> cnt 0))
-           (goto-char (point-max)) (insert "\\n")))
-       (goto-char (point-min))
-       (if (looking-at "\\s-*") (replace-match " ")))
-      (when (and (org-bound-and-true-p org-edit-src-from-org-mode)
-                (not fixed-width-p))
-       (org-escape-code-in-region (point-min) (point-max))
-       (setq delta (+ delta
-                      (save-excursion
-                        (org-goto-line line)
-                        (if (looking-at "[ \t]*\\(,,\\)?\\(\\*\\|#+\\)") 1
-                          0)))))
-      (when (org-bound-and-true-p org-edit-src-picture)
-       (setq preserve-indentation nil)
-       (untabify (point-min) (point-max))
-       (goto-char (point-min))
-       (while (re-search-forward "^" nil t)
-         (replace-match ": ")))
-      (unless (or single preserve-indentation (= total-nindent 0))
-       (setq indent (make-string total-nindent ?\ ))
-       (goto-char (point-min))
-       (while (re-search-forward "\\(^\\).+" nil t)
-         (replace-match indent nil nil nil 1)))
-      (if (org-bound-and-true-p org-edit-src-picture)
-         (setq total-nindent (+ total-nindent 2)))
-      (setq code (buffer-string))
-      (when (eq context 'save)
-       (erase-buffer)
-       (insert bufstr))
-      (set-buffer-modified-p nil))
-    (org-src-switch-to-buffer (marker-buffer beg) (or context 'exit))
-    (if (eq context 'save) (save-buffer)
-      (with-current-buffer buffer
-       (set-buffer-modified-p nil))
-      (kill-buffer buffer))
-    (goto-char beg)
-    (when allow-write-back-p
-      (undo-boundary)
-      (delete-region beg (max beg end))
-      (unless (string-match "\\`[ \t]*\\'" code)
-       (insert code))
-      ;; Make sure the overlay stays in place
-      (when (eq context 'save) (move-overlay ovl beg (point)))
-      (goto-char beg)
-      (if single (just-one-space)))
-    (if (memq t (mapcar (lambda (overlay)
-                         (eq (overlay-get overlay 'invisible)
-                             'org-hide-block))
-                       (overlays-at (point))))
-       ;; Block is hidden; put point at start of block
-       (beginning-of-line 0)
-      ;; Block is visible, put point where it was in the code buffer
-      (when allow-write-back-p
-       (org-goto-line (1- (+ (org-current-line) line)))
-       (org-move-to-column (if preserve-indentation col (+ col total-nindent 
delta)))))
-    (unless (eq context 'save)
-      (move-marker beg nil)
-      (move-marker end nil)))
-  (unless (eq context 'save)
-    (when org-edit-src-saved-temp-window-config
-      (set-window-configuration org-edit-src-saved-temp-window-config)
-      (setq org-edit-src-saved-temp-window-config nil))))
-
-(defun org-edit-src-abort ()
-  "Abort editing of the src code and return to the Org buffer."
-  (interactive)
-  (let (org-edit-src-allow-write-back-p)
-    (org-edit-src-exit 'exit)))
-
-(defmacro org-src-in-org-buffer (&rest body)
-  `(let ((p (point)) (m (mark)) (ul buffer-undo-list) msg)
-     (save-window-excursion
-       (org-edit-src-exit 'save)
-       ,@body
-       (setq msg (current-message))
-       (if (eq org-src-window-setup 'other-frame)
-          (let ((org-src-window-setup 'current-window))
-            (org-edit-src-code 'save))
-        (org-edit-src-code 'save)))
-     (setq buffer-undo-list ul)
-     (push-mark m 'nomessage)
-     (goto-char (min p (point-max)))
-     (message (or msg ""))))
-(def-edebug-spec org-src-in-org-buffer (body))
 
-(defun org-edit-src-save ()
-  "Save parent buffer with current state source-code buffer."
-  (interactive)
-  (if (string-match "Fixed Width" (buffer-name))
-      (user-error "%s" "Use C-c ' to save and exit, C-c C-k to abort editing")
-    (org-src-in-org-buffer (save-buffer))))
+
+;;; Org src minor mode
 
-(declare-function org-babel-tangle "ob-tangle" (&optional arg target-file 
lang))
+(defvar org-src-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-c'" 'org-edit-src-exit)
+    (define-key map "\C-c\C-k" 'org-edit-src-abort)
+    (define-key map "\C-x\C-s" 'org-edit-src-save)
+    map))
 
-(defun org-src-tangle (arg)
-  "Tangle the parent buffer."
-  (interactive)
-  (org-src-in-org-buffer (org-babel-tangle arg)))
+(define-minor-mode org-src-mode
+  "Minor mode for language major mode buffers generated by Org.
+\\<org-mode-map>
+This minor mode is turned on in two situations:
+  - when editing a source code snippet with `\\[org-edit-special]'
+  - when formatting a source code snippet for export with htmlize.
+
+\\{org-src-mode-map}
+
+See also `org-src-mode-hook'."
+  nil " OrgSrc" nil
+  (when org-edit-src-persistent-message
+    (setq-local
+     header-line-format
+     (substitute-command-keys
+      (if org-src--allow-write-back
+         "Edit, then exit with `\\[org-edit-src-exit]' or abort with \
+`\\[org-edit-src-abort]'"
+       "Exit with `\\[org-edit-src-exit]' or abort with \
+`\\[org-edit-src-abort]'"))))
+  ;; Possibly activate various auto-save features (for the edit buffer
+  ;; or the source buffer).
+  (when org-edit-src-turn-on-auto-save
+    (setq buffer-auto-save-file-name
+         (concat (make-temp-name "org-src-")
+                 (format-time-string "-%Y-%d-%m")
+                 ".txt")))
+  (unless (or org-src--auto-save-timer (zerop 
org-edit-src-auto-save-idle-delay))
+    (setq org-src--auto-save-timer
+         (run-with-idle-timer
+          org-edit-src-auto-save-idle-delay t
+          (lambda ()
+            (save-excursion
+              (let (edit-flag)
+                (dolist (b (buffer-list))
+                  (with-current-buffer b
+                    (when (org-src-edit-buffer-p)
+                      (unless edit-flag (setq edit-flag t))
+                      (when (buffer-modified-p) (org-edit-src-save)))))
+                (unless edit-flag
+                  (cancel-timer org-src--auto-save-timer)
+                  (setq org-src--auto-save-timer nil)))))))))
 
 (defun org-src-mode-configure-edit-buffer ()
-  (when (org-bound-and-true-p org-edit-src-from-org-mode)
-    (org-add-hook 'kill-buffer-hook
-                 #'(lambda () (delete-overlay org-edit-src-overlay)) nil 
'local)
-    (if (org-bound-and-true-p org-edit-src-allow-write-back-p)
+  (when (bound-and-true-p org-src--from-org-mode)
+    (add-hook 'kill-buffer-hook #'org-src--remove-overlay nil 'local)
+    (if (bound-and-true-p org-src--allow-write-back)
        (progn
          (setq buffer-offer-save t)
          (setq buffer-file-name
-               (concat (buffer-file-name (marker-buffer 
org-edit-src-beg-marker))
+               (concat (buffer-file-name (marker-buffer org-src--beg-marker))
                        "[" (buffer-name) "]"))
-         (if (featurep 'xemacs)
-             (progn
-               (make-variable-buffer-local 'write-contents-hooks) ; needed 
only for 21.4
-               (setq write-contents-hooks '(org-edit-src-save)))
-           (setq write-contents-functions '(org-edit-src-save))))
+         (setq-local write-contents-functions '(org-edit-src-save)))
       (setq buffer-read-only t))))
 
-(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer)
+(add-hook 'org-src-mode-hook #'org-src-mode-configure-edit-buffer)
+
 
+
+;;; Babel related functions
 
 (defun org-src-associate-babel-session (info)
   "Associate edit buffer with comint session."
   (interactive)
-  (let ((session (cdr (assoc :session (nth 2 info)))))
+  (let ((session (cdr (assq :session (nth 2 info)))))
     (and session (not (string= session "none"))
         (org-babel-comint-buffer-livep session)
         (let ((f (intern (format "org-babel-%s-associate-session"
@@ -843,18 +690,22 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
            (and (fboundp f) (funcall f session))))))
 
 (defun org-src-babel-configure-edit-buffer ()
-  (when org-src-babel-info
-    (org-src-associate-babel-session org-src-babel-info)))
+  (when org-src--babel-info
+    (org-src-associate-babel-session org-src--babel-info)))
+
+(add-hook 'org-src-mode-hook #'org-src-babel-configure-edit-buffer)
+
+
+;;; Public API
 
-(org-add-hook 'org-src-mode-hook 'org-src-babel-configure-edit-buffer)
 (defmacro org-src-do-at-code-block (&rest body)
-  "Execute a command from an edit buffer in the Org-mode buffer."
-  `(let ((beg-marker org-edit-src-beg-marker))
-     (if beg-marker
-        (with-current-buffer (marker-buffer beg-marker)
-          (goto-char (marker-position beg-marker))
-          ,@body))))
-(def-edebug-spec org-src-do-at-code-block (body))
+  "Execute BODY from an edit buffer in the Org mode buffer."
+  (declare (debug (body)))
+  `(let ((beg-marker org-src--beg-marker))
+     (when beg-marker
+       (with-current-buffer (marker-buffer beg-marker)
+        (goto-char beg-marker)
+        ,@body))))
 
 (defun org-src-do-key-sequence-at-code-block (&optional key)
   "Execute key sequence at code block in the source Org buffer.
@@ -878,85 +729,375 @@ Org-babel commands."
   (if (equal key (kbd "C-g")) (keyboard-quit)
     (org-edit-src-save)
     (org-src-do-at-code-block
-     (call-interactively
-      (lookup-key org-babel-map key)))))
+     (call-interactively (lookup-key org-babel-map key)))))
 
-(defcustom org-src-tab-acts-natively nil
-  "If non-nil, the effect of TAB in a code block is as if it were
-issued in the language major mode buffer."
-  :type 'boolean
-  :version "24.1"
-  :group 'org-babel)
+(defun org-src-edit-buffer-p (&optional buffer)
+  "Non-nil when current buffer is a source editing buffer.
+If BUFFER is non-nil, test it instead."
+  (let ((buffer (org-base-buffer (or buffer (current-buffer)))))
+    (and (buffer-live-p buffer)
+        (local-variable-p 'org-src--beg-marker buffer)
+        (local-variable-p 'org-src--end-marker buffer))))
+
+(defun org-src-switch-to-buffer (buffer context)
+  (pcase org-src-window-setup
+    (`current-window (pop-to-buffer-same-window buffer))
+    (`other-window
+     (switch-to-buffer-other-window buffer))
+    (`other-frame
+     (pcase context
+       (`exit
+       (let ((frame (selected-frame)))
+         (switch-to-buffer-other-frame buffer)
+         (delete-frame frame)))
+       (`save
+       (kill-buffer (current-buffer))
+       (pop-to-buffer-same-window buffer))
+       (_ (switch-to-buffer-other-frame buffer))))
+    (`reorganize-frame
+     (when (eq context 'edit) (delete-other-windows))
+     (org-switch-to-buffer-other-window buffer)
+     (when (eq context 'exit) (delete-other-windows)))
+    (`switch-invisibly (set-buffer buffer))
+    (_
+     (message "Invalid value %s for `org-src-window-setup'"
+             org-src-window-setup)
+     (pop-to-buffer-same-window buffer))))
+
+(defun org-src-coderef-format (&optional element)
+  "Return format string for block at point.
+
+When optional argument ELEMENT is provided, use that block.
+Otherwise, assume point is either at a source block, at an
+example block.
+
+If point is in an edit buffer, retrieve format string associated
+to the remote source block."
+  (cond
+   ((and element (org-element-property :label-fmt element)))
+   ((org-src-edit-buffer-p) (org-src-do-at-code-block 
(org-src-coderef-format)))
+   ((org-element-property :label-fmt (org-element-at-point)))
+   (t org-coderef-label-format)))
+
+(defun org-src-coderef-regexp (fmt &optional label)
+  "Return regexp matching a coderef format string FMT.
+
+When optional argument LABEL is non-nil, match coderef for that
+label only.
+
+Match group 1 contains the full coderef string with surrounding
+white spaces.  Match group 2 contains the same string without any
+surrounding space.  Match group 3 contains the label.
+
+A coderef format regexp can only match at the end of a line."
+  (format "\\([ \t]*\\(%s\\)[ \t]*\\)$"
+         (replace-regexp-in-string
+          "%s"
+          (if label (regexp-quote label) "\\([-a-zA-Z0-9_][-a-zA-Z0-9_ ]*\\)")
+          (regexp-quote fmt)
+          nil t)))
+
+(defun org-edit-footnote-reference ()
+  "Edit definition of footnote reference at point."
+  (interactive)
+  (let* ((context (org-element-context))
+        (label (org-element-property :label context)))
+    (unless (and (eq (org-element-type context) 'footnote-reference)
+                (org-src--on-datum-p context))
+      (user-error "Not on a footnote reference"))
+    (unless label (user-error "Cannot edit remotely anonymous footnotes"))
+    (let* ((definition (org-with-wide-buffer
+                       (org-footnote-goto-definition label)
+                       (backward-char)
+                       (org-element-context)))
+          (inline? (eq 'footnote-reference (org-element-type definition)))
+          (contents
+           (org-with-wide-buffer
+            (buffer-substring-no-properties
+             (or (org-element-property :post-affiliated definition)
+                 (org-element-property :begin definition))
+             (cond
+              (inline? (1+ (org-element-property :contents-end definition)))
+              ((org-element-property :contents-end definition))
+              (t (goto-char (org-element-property :post-affiliated definition))
+                 (line-end-position)))))))
+      (add-text-properties
+       0
+       (progn (string-match (if inline? "\\`\\[fn:.*?:" "\\`.*?\\]") contents)
+             (match-end 0))
+       '(read-only "Cannot edit footnote label" front-sticky t rear-nonsticky 
t)
+       contents)
+      (when inline?
+       (let ((l (length contents)))
+         (add-text-properties
+          (1- l) l
+          '(read-only "Cannot edit past footnote reference"
+                      front-sticky nil rear-nonsticky nil)
+          contents)))
+      (org-src--edit-element
+       definition
+       (format "*Edit footnote [%s]*" label)
+       #'org-mode
+       (lambda ()
+        (if (not inline?) (delete-region (point) (search-forward "]"))
+          (delete-region (point) (search-forward ":" nil t 2))
+          (delete-region (1- (point-max)) (point-max))
+          (when (re-search-forward "\n[ \t]*\n" nil t)
+            (user-error "Inline definitions cannot contain blank lines"))
+          ;; If footnote reference belongs to a table, make sure to
+          ;; remove any newline characters in order to preserve
+          ;; table's structure.
+          (when (org-element-lineage definition '(table-cell))
+            (while (search-forward "\n" nil t) (replace-match "")))))
+       contents
+       'remote))
+    ;; Report success.
+    t))
+
+(defun org-edit-table.el ()
+  "Edit \"table.el\" table at point.
+\\<org-src-mode-map>
+A new buffer is created and the table is copied into it.  Then
+the table is recognized with `table-recognize'.  When done
+editing, exit with `\\[org-edit-src-exit]'.  The edited text will \
+then replace
+the area in the Org mode buffer.
+
+Throw an error when not at such a table."
+  (interactive)
+  (let ((element (org-element-at-point)))
+    (unless (and (eq (org-element-type element) 'table)
+                (eq (org-element-property :type element) 'table.el)
+                (org-src--on-datum-p element))
+      (user-error "Not in a table.el table"))
+    (org-src--edit-element
+     element
+     (org-src--construct-edit-buffer-name (buffer-name) "Table")
+     #'text-mode t)
+    (when (bound-and-true-p flyspell-mode) (flyspell-mode -1))
+    (table-recognize)
+    t))
+
+(defun org-edit-export-block ()
+  "Edit export block at point.
+\\<org-src-mode-map>
+A new buffer is created and the block is copied into it, and the
+buffer is switched into an appropriate major mode.  See also
+`org-src-lang-modes'.
+
+When done, exit with `\\[org-edit-src-exit]'.  The edited text \
+will then replace
+the area in the Org mode buffer.
+
+Throw an error when not at an export block."
+  (interactive)
+  (let ((element (org-element-at-point)))
+    (unless (and (eq (org-element-type element) 'export-block)
+                (org-src--on-datum-p element))
+      (user-error "Not in an export block"))
+    (let* ((type (downcase (org-element-property :type element)))
+          (mode (org-src--get-lang-mode type)))
+      (unless (functionp mode) (error "No such language mode: %s" mode))
+      (org-src--edit-element
+       element
+       (org-src--construct-edit-buffer-name (buffer-name) type)
+       mode
+       (lambda () (org-escape-code-in-region (point-min) (point-max)))))
+    t))
+
+(defun org-edit-src-code (&optional code edit-buffer-name)
+  "Edit the source or example block at point.
+\\<org-src-mode-map>
+The code is copied to a separate buffer and the appropriate mode
+is turned on.  When done, exit with `\\[org-edit-src-exit]'.  This \
+will remove the
+original code in the Org buffer, and replace it with the edited
+version.  See `org-src-window-setup' to configure the display of
+windows containing the Org buffer and the code buffer.
 
-(defun org-src-native-tab-command-maybe ()
-  "Perform language-specific TAB action.
-Alter code block according to what TAB does in the language major mode."
-  (and org-src-tab-acts-natively
-       (org-in-src-block-p)
-       (not (equal this-command 'org-shifttab))
-       (let ((org-src-strip-leading-and-trailing-blank-lines nil))
-        (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))))
+When optional argument CODE is a string, edit it in a dedicated
+buffer instead.
 
-(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe)
+When optional argument EDIT-BUFFER-NAME is non-nil, use it as the
+name of the sub-editing buffer."
+  (interactive)
+  (let* ((element (org-element-at-point))
+        (type (org-element-type element)))
+    (unless (and (memq type '(example-block src-block))
+                (org-src--on-datum-p element))
+      (user-error "Not in a source or example block"))
+    (let* ((lang
+           (if (eq type 'src-block) (org-element-property :language element)
+             "example"))
+          (lang-f (and (eq type 'src-block) (org-src--get-lang-mode lang)))
+          (babel-info (and (eq type 'src-block)
+                           (org-babel-get-src-block-info 'light)))
+          deactivate-mark)
+      (when (and (eq type 'src-block) (not (functionp lang-f)))
+       (error "No such language mode: %s" lang-f))
+      (org-src--edit-element
+       element
+       (or edit-buffer-name
+          (org-src--construct-edit-buffer-name (buffer-name) lang))
+       lang-f
+       (and (null code)
+           (lambda () (org-escape-code-in-region (point-min) (point-max))))
+       (and code (org-unescape-code-in-string code)))
+      ;; Finalize buffer.
+      (setq-local org-coderef-label-format
+                 (or (org-element-property :label-fmt element)
+                     org-coderef-label-format))
+      (when (eq type 'src-block)
+       (setq-local org-src--babel-info babel-info)
+       (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
+         (when (fboundp edit-prep-func)
+           (funcall edit-prep-func babel-info))))
+      t)))
 
-(defun org-src-font-lock-fontify-block (lang start end)
-  "Fontify code block.
-This function is called by emacs automatic fontification, as long
-as `org-src-fontify-natively' is non-nil.  For manual
-fontification of code blocks see `org-src-fontify-block' and
-`org-src-fontify-buffer'"
-  (let ((lang-mode (org-src-get-lang-mode lang)))
-    (if (fboundp lang-mode)
-       (let ((string (buffer-substring-no-properties start end))
-             (modified (buffer-modified-p))
-             (org-buffer (current-buffer)) pos next)
-         (remove-text-properties start end '(face nil))
-         (with-current-buffer
-             (get-buffer-create
-              (concat " org-src-fontification:" (symbol-name lang-mode)))
-            ;; Make sure that modification hooks are not inhibited in
-            ;; the org-src-fontification buffer in case we're called
-            ;; from `jit-lock-function' (Bug#25132).
-            (let ((inhibit-modification-hooks nil))
-              (delete-region (point-min) (point-max))
-              (insert string " ")) ;; so there's a final property change
-            (unless (eq major-mode lang-mode) (funcall lang-mode))
-            (org-font-lock-ensure)
-            (setq pos (point-min))
-            (while (setq next (next-single-property-change pos 'face))
-              (put-text-property
-               (+ start (1- pos)) (1- (+ start next)) 'face
-               (get-text-property pos 'face) org-buffer)
-              (setq pos next)))
-         (add-text-properties
-          start end
-          '(font-lock-fontified t fontified t font-lock-multiline t))
-         (set-buffer-modified-p modified)))))
+(defun org-edit-inline-src-code ()
+  "Edit inline source code at point."
+  (interactive)
+  (let ((context (org-element-context)))
+    (unless (and (eq (org-element-type context) 'inline-src-block)
+                (org-src--on-datum-p context))
+      (user-error "Not on inline source code"))
+    (let* ((lang (org-element-property :language context))
+          (lang-f (org-src--get-lang-mode lang))
+          (babel-info (org-babel-get-src-block-info 'light))
+          deactivate-mark)
+      (unless (functionp lang-f) (error "No such language mode: %s" lang-f))
+      (org-src--edit-element
+       context
+       (org-src--construct-edit-buffer-name (buffer-name) lang)
+       lang-f
+       (lambda ()
+        ;; Inline src blocks are limited to one line.
+        (while (re-search-forward "\n[ \t]*" nil t) (replace-match " "))
+        ;; Trim contents.
+        (goto-char (point-min))
+        (skip-chars-forward " \t")
+        (delete-region (point-min) (point))
+        (goto-char (point-max))
+        (skip-chars-backward " \t")
+        (delete-region (point) (point-max))))
+      ;; Finalize buffer.
+      (setq-local org-src--babel-info babel-info)
+      (setq-local org-src--preserve-indentation t)
+      (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
+       (when (fboundp edit-prep-func) (funcall edit-prep-func babel-info)))
+      ;; Return success.
+      t)))
 
-(defvar org-src-fontify-natively)
+(defun org-edit-fixed-width-region ()
+  "Edit the fixed-width ASCII drawing at point.
+\\<org-src-mode-map>
+This must be a region where each line starts with a colon
+followed by a space or a newline character.
+
+A new buffer is created and the fixed-width region is copied into
+it, and the buffer is switched into the major mode defined in
+`org-edit-fixed-width-region-mode', which see.
+
+When done, exit with `\\[org-edit-src-exit]'.  The edited text \
+will then replace
+the area in the Org mode buffer."
+  (interactive)
+  (let ((element (org-element-at-point)))
+    (unless (and (eq (org-element-type element) 'fixed-width)
+                (org-src--on-datum-p element))
+      (user-error "Not in a fixed-width area"))
+    (org-src--edit-element
+     element
+     (org-src--construct-edit-buffer-name (buffer-name) "Fixed Width")
+     org-edit-fixed-width-region-mode
+     (lambda () (while (not (eobp)) (insert ": ") (forward-line))))
+    ;; Return success.
+    t))
 
-(defun org-src-fontify-block ()
-  "Fontify code block at point."
+(defun org-edit-src-abort ()
+  "Abort editing of the src code and return to the Org buffer."
   (interactive)
-  (save-excursion
-    (let ((org-src-fontify-natively t)
-         (info (org-edit-src-find-region-and-lang)))
-      (font-lock-fontify-region (nth 0 info) (nth 1 info)))))
+  (let (org-src--allow-write-back) (org-edit-src-exit)))
 
-(defun org-src-fontify-buffer ()
-  "Fontify all code blocks in the current buffer."
+(defun org-edit-src-continue (e)
+  "Unconditionally return to buffer editing area under point.
+Throw an error if there is no such buffer."
+  (interactive "e")
+  (mouse-set-point e)
+  (let ((buf (get-char-property (point) 'edit-buffer)))
+    (if buf (org-src-switch-to-buffer buf 'continue)
+      (user-error "No sub-editing buffer for area at point"))))
+
+(defun org-edit-src-save ()
+  "Save parent buffer with current state source-code buffer."
   (interactive)
-  (org-babel-map-src-blocks nil
-    (org-src-fontify-block)))
+  (unless (org-src-edit-buffer-p) (user-error "Not in a sub-editing buffer"))
+  (set-buffer-modified-p nil)
+  (let ((edited-code (org-src--contents-for-write-back))
+       (beg org-src--beg-marker)
+       (end org-src--end-marker)
+       (overlay org-src--overlay))
+    (with-current-buffer (org-src--source-buffer)
+      (undo-boundary)
+      (goto-char beg)
+      ;; Temporarily disable read-only features of OVERLAY in order to
+      ;; insert new contents.
+      (delete-overlay overlay)
+      (delete-region beg end)
+      (let ((expecting-bol (bolp)))
+       (insert edited-code)
+       (when (and expecting-bol (not (bolp))) (insert "\n")))
+      (save-buffer)
+      (move-overlay overlay beg (point))))
+  ;; `write-contents-functions' requires the function to return
+  ;; a non-nil value so that other functions are not called.
+  t)
+
+(defun org-edit-src-exit ()
+  "Kill current sub-editing buffer and return to source buffer."
+  (interactive)
+  (unless (org-src-edit-buffer-p) (error "Not in a sub-editing buffer"))
+  (let* ((beg org-src--beg-marker)
+        (end org-src--end-marker)
+        (write-back org-src--allow-write-back)
+        (remote org-src--remote)
+        (coordinates (and (not remote)
+                          (org-src--coordinates (point) 1 (point-max))))
+        (code (and write-back (org-src--contents-for-write-back))))
+    (set-buffer-modified-p nil)
+    ;; Switch to source buffer.  Kill sub-editing buffer.
+    (let ((edit-buffer (current-buffer))
+         (source-buffer (marker-buffer beg)))
+      (unless source-buffer (error "Source buffer disappeared.  Aborting"))
+      (org-src-switch-to-buffer source-buffer 'exit)
+      (kill-buffer edit-buffer))
+    ;; Insert modified code.  Ensure it ends with a newline character.
+    (org-with-wide-buffer
+     (when (and write-back (not (equal (buffer-substring beg end) code)))
+       (undo-boundary)
+       (goto-char beg)
+       (delete-region beg end)
+       (let ((expecting-bol (bolp)))
+        (insert code)
+        (when (and expecting-bol (not (bolp))) (insert "\n")))))
+    ;; If we are to return to source buffer, put point at an
+    ;; appropriate location.  In particular, if block is hidden, move
+    ;; to the beginning of the block opening line.
+    (unless remote
+      (goto-char beg)
+      (cond
+       ;; Block is hidden; move at start of block.
+       ((cl-some (lambda (o) (eq (overlay-get o 'invisible) 'org-hide-block))
+                (overlays-at (point)))
+       (beginning-of-line 0))
+       (write-back (org-src--goto-coordinates coordinates beg end))))
+    ;; Clean up left-over markers and restore window configuration.
+    (set-marker beg nil)
+    (set-marker end nil)
+    (when org-src--saved-temp-window-config
+      (set-window-configuration org-src--saved-temp-window-config)
+      (setq org-src--saved-temp-window-config nil))))
 
-(defun org-src-get-lang-mode (lang)
-  "Return major mode that should be used for LANG.
-LANG is a string, and the returned major mode is a symbol."
-  (intern
-   (concat
-    (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
-      (if (symbolp l) (symbol-name l) l))
-    "-mode")))
 
 (provide 'org-src)
 
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 0c813d0..40a715a 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -1,4 +1,4 @@
-;;; org-table.el --- The table editor for Org-mode
+;;; org-table.el --- The Table Editor for Org        -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -24,27 +24,53 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the table editor and spreadsheet for Org-mode.
+;; This file contains the table editor and spreadsheet for Org mode.
 
 ;; Watch out:  Here we are talking about two different kind of tables.
-;; Most of the code is for the tables created with the Org-mode table editor.
+;; Most of the code is for the tables created with the Org mode table editor.
 ;; Sometimes, we talk about tables created and edited with the table.el
 ;; Emacs package.  We call the former org-type tables, and the latter
 ;; table.el-type tables.
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl))
+(require 'cl-lib)
 (require 'org)
 
-(declare-function org-export-string-as "ox"
-                 (string backend &optional body-only ext-plist))
-(declare-function aa2u "ext:ascii-art-to-unicode" ())
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-contents "org-element" (element))
+(declare-function org-element-extract-element "org-element" (element))
+(declare-function org-element-interpret-data "org-element" (data))
+(declare-function org-element-lineage "org-element"
+                 (blob &optional types with-self))
+(declare-function org-element-map "org-element"
+                 (data types fun
+                       &optional info first-match no-recursion 
with-affiliated))
+(declare-function org-element-parse-buffer "org-element"
+                 (&optional granularity visible-only))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+
+(declare-function org-export-create-backend "ox" (&rest rest) t)
+(declare-function org-export-data-with-backend "ox" (data backend info))
+(declare-function org-export-filter-apply-functions "ox"
+                 (filters value info))
+(declare-function org-export-first-sibling-p "ox" (blob info))
+(declare-function org-export-get-backend "ox" (name))
+(declare-function org-export-get-environment "ox"
+                 (&optional backend subtreep ext-plist))
+(declare-function org-export-install-filters "ox" (info))
+(declare-function org-export-table-has-special-column-p "ox" (table))
+(declare-function org-export-table-row-is-special-p "ox" (table-row info))
+
+(declare-function calc-eval "calc" (str &optional separator &rest args))
+
 (defvar orgtbl-mode) ; defined below
 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
 (defvar constants-unit-system)
+(defvar org-export-filters-alist)
 (defvar org-table-follow-field-mode)
+(defvar sort-fold-case)
 
 (defvar orgtbl-after-send-table-hook nil
   "Hook for functions attaching to `C-c C-c', if the table is sent.
@@ -52,7 +78,7 @@ This can be used to add additional functionality after the 
table is sent
 to the receiver position, otherwise, if table is not sent, the functions
 are not run.")
 
-(defvar org-table-TBLFM-begin-regexp "|\n[ \t]*#\\+TBLFM: ")
+(defvar org-table-TBLFM-begin-regexp "^[ \t]*|.*\n[ \t]*#\\+TBLFM: ")
 
 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
   "Non-nil means use the optimized table editor version for `orgtbl-mode'.
@@ -63,7 +89,7 @@ for empty fields).  Outside tables, the correct binding of 
the keys is
 restored.
 
 The default for this option is t if the optimized version is also used in
-Org-mode.  See the variable `org-enable-table-editor' for details.  Changing
+Org mode.  See the variable `org-enable-table-editor' for details.  Changing
 this variable requires a restart of Emacs to become effective."
   :group 'org-table
   :type 'boolean)
@@ -118,7 +144,7 @@ table, obtained by prompting the user."
                (string :tag "Format"))))
 
 (defgroup org-table-settings nil
-  "Settings for tables in Org-mode."
+  "Settings for tables in Org mode."
   :tag "Org Table Settings"
   :group 'org-table)
 
@@ -167,13 +193,13 @@ alignment to the right border applies."
   :type 'number)
 
 (defgroup org-table-editing nil
-  "Behavior of tables during editing in Org-mode."
+  "Behavior of tables during editing in Org mode."
   :tag "Org Table Editing"
   :group 'org-table)
 
 (defcustom org-table-automatic-realign t
   "Non-nil means automatically re-align table when pressing TAB or RETURN.
-When nil, aligning is only done with \\[org-table-align], or after column
+When nil, aligning is only done with `\\[org-table-align]', or after column
 removal/insertion."
   :group 'org-table-editing
   :type 'boolean)
@@ -219,12 +245,12 @@ this line."
   :type 'boolean)
 
 (defgroup org-table-calculation nil
-  "Options concerning tables in Org-mode."
+  "Options concerning tables in Org mode."
   :tag "Org Table Calculation"
   :group 'org-table)
 
 (defcustom org-table-use-standard-references 'from
-  "Should org-mode work with table references like B3 instead of @3$2?
+  "Non-nil means using table references like B3 instead of @3$2.
 Possible values are:
 nil     never use them
 from    accept as input, do not present for editing
@@ -236,9 +262,15 @@ t       accept as input and present for editing"
          (const :tag "Convert user input, don't offer during editing" from)))
 
 (defcustom org-table-copy-increment t
-  "Non-nil means increment when copying current field with 
\\[org-table-copy-down]."
+  "Non-nil means increment when copying current field with \
+`\\[org-table-copy-down]'."
   :group 'org-table-calculation
-  :type 'boolean)
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice
+         (const :tag "Use the difference between the current and the above 
fields" t)
+         (integer :tag "Use a number" 1)
+         (const :tag "Don't increment the value when copying a field" nil)))
 
 (defcustom org-calc-default-modes
   '(calc-internal-prec 12
@@ -251,16 +283,16 @@ t       accept as input and present for editing"
                       )
   "List with Calc mode settings for use in `calc-eval' for table formulas.
 The list must contain alternating symbols (Calc modes variables and values).
-Don't remove any of the default settings, just change the values.  Org-mode
+Don't remove any of the default settings, just change the values.  Org mode
 relies on the variables to be present in the list."
   :group 'org-table-calculation
   :type 'plist)
 
 (defcustom org-table-duration-custom-format 'hours
   "Format for the output of calc computations like $1+$2;t.
-The default value is 'hours, and will output the results as a
-number of hours.  Other allowed values are 'seconds, 'minutes and
-'days, and the output will be a fraction of seconds, minutes or
+The default value is `hours', and will output the results as a
+number of hours.  Other allowed values are `seconds', `minutes' and
+`days', and the output will be a fraction of seconds, minutes or
 days."
   :group 'org-table-calculation
   :version "24.1"
@@ -285,7 +317,7 @@ which should be evaluated as described in the manual and in 
the documentation
 string of the command `org-table-eval-formula'.  This feature requires the
 Emacs calc package.
 When this variable is nil, formula calculation is only available through
-the command \\[org-table-eval-formula]."
+the command `\\[org-table-eval-formula]'."
   :group 'org-table-calculation
   :type 'boolean)
 
@@ -317,15 +349,12 @@ Constants can also be defined on a per-file basis using a 
line like
 
 (defcustom org-table-allow-automatic-line-recalculation t
   "Non-nil means lines marked with |#| or |*| will be recomputed automatically.
-Automatically means when TAB or RET or C-c C-c are pressed in the line."
+\\<org-mode-map>\
+Automatically means when `TAB' or `RET' or `\\[org-ctrl-c-ctrl-c]' \
+are pressed in the line."
   :group 'org-table-calculation
   :type 'boolean)
 
-(defcustom org-table-error-on-row-ref-crossing-hline t
-  "OBSOLETE VARIABLE, please see `org-table-relative-ref-may-cross-hline'."
-  :group 'org-table
-  :type 'boolean)
-
 (defcustom org-table-relative-ref-may-cross-hline t
   "Non-nil means relative formula references may cross hlines.
 Here are the allowed values:
@@ -345,8 +374,20 @@ portability of tables."
          (const :tag "Stick to hline" nil)
          (const :tag "Error on attempt to cross" error)))
 
+(defcustom org-table-formula-create-columns nil
+  "Non-nil means that evaluation of a field formula can add new
+columns if an out-of-bounds field is being set."
+  :group 'org-table-calculation
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice
+         (const :tag "Setting an out-of-bounds field generates an error 
(default)" nil)
+         (const :tag "Setting an out-of-bounds field silently adds columns as 
needed" t)
+         (const :tag "Setting an out-of-bounds field adds columns as needed, 
but issues a warning message" warn)
+         (const :tag "When setting an out-of-bounds field, the user is 
prompted" prompt)))
+
 (defgroup org-table-import-export nil
-  "Options concerning table import and export in Org-mode."
+  "Options concerning table import and export in Org mode."
   :tag "Org Table Import Export"
   :group 'org-table)
 
@@ -359,38 +400,73 @@ available parameters."
   :group 'org-table-import-export
   :type 'string)
 
+(defcustom org-table-convert-region-max-lines 999
+  "Max lines that `org-table-convert-region' will attempt to process.
+
+The function can be slow on larger regions; this safety feature
+prevents it from hanging emacs."
+  :group 'org-table-import-export
+  :type 'integer
+  :version "26.1"
+  :package-version '(Org . "8.3"))
+
 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
-  "Detects a table line marked for automatic recalculation.")
+  "Regexp matching a line marked for automatic recalculation.")
+
 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
-  "Detects a table line marked for automatic recalculation.")
+  "Regexp matching a line marked for recalculation.")
+
 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
-  "Detects a table line marked for automatic recalculation.")
+  "Regexp matching a line marked for calculation.")
+
 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
-  "Searching from within a table (any type) this finds the first line outside 
the table.")
+  "Regexp matching any line outside an Org table.")
+
 (defvar org-table-last-highlighted-reference nil)
+
 (defvar org-table-formula-history nil)
 
 (defvar org-table-column-names nil
-  "Alist with column names, derived from the `!' line.")
+  "Alist with column names, derived from the `!' line.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-column-name-regexp nil
-  "Regular expression matching the current column names.")
+  "Regular expression matching the current column names.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-local-parameters nil
-  "Alist with parameter names, derived from the `$' line.")
+  "Alist with parameter names, derived from the `$' line.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-named-field-locations nil
-  "Alist with locations of named fields.")
+  "Alist with locations of named fields.
+Associations follow the pattern (NAME LINE COLUMN) where
+  NAME is the name of the field as a string,
+  LINE is the number of lines from the beginning of the table,
+  COLUMN is the column of the field, as an integer.
+This variable is initialized with `org-table-analyze'.")
 
 (defvar org-table-current-line-types nil
-  "Table row types, non-nil only for the duration of a command.")
-(defvar org-table-current-begin-line nil
-  "Table begin line, non-nil only for the duration of a command.")
+  "Table row types in current table.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-current-begin-pos nil
-  "Table begin position, non-nil only for the duration of a command.")
+  "Current table begin position, as a marker.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-current-ncol nil
-  "Number of columns in table, non-nil only for the duration of a command.")
+  "Number of columns in current table.
+This variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-dlines nil
-  "Vector of data line line numbers in the current table.")
+  "Vector of data line line numbers in the current table.
+Line numbers are counted from the beginning of the table.  This
+variable is initialized with `org-table-analyze'.")
+
 (defvar org-table-hlines nil
-  "Vector of hline line numbers in the current table.")
+  "Vector of hline line numbers in the current table.
+Line numbers are counted from the beginning of the table.  This
+variable is initialized with `org-table-analyze'.")
 
 (defconst org-table-range-regexp
   
"@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(address@hidden([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
@@ -404,85 +480,33 @@ available parameters."
    "\\(" "@?[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" 
"\\$[a-zA-Z0-9]+" "\\)")
   "Match a range for reference display.")
 
-(defun org-table-colgroup-line-p (line)
-  "Is this a table line colgroup information?"
-  (save-match-data
-    (and (string-match "[<>]\\|&[lg]t;" line)
-        (string-match "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lgt&;]+\\)\\'"
-                      line)
-        (not (delq
-              nil
-              (mapcar
-               (lambda (s)
-                 (not (member s '("" "<" ">" "<>" "&lt;" "&gt;" "&lt;&gt;"))))
-               (org-split-string (match-string 1 line) "[ \t]*|[ \t]*")))))))
-
-(defun org-table-cookie-line-p (line)
-  "Is this a table line with only alignment/width cookies?"
-  (save-match-data
-    (and (string-match "[<>]\\|&[lg]t;" line)
-        (or (string-match
-             "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lrcgt&;]+\\)\\'" line)
-            (string-match "\\(\\`[ \t<>lrc0-9|gt&;]+\\'\\)" line))
-        (not (delq nil (mapcar
-                        (lambda (s)
-                          (not (or (equal s "")
-                                   (string-match
-                                    "\\`<\\([lrc]?[0-9]+\\|[lrc]\\)>\\'" s)
-                                   (string-match
-                                    "\\`&lt;\\([lrc]?[0-9]+\\|[lrc]\\)&gt;\\'"
-                                    s))))
-                        (org-split-string (match-string 1 line)
-                                          "[ \t]*|[ \t]*")))))))
-
-(defvar org-table-clean-did-remove-column nil) ; dynamically scoped
-(defun org-table-clean-before-export (lines &optional maybe-quoted)
-  "Check if the table has a marking column.
-If yes remove the column and the special lines."
-  (let ((special (if maybe-quoted
-                    "^[ \t]*| *\\\\?[#!$*_^/ ] *|"
-                  "^[ \t]*| *[#!$*_^/ ] *|"))
-       (ignore  (if maybe-quoted
-                    "^[ \t]*| *\\\\?[!$_^/] *|"
-                  "^[ \t]*| *[!$_^/] *|")))
-    (setq org-table-clean-did-remove-column
-         (not (memq nil
-                    (mapcar
-                     (lambda (line)
-                       (or (string-match org-table-hline-regexp line)
-                           (string-match special                line)))
-                     lines))))
-    (delq nil
-         (mapcar
-          (lambda (line)
-            (cond
-             ((or (org-table-colgroup-line-p line)  ;; colgroup info
-                  (org-table-cookie-line-p line)    ;; formatting cookies
-                  (and org-table-clean-did-remove-column
-                       (string-match ignore line))) ;; non-exportable data
-              nil)
-             ((and org-table-clean-did-remove-column
-                   (or (string-match "^\\([ \t]*\\)|-+\\+" line)
-                       (string-match "^\\([ \t]*\\)|[^|]*|" line)))
-              ;; remove the first column
-              (replace-match "\\1|" t nil line))
-             (t line)))
-          lines))))
-
 (defconst org-table-translate-regexp
   (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)")
   "Match a reference that needs translation, for reference display.")
 
+(defmacro org-table-save-field (&rest body)
+  "Save current field; execute BODY; restore field.
+Field is restored even in case of abnormal exit."
+  (declare (debug (body)))
+  (org-with-gensyms (line column)
+    `(let ((,line (copy-marker (line-beginning-position)))
+          (,column (org-table-current-column)))
+       (unwind-protect
+          (progn ,@body)
+        (goto-char ,line)
+        (org-table-goto-column ,column)
+        (set-marker ,line nil)))))
+
 ;;;###autoload
 (defun org-table-create-with-table.el ()
   "Use the table.el package to insert a new table.
-If there is already a table at point, convert between Org-mode tables
+If there is already a table at point, convert between Org tables
 and table.el tables."
   (interactive)
   (require 'table)
   (cond
    ((org-at-table.el-p)
-    (if (y-or-n-p "Convert table to Org-mode table? ")
+    (if (y-or-n-p "Convert table to Org table? ")
        (org-table-convert)))
    ((org-at-table-p)
     (when (y-or-n-p "Convert table to table.el table? ")
@@ -526,7 +550,7 @@ SIZE is a string Columns x Rows like for example \"3x2\"."
        (beginning-of-line 1)
       (newline))
     ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
-    (dotimes (i rows) (insert line))
+    (dotimes (_ rows) (insert line))
     (goto-char pos)
     (if (> rows 1)
        ;; Insert a hline after the first row.
@@ -539,15 +563,18 @@ SIZE is a string Columns x Rows like for example \"3x2\"."
 ;;;###autoload
 (defun org-table-convert-region (beg0 end0 &optional separator)
   "Convert region to a table.
+
 The region goes from BEG0 to END0, but these borders will be moved
 slightly, to make sure a beginning of line in the first line is included.
 
 SEPARATOR specifies the field separator in the lines.  It can have the
 following values:
 
-(4)      Use the comma as a field separator
-(16)     Use a TAB as field separator
-integer  When a number, use that many spaces as field separator
+(4)     Use the comma as a field separator
+(16)    Use a TAB as field separator
+(64)    Prompt for a regular expression as field separator
+integer  When a number, use that many spaces, or a TAB, as field separator
+regexp   When a regular expression, use it to match the separator
 nil      When nil, the command tries to be smart and figure out the
          separator in the following way:
          - when each line contains a TAB, assume TAB-separated material
@@ -557,45 +584,52 @@ nil      When nil, the command tries to be smart and 
figure out the
   (let* ((beg (min beg0 end0))
         (end (max beg0 end0))
         re)
-    (goto-char beg)
-    (beginning-of-line 1)
-    (setq beg (point-marker))
-    (goto-char end)
-    (if (bolp) (backward-char 1) (end-of-line 1))
-    (setq end (point-marker))
-    ;; Get the right field separator
-    (unless separator
+    (if (> (count-lines beg end) org-table-convert-region-max-lines)
+       (user-error "Region is longer than `org-table-convert-region-max-lines' 
(%s) lines; not converting"
+                   org-table-convert-region-max-lines)
+      (if (equal separator '(64))
+         (setq separator (read-regexp "Regexp for field separator")))
       (goto-char beg)
-      (setq separator
+      (beginning-of-line 1)
+      (setq beg (point-marker))
+      (goto-char end)
+      (if (bolp) (backward-char 1) (end-of-line 1))
+      (setq end (point-marker))
+      ;; Get the right field separator
+      (unless separator
+       (goto-char beg)
+       (setq separator
+             (cond
+              ((not (re-search-forward "^[^\n\t]+$" end t)) '(16))
+              ((not (re-search-forward "^[^\n,]+$" end t)) '(4))
+              (t 1))))
+      (goto-char beg)
+      (if (equal separator '(4))
+         (while (< (point) end)
+           ;; parse the csv stuff
            (cond
-            ((not (re-search-forward "^[^\n\t]+$" end t)) '(16))
-            ((not (re-search-forward "^[^\n,]+$" end t)) '(4))
-            (t 1))))
-    (goto-char beg)
-    (if (equal separator '(4))
-       (while (< (point) end)
-         ;; parse the csv stuff
-         (cond
-          ((looking-at "^") (insert "| "))
-          ((looking-at "[ \t]*$") (replace-match " |") (beginning-of-line 2))
-          ((looking-at "[ \t]*\"\\([^\"\n]*\\)\"")
-           (replace-match "\\1")
-           (if (looking-at "\"") (insert "\"")))
-          ((looking-at "[^,\n]+") (goto-char (match-end 0)))
-          ((looking-at "[ \t]*,") (replace-match " | "))
-          (t (beginning-of-line 2))))
-      (setq re (cond
-               ((equal separator '(4)) "^\\|\"?[ \t]*,[ \t]*\"?")
-               ((equal separator '(16)) "^\\|\t")
-               ((integerp separator)
-                (if (< separator 1)
-                    (user-error "Number of spaces in separator must be >= 1")
-                  (format "^ *\\| *\t *\\| \\{%d,\\}" separator)))
-               (t (error "This should not happen"))))
-      (while (re-search-forward re end t)
-       (replace-match "| " t t)))
-    (goto-char beg)
-    (org-table-align)))
+            ((looking-at "^") (insert "| "))
+            ((looking-at "[ \t]*$") (replace-match " |") (beginning-of-line 2))
+            ((looking-at "[ \t]*\"\\([^\"\n]*\\)\"")
+             (replace-match "\\1")
+             (if (looking-at "\"") (insert "\"")))
+            ((looking-at "[^,\n]+") (goto-char (match-end 0)))
+            ((looking-at "[ \t]*,") (replace-match " | "))
+            (t (beginning-of-line 2))))
+       (setq re (cond
+                 ((equal separator '(4)) "^\\|\"?[ \t]*,[ \t]*\"?")
+                 ((equal separator '(16)) "^\\|\t")
+                 ((integerp separator)
+                  (if (< separator 1)
+                      (user-error "Number of spaces in separator must be >= 1")
+                    (format "^ *\\| *\t *\\| \\{%d,\\}" separator)))
+                 ((stringp separator)
+                  (format "^ *\\|%s" separator))
+                 (t (error "This should not happen"))))
+       (while (re-search-forward re end t)
+         (replace-match "| " t t)))
+      (goto-char beg)
+      (org-table-align))))
 
 ;;;###autoload
 (defun org-table-import (file arg)
@@ -611,8 +645,6 @@ are found, lines will be split on whitespace into fields."
     (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
 
 
-(defvar org-table-last-alignment)
-(defvar org-table-last-column-widths)
 ;;;###autoload
 (defun org-table-export (&optional file format)
   "Export table to a file, with configurable format.
@@ -630,77 +662,61 @@ extension of the given file name, and finally on the 
variable
 `org-table-export-default-format'."
   (interactive)
   (unless (org-at-table-p) (user-error "No table at point"))
-  (org-table-align) ;; make sure we have everything we need
-  (let* ((beg (org-table-begin))
-        (end (org-table-end))
-        (txt (buffer-substring-no-properties beg end))
-        (file (or file (org-entry-get beg "TABLE_EXPORT_FILE" t)))
-        (formats '("orgtbl-to-tsv" "orgtbl-to-csv"
-                   "orgtbl-to-latex" "orgtbl-to-html"
-                   "orgtbl-to-generic" "orgtbl-to-texinfo"
-                   "orgtbl-to-orgtbl"))
-        (format (or format
-                    (org-entry-get beg "TABLE_EXPORT_FORMAT" t)))
-        buf deffmt-readable fileext)
+  (org-table-align)           ; Make sure we have everything we need.
+  (let ((file (or file (org-entry-get (point) "TABLE_EXPORT_FILE" t))))
     (unless file
       (setq file (read-file-name "Export table to: "))
       (unless (or (not (file-exists-p file))
                  (y-or-n-p (format "Overwrite file %s? " file)))
        (user-error "File not written")))
-    (if (file-directory-p file)
-       (user-error "This is a directory path, not a file"))
-    (if (and (buffer-file-name)
-            (equal (file-truename file)
-                   (file-truename (buffer-file-name))))
-       (user-error "Please specify a file name that is different from 
current"))
-    (setq fileext (concat (file-name-extension file) "$"))
-    (unless format
-      (setq deffmt-readable
-           (or (car (delq nil (mapcar (lambda(f) (if (string-match fileext f) 
f)) formats)))
-               org-table-export-default-format))
-      (while (string-match "\t" deffmt-readable)
-       (setq deffmt-readable (replace-match "\\t" t t deffmt-readable)))
-      (while (string-match "\n" deffmt-readable)
-       (setq deffmt-readable (replace-match "\\n" t t deffmt-readable)))
-      (setq format (org-completing-read "Format: " formats nil nil 
deffmt-readable)))
-    (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format)
-       (let* ((transform (intern (match-string 1 format)))
-              (params (if (match-end 2)
-                          (read (concat "(" (match-string 2 format) ")"))))
-              (skip (plist-get params :skip))
-              (skipcols (plist-get params :skipcols))
-              (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ 
\t]*")))
-              (lines (org-table-clean-before-export lines))
-              (i0 (if org-table-clean-did-remove-column 2 1))
-              (table (mapcar
-                      (lambda (x)
-                        (if (string-match org-table-hline-regexp x)
-                            'hline
-                          (org-remove-by-index
-                           (org-split-string (org-trim x) "\\s-*|\\s-*")
-                           skipcols i0)))
-                      lines))
-              (fun (if (= i0 2) 'cdr 'identity))
-              (org-table-last-alignment
-               (org-remove-by-index (funcall fun org-table-last-alignment)
-                                    skipcols i0))
-              (org-table-last-column-widths
-               (org-remove-by-index (funcall fun org-table-last-column-widths)
-                                    skipcols i0)))
-
-         (unless (fboundp transform)
-           (user-error "No such transformation function %s" transform))
-         (setq txt (funcall transform table params))
-
-         (with-current-buffer (find-file-noselect file)
-           (setq buf (current-buffer))
-           (erase-buffer)
-           (fundamental-mode)
-           (insert txt "\n")
-           (save-buffer))
-         (kill-buffer buf)
-         (message "Export done."))
-      (user-error "TABLE_EXPORT_FORMAT invalid"))))
+    (when (file-directory-p file)
+      (user-error "This is a directory path, not a file"))
+    (when (and (buffer-file-name (buffer-base-buffer))
+              (file-equal-p
+               (file-truename file)
+               (file-truename (buffer-file-name (buffer-base-buffer)))))
+      (user-error "Please specify a file name that is different from current"))
+    (let ((fileext (concat (file-name-extension file) "$"))
+         (format (or format (org-entry-get (point) "TABLE_EXPORT_FORMAT" t))))
+      (unless format
+       (let* ((formats '("orgtbl-to-tsv" "orgtbl-to-csv" "orgtbl-to-latex"
+                         "orgtbl-to-html" "orgtbl-to-generic"
+                         "orgtbl-to-texinfo" "orgtbl-to-orgtbl"
+                         "orgtbl-to-unicode"))
+              (deffmt-readable
+                (replace-regexp-in-string
+                 "\t" "\\t"
+                 (replace-regexp-in-string
+                  "\n" "\\n"
+                  (or (car (delq nil
+                                 (mapcar
+                                  (lambda (f)
+                                    (and (string-match-p fileext f) f))
+                                  formats)))
+                      org-table-export-default-format)
+                  t t) t t)))
+         (setq format
+               (org-completing-read
+                "Format: " formats nil nil deffmt-readable))))
+      (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format)
+         (let ((transform (intern (match-string 1 format)))
+               (params (and (match-end 2)
+                            (read (concat "(" (match-string 2 format) ")"))))
+               (table (org-table-to-lisp
+                       (buffer-substring-no-properties
+                        (org-table-begin) (org-table-end)))))
+           (unless (fboundp transform)
+             (user-error "No such transformation function %s" transform))
+           (let (buf)
+             (with-current-buffer (find-file-noselect file)
+               (setq buf (current-buffer))
+               (erase-buffer)
+               (fundamental-mode)
+               (insert (funcall transform table params) "\n")
+               (save-buffer))
+             (kill-buffer buf))
+           (message "Export done."))
+       (user-error "TABLE_EXPORT_FORMAT invalid")))))
 
 (defvar org-table-aligned-begin-marker (make-marker)
   "Marker at the beginning of the table last aligned.
@@ -714,13 +730,11 @@ This is being used to correctly align a single field 
after TAB or RET.")
 (defvar org-table-last-column-widths nil
   "List of max width of fields in each column.
 This is being used to correctly align a single field after TAB or RET.")
-(defvar org-table-formula-debug nil
+(defvar-local org-table-formula-debug nil
   "Non-nil means debug table formulas.
 When nil, simply write \"#ERROR\" in corrupted fields.")
-(make-variable-buffer-local 'org-table-formula-debug)
-(defvar org-table-overlay-coordinates nil
+(defvar-local org-table-overlay-coordinates nil
   "Overlay coordinates after each align of a table.")
-(make-variable-buffer-local 'org-table-overlay-coordinates)
 
 (defvar org-last-recalc-line nil)
 (defvar org-table-do-narrow t)   ; for dynamic scoping
@@ -731,216 +745,198 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
 (defun org-table-align ()
   "Align the table at point by aligning all vertical bars."
   (interactive)
-  (let* (
-        ;; Limits of table
-        (beg (org-table-begin))
-        (end (org-table-end))
-        ;; Current cursor position
-        (linepos (org-current-line))
-        (colpos (org-table-current-column))
-        (winstart (window-start))
-        (winstartline (org-current-line (min winstart (1- (point-max)))))
-        lines (new "") lengths l typenums ty fields maxfields i
-        column
-        (indent "") cnt frac
-        rfmt hfmt
-        (spaces '(1 . 1))
-        (sp1 (car spaces))
-        (sp2 (cdr spaces))
-        (rfmt1 (concat
-                (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
-        (hfmt1 (concat
-                (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
-        emptystrings links dates emph raise narrow
-        falign falign1 fmax f1 len c e space)
-    (untabify beg end)
-    (remove-text-properties beg end '(org-cwidth t org-dwidth t display t))
-    ;; Check if we have links or dates
-    (goto-char beg)
-    (setq links (re-search-forward org-bracket-link-regexp end t))
-    (goto-char beg)
-    (setq emph (and org-hide-emphasis-markers
-                   (re-search-forward org-emph-re end t)))
-    (goto-char beg)
-    (setq raise (and org-use-sub-superscripts
-                    (re-search-forward org-match-substring-regexp end t)))
-    (goto-char beg)
-    (setq dates (and org-display-custom-times
-                    (re-search-forward org-ts-regexp-both end t)))
-    ;; Make sure the link properties are right
-    (when links (goto-char beg) (while (org-activate-bracket-links end)))
-    ;; Make sure the date properties are right
-    (when dates (goto-char beg) (while (org-activate-dates end)))
-    (when emph (goto-char beg) (while (org-do-emphasis-faces end)))
-    (when raise (goto-char beg) (while (org-raise-scripts end)))
-
-    ;; Check if we are narrowing any columns
-    (goto-char beg)
-    (setq narrow (and org-table-do-narrow
-                     org-format-transports-properties-p
-                     (re-search-forward "<[lrc]?[0-9]+>" end t)))
-    (goto-char beg)
-    (setq falign (re-search-forward "<[lrc][0-9]*>" end t))
-    (goto-char beg)
-    ;; Get the rows
-    (setq lines (org-split-string
-                (buffer-substring beg end) "\n"))
-    ;; Store the indentation of the first line
-    (if (string-match "^ *" (car lines))
-       (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
-    ;; Mark the hlines by setting the corresponding element to nil
-    ;; At the same time, we remove trailing space.
-    (setq lines (mapcar (lambda (l)
-                         (if (string-match "^ *|-" l)
-                             nil
-                           (if (string-match "[ \t]+$" l)
-                               (substring l 0 (match-beginning 0))
-                             l)))
-                       lines))
-    ;; Get the data fields by splitting the lines.
-    (setq fields (mapcar
-                 (lambda (l)
-                   (org-split-string l " *| *"))
-                 (delq nil (copy-sequence lines))))
-    ;; How many fields in the longest line?
-    (condition-case nil
-       (setq maxfields (apply 'max (mapcar 'length fields)))
-      (error
-       (kill-region beg end)
-       (org-table-create org-table-default-size)
-       (user-error "Empty table - created default table")))
-    ;; A list of empty strings to fill any short rows on output
-    (setq emptystrings (make-list maxfields ""))
-    ;; Check for special formatting.
-    (setq i -1)
-    (while (< (setq i (1+ i)) maxfields)   ;; Loop over all columns
-      (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
-      ;; Check if there is an explicit width specified
-      (setq fmax nil)
-      (when (or narrow falign)
-       (setq c column fmax nil falign1 nil)
-       (while c
-         (setq e (pop c))
-         (when (and (stringp e) (string-match "^<\\([lrc]\\)?\\([0-9]+\\)?>$" 
e))
-           (if (match-end 1) (setq falign1 (match-string 1 e)))
-           (if (and org-table-do-narrow (match-end 2))
-               (setq fmax (string-to-number (match-string 2 e)) c nil))))
-       ;; Find fields that are wider than fmax, and shorten them
-       (when fmax
-         (loop for xx in column do
-               (when (and (stringp xx)
-                          (> (org-string-width xx) fmax))
-                 (org-add-props xx nil
-                   'help-echo
-                   (concat "Clipped table field, use C-c ` to edit.  Full 
value is:\n" (org-no-properties (copy-sequence xx))))
-                 (setq f1 (min fmax (or (string-match org-bracket-link-regexp 
xx) fmax)))
-                 (unless (> f1 1)
-                   (user-error "Cannot narrow field starting with wide link 
\"%s\""
-                          (match-string 0 xx)))
-                 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
-                 (add-text-properties (- f1 2) f1
-                                      (list 'display org-narrow-column-arrow)
-                                      xx)))))
-      ;; Get the maximum width for each column
-      (push (apply 'max (or fmax 1) 1 (mapcar 'org-string-width column))
-           lengths)
-      ;; Get the fraction of numbers, to decide about alignment of the column
-      (if falign1
-         (push (equal (downcase falign1) "r") typenums)
-       (setq cnt 0 frac 0.0)
-       (loop for x in column do
-             (if (equal x "")
-                 nil
-               (setq frac ( / (+ (* frac cnt)
-                                 (if (string-match org-table-number-regexp x) 
1 0))
-                              (setq cnt (1+ cnt))))))
-       (push (>= frac org-table-number-fraction) typenums)))
-    (setq lengths (nreverse lengths) typenums (nreverse typenums))
-
-    ;; Store the alignment of this table, for later editing of single fields
-    (setq org-table-last-alignment typenums
-         org-table-last-column-widths lengths)
-
-    ;; With invisible characters, `format' does not get the field width right
-    ;; So we need to make these fields wide by hand.
-    (when (or links emph raise)
-      (loop for i from 0 upto (1- maxfields) do
-           (setq len (nth i lengths))
-           (loop for j from 0 upto (1- (length fields)) do
-                 (setq c (nthcdr i (car (nthcdr j fields))))
-                 (if (and (stringp (car c))
-                          (or (text-property-any 0 (length (car c))
-                                                 'invisible 'org-link (car c))
-                              (text-property-any 0 (length (car c))
-                                                 'org-dwidth t (car c)))
-                          (< (org-string-width (car c)) len))
-                     (progn
-                       (setq space (make-string (- len (org-string-width (car 
c))) ?\ ))
-                       (setcar c (if (nth i typenums)
-                                     (concat space (car c))
-                                   (concat (car c) space))))))))
-
-    ;; Compute the formats needed for output of the table
-    (setq rfmt (concat indent "|") hfmt (concat indent "|"))
-    (while (setq l (pop lengths))
-      (setq ty (if (pop typenums) "" "-")) ; number types flushright
-      (setq rfmt (concat rfmt (format rfmt1 ty l))
-           hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
-    (setq rfmt (concat rfmt "\n")
-         hfmt (concat (substring hfmt 0 -1) "|\n"))
-
-    (setq new (mapconcat
-              (lambda (l)
-                (if l (apply 'format rfmt
-                             (append (pop fields) emptystrings))
-                  hfmt))
-              lines ""))
-    (move-marker org-table-aligned-begin-marker (point))
-    (insert new)
-    ;; Replace the old one
-    (delete-region (point) end)
-    (move-marker end nil)
-    (move-marker org-table-aligned-end-marker (point))
-    (when (and orgtbl-mode (not (derived-mode-p 'org-mode)))
-      (goto-char org-table-aligned-begin-marker)
-      (while (org-hide-wide-columns org-table-aligned-end-marker)))
-    ;; Try to move to the old location
-    (org-goto-line winstartline)
-    (setq winstart (point-at-bol))
-    (org-goto-line linepos)
-    (when (eq (window-buffer (selected-window)) (current-buffer))
-      (set-window-start (selected-window) winstart 'noforce))
-    (org-table-goto-column colpos)
-    (and org-table-overlay-coordinates (org-table-overlay-coordinates))
-    (setq org-table-may-need-update nil)
-    ))
+  (let* ((beg (org-table-begin))
+         (end (copy-marker (org-table-end))))
+    (org-table-save-field
+     ;; Make sure invisible characters in the table are at the right
+     ;; place since column widths take them into account.
+     (font-lock-fontify-region beg end)
+     (move-marker org-table-aligned-begin-marker beg)
+     (move-marker org-table-aligned-end-marker end)
+     (goto-char beg)
+     (let* ((indent (progn (looking-at "[ \t]*") (match-string 0)))
+            ;; Table's rows.  Separators are replaced by nil.  Trailing
+            ;; spaces are also removed.
+            (lines (mapcar (lambda (l)
+                             (and (not (string-match-p "\\`[ \t]*|-" l))
+                                  (let ((l (org-trim l)))
+                                    (remove-text-properties
+                                     0 (length l) '(display t org-cwidth t) l)
+                                    l)))
+                           (org-split-string (buffer-substring beg end) "\n")))
+            ;; Get the data fields by splitting the lines.
+            (fields (mapcar (lambda (l) (org-split-string l " *| *"))
+                            (remq nil lines)))
+            ;; Compute number of fields in the longest line.  If the
+            ;; table contains no field, create a default table.
+            (maxfields (if fields (apply #'max (mapcar #'length fields))
+                         (kill-region beg end)
+                         (org-table-create org-table-default-size)
+                         (user-error "Empty table - created default table")))
+            ;; A list of empty strings to fill any short rows on output.
+            (emptycells (make-list maxfields ""))
+            lengths typenums)
+       ;; Check for special formatting.
+       (dotimes (i maxfields)
+         (let ((column (mapcar (lambda (x) (or (nth i x) "")) fields))
+               fmax falign)
+           ;; Look for an explicit width or alignment.
+           (when (save-excursion
+                   (or (re-search-forward "| *<[lrc][0-9]*> *\\(|\\|$\\)" end 
t)
+                       (and org-table-do-narrow
+                            (re-search-forward
+                             "| *<[lrc]?[0-9]+> *\\(|\\|$\\)" end t))))
+             (catch :exit
+               (dolist (cell column)
+                 (when (string-match "\\`<\\([lrc]\\)?\\([0-9]+\\)?>\\'" cell)
+                   (when (match-end 1) (setq falign (match-string 1 cell)))
+                   (when (and org-table-do-narrow (match-end 2))
+                     (setq fmax (string-to-number (match-string 2 cell))))
+                   (when (or falign fmax) (throw :exit nil)))))
+             ;; Find fields that are wider than FMAX, and shorten them.
+             (when fmax
+               (dolist (x column)
+                 (when (> (org-string-width x) fmax)
+                   (org-add-props x nil
+                     'help-echo
+                     (concat
+                     "Clipped table field, use `\\[org-table-edit-field]' to \
+edit.  Full value is:\n"
+                      (substring-no-properties x)))
+                   (let ((l (length x))
+                         (f1 (min fmax
+                                  (or (string-match org-bracket-link-regexp x)
+                                      fmax)))
+                         (f2 1))
+                     (unless (> f1 1)
+                       (user-error
+                        "Cannot narrow field starting with wide link \"%s\""
+                        (match-string 0 x)))
+                     (if (= (org-string-width x) l) (setq f2 f1)
+                       (setq f2 1)
+                       (while (< (org-string-width (substring x 0 f2)) f1)
+                         (cl-incf f2)))
+                     (add-text-properties f2 l (list 'org-cwidth t) x)
+                     (add-text-properties
+                      (if (>= (string-width (substring x (1- f2) f2)) 2) (1- 
f2)
+                        (- f2 2))
+                      f2
+                      (list 'display org-narrow-column-arrow)
+                      x))))))
+           ;; Get the maximum width for each column
+           (push (apply #'max (or fmax 1) 1 (mapcar #'org-string-width column))
+                 lengths)
+           ;; Get the fraction of numbers among non-empty cells to
+           ;; decide about alignment of the column.
+           (if falign (push (equal (downcase falign) "r") typenums)
+             (let ((cnt 0)
+                   (frac 0.0))
+               (dolist (x column)
+                 (unless (equal x "")
+                   (setq frac
+                         (/ (+ (* frac cnt)
+                               (if (string-match-p org-table-number-regexp x)
+                                   1
+                                 0))
+                            (cl-incf cnt)))))
+               (push (>= frac org-table-number-fraction) typenums)))))
+       (setq lengths (nreverse lengths))
+       (setq typenums (nreverse typenums))
+       ;; Store alignment of this table, for later editing of single
+       ;; fields.
+       (setq org-table-last-alignment typenums)
+       (setq org-table-last-column-widths lengths)
+       ;; With invisible characters, `format' does not get the field
+       ;; width right So we need to make these fields wide by hand.
+       ;; Invisible characters may be introduced by fontified links,
+       ;; emphasis, macros or sub/superscripts.
+       (when (or (text-property-any beg end 'invisible 'org-link)
+                 (text-property-any beg end 'invisible t))
+         (dotimes (i maxfields)
+           (let ((len (nth i lengths)))
+             (dotimes (j (length fields))
+               (let* ((c (nthcdr i (nth j fields)))
+                      (cell (car c)))
+                 (when (and
+                        (stringp cell)
+                        (let ((l (length cell)))
+                          (or (text-property-any 0 l 'invisible 'org-link cell)
+                              (text-property-any beg end 'invisible t)))
+                        (< (org-string-width cell) len))
+                   (let ((s (make-string (- len (org-string-width cell)) ?\s)))
+                     (setcar c (if (nth i typenums) (concat s cell)
+                                 (concat cell s))))))))))
+
+       ;; Compute the formats needed for output of the table.
+       (let ((hfmt (concat indent "|"))
+             (rfmt (concat indent "|"))
+             (rfmt1 " %%%s%ds |")
+             (hfmt1 "-%s-+"))
+         (dolist (l lengths (setq hfmt (concat (substring hfmt 0 -1) "|")))
+           (let ((ty (if (pop typenums) "" "-"))) ; Flush numbers right.
+             (setq rfmt (concat rfmt (format rfmt1 ty l)))
+             (setq hfmt (concat hfmt (format hfmt1 (make-string l ?-))))))
+         ;; Replace modified lines only.  Check not only contents, but
+         ;; also columns' width.
+         (dolist (l lines)
+           (let ((line
+                  (if l (apply #'format rfmt (append (pop fields) emptycells))
+                    hfmt))
+                 (previous (buffer-substring (point) (line-end-position))))
+             (if (and (equal previous line)
+                      (let ((a 0)
+                            (b 0))
+                        (while (and (progn
+                                      (setq a (next-single-property-change
+                                               a 'org-cwidth previous))
+                                      (setq b (next-single-property-change
+                                               b 'org-cwidth line)))
+                                    (eq a b)))
+                        (eq a b)))
+                 (forward-line)
+               (insert line "\n")
+               (delete-region (point) (line-beginning-position 2))))))
+       (when (and orgtbl-mode (not (derived-mode-p 'org-mode)))
+         (goto-char org-table-aligned-begin-marker)
+         (while (org-hide-wide-columns org-table-aligned-end-marker)))
+       (set-marker end nil)
+       (when org-table-overlay-coordinates (org-table-overlay-coordinates))
+       (setq org-table-may-need-update nil)))))
 
 ;;;###autoload
 (defun org-table-begin (&optional table-type)
   "Find the beginning of the table and return its position.
-With argument TABLE-TYPE, go to the beginning of a table.el-type table."
-  (save-excursion
-    (if (not (re-search-backward
-             (if table-type org-table-any-border-regexp
-               org-table-border-regexp)
-             nil t))
-       (progn (goto-char (point-min)) (point))
-      (goto-char (match-beginning 0))
-      (beginning-of-line 2)
-      (point))))
+With a non-nil optional argument TABLE-TYPE, return the beginning
+of a table.el-type table.  This function assumes point is on
+a table."
+  (cond (table-type
+        (org-element-property :post-affiliated (org-element-at-point)))
+       ((save-excursion
+          (and (re-search-backward org-table-border-regexp nil t)
+               (line-beginning-position 2))))
+       (t (point-min))))
 
 ;;;###autoload
 (defun org-table-end (&optional table-type)
   "Find the end of the table and return its position.
-With argument TABLE-TYPE, go to the end of a table.el-type table."
+With a non-nil optional argument TABLE-TYPE, return the end of
+a table.el-type table.  This function assumes point is on
+a table."
   (save-excursion
-    (if (not (re-search-forward
-             (if table-type org-table-any-border-regexp
-               org-table-border-regexp)
-             nil t))
-       (goto-char (point-max))
-      (goto-char (match-beginning 0)))
-    (point-marker)))
+    (cond (table-type
+          (goto-char (org-element-property :end (org-element-at-point)))
+          (skip-chars-backward " \t\n")
+          (line-beginning-position 2))
+         ((re-search-forward org-table-border-regexp nil t)
+          (match-beginning 0))
+         ;; When the line right after the table is the last line in
+         ;; the buffer with trailing spaces but no final newline
+         ;; character, be sure to catch the correct ending at its
+         ;; beginning.  In any other case, ending is expected to be
+         ;; at point max.
+         (t (goto-char (point-max))
+            (skip-chars-backward " \t")
+            (if (bolp) (point) (line-end-position))))))
 
 ;;;###autoload
 (defun org-table-justify-field-maybe (&optional new)
@@ -950,38 +946,40 @@ Optional argument NEW may specify text to replace the 
current field content."
    ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
    ((org-at-table-hline-p))
    ((and (not new)
-        (or (not (equal (marker-buffer org-table-aligned-begin-marker)
-                        (current-buffer)))
+        (or (not (eq (marker-buffer org-table-aligned-begin-marker)
+                     (current-buffer)))
             (< (point) org-table-aligned-begin-marker)
             (>= (point) org-table-aligned-end-marker)))
-    ;; This is not the same table, force a full re-align
+    ;; This is not the same table, force a full re-align.
     (setq org-table-may-need-update t))
-   (t ;; realign the current field, based on previous full realign
-    (let* ((pos (point)) s
-          (col (org-table-current-column))
-          (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
-          l f n o e)
+   (t
+    ;; Realign the current field, based on previous full realign.
+    (let ((pos (point))
+         (col (org-table-current-column)))
       (when (> col 0)
-       (skip-chars-backward "^|\n")
-       (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
-           (progn
-             (setq s (match-string 1)
-                   o (match-string 0)
-                   l (max 1 (- (match-end 0) (match-beginning 0) 3))
-                   e (not (= (match-beginning 2) (match-end 2))))
-             (setq f (format (if num " %%%ds %s" " %%-%ds %s")
-                             l (if e "|" (setq org-table-may-need-update t) 
""))
-                   n (format f s))
-             (if new
-                 (if (<= (length new) l)      ;; FIXME: length -> str-width?
-                     (setq n (format f new))
-                   (setq n (concat new "|") org-table-may-need-update t)))
-             (if (equal (string-to-char n) ?-) (setq n (concat " " n)))
-             (or (equal n o)
-                 (let (org-table-may-need-update)
-                   (replace-match n t t))))
-         (setq org-table-may-need-update t))
-       (goto-char pos))))))
+       (skip-chars-backward "^|")
+       (if (not (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)"))
+           (setq org-table-may-need-update t)
+         (let* ((numbers? (nth (1- col) org-table-last-alignment))
+                (cell (match-string 0))
+                (field (match-string 1))
+                (len (max 1 (- (org-string-width cell) 3)))
+                (properly-closed? (/= (match-beginning 2) (match-end 2)))
+                (fmt (format (if numbers? " %%%ds %s" " %%-%ds %s")
+                             len
+                             (if properly-closed? "|"
+                               (setq org-table-may-need-update t)
+                               "")))
+                (new-cell
+                 (cond ((not new) (format fmt field))
+                       ((<= (org-string-width new) len) (format fmt new))
+                       (t
+                        (setq org-table-may-need-update t)
+                        (format " %s |" new)))))
+           (unless (equal new-cell cell)
+             (let (org-table-may-need-update)
+               (replace-match new-cell t t)))
+           (goto-char pos))))))))
 
 ;;;###autoload
 (defun org-table-next-field ()
@@ -1036,9 +1034,10 @@ Before doing so, re-align the table if necessary."
       (goto-char (match-end 0))))
 
 (defun org-table-beginning-of-field (&optional n)
-  "Move to the end of the current table field.
-If already at or after the end, move to the end of the next table field.
-With numeric argument N, move N-1 fields forward first."
+  "Move to the beginning of the current table field.
+If already at or before the beginning, move to the beginning of the
+previous field.
+With numeric argument N, move N-1 fields backward first."
   (interactive "p")
   (let ((pos (point)))
     (while (> n 1)
@@ -1051,10 +1050,9 @@ With numeric argument N, move N-1 fields forward first."
     (if (>= (point) pos) (org-table-beginning-of-field 2))))
 
 (defun org-table-end-of-field (&optional n)
-  "Move to the beginning of the current table field.
-If already at or before the beginning, move to the beginning of the
-previous field.
-With numeric argument N, move N-1 fields backward first."
+  "Move to the end of the current table field.
+If already at or after the end, move to the end of the next table field.
+With numeric argument N, move N-1 fields forward first."
   (interactive "p")
   (let ((pos (point)))
     (while (> n 1)
@@ -1093,30 +1091,36 @@ Before doing so, re-align the table if necessary."
 
 ;;;###autoload
 (defun org-table-copy-down (n)
-  "Copy a field down in the current column.
-If the field at the cursor is empty, copy into it the content of
-the nearest non-empty field above.  With argument N, use the Nth
-non-empty field.  If the current field is not empty, it is copied
-down to the next row, and the cursor is moved with it.
-Therefore, repeating this command causes the column to be filled
-row-by-row.
+  "Copy the value of the current field one row below.
+
+If the field at the cursor is empty, copy the content of the
+nearest non-empty field above.  With argument N, use the Nth
+non-empty field.
+
+If the current field is not empty, it is copied down to the next
+row, and the cursor is moved with it.  Therefore, repeating this
+command causes the column to be filled row-by-row.
+
 If the variable `org-table-copy-increment' is non-nil and the
 field is an integer or a timestamp, it will be incremented while
-copying.  In the case of a timestamp, increment by one day."
+copying.  By default, increment by the difference between the
+value in the current field and the one in the field above.  To
+increment using a fixed integer, set `org-table-copy-increment'
+to a number.  In the case of a timestamp, increment by days."
   (interactive "p")
   (let* ((colpos (org-table-current-column))
         (col (current-column))
         (field (save-excursion (org-table-get-field)))
+        (field-up (or (save-excursion
+                        (org-table-get (1- (org-table-current-line))
+                                       (org-table-current-column))) ""))
         (non-empty (string-match "[^ \t]" field))
+        (non-empty-up (string-match "[^ \t]" field-up))
         (beg (org-table-begin))
         (orig-n n)
-        txt)
+        txt txt-up inc)
     (org-table-check-inside-data-field)
-    (if non-empty
-       (progn
-         (setq txt (org-trim field))
-         (org-table-next-row)
-         (org-table-blank-field))
+    (if (not non-empty)
       (save-excursion
        (setq txt
              (catch 'exit
@@ -1127,35 +1131,60 @@ copying.  In the case of a timestamp, increment by one 
day."
                  (if (and (looking-at
                            "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
                           (<= (setq n (1- n)) 0))
-                     (throw 'exit (match-string 1))))))))
-    (if txt
-       (progn
-         (if (and org-table-copy-increment
-                  (not (equal orig-n 0))
-                  (string-match "^[0-9]+$" txt)
-                  (< (string-to-number txt) 100000000))
-             (setq txt (format "%d" (+ (string-to-number txt) 1))))
-         (insert txt)
-         (org-move-to-column col)
-         (if (and org-table-copy-increment (org-at-timestamp-p t))
-             (org-timestamp-up-day)
-           (org-table-maybe-recalculate-line))
-         (org-table-align)
-         (org-move-to-column col))
-      (user-error "No non-empty field found"))))
+                     (throw 'exit (match-string 1))))))
+       (setq field-up
+             (catch 'exit
+               (while (progn (beginning-of-line 1)
+                             (re-search-backward org-table-dataline-regexp
+                                                 beg t))
+                 (org-table-goto-column colpos t)
+                 (if (and (looking-at
+                           "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
+                          (<= (setq n (1- n)) 0))
+                     (throw 'exit (match-string 1))))))
+       (setq non-empty-up (and field-up (string-match "[^ \t]" field-up))))
+      ;; Above field was not empty, go down to the next row
+      (setq txt (org-trim field))
+      (org-table-next-row)
+      (org-table-blank-field))
+    (if non-empty-up (setq txt-up (org-trim field-up)))
+    (setq inc (cond
+              ((numberp org-table-copy-increment) org-table-copy-increment)
+              (txt-up (cond ((and (string-match org-ts-regexp3 txt-up)
+                                  (string-match org-ts-regexp3 txt))
+                             (- (org-time-string-to-absolute txt)
+                                (org-time-string-to-absolute txt-up)))
+                            ((string-match org-ts-regexp3 txt) 1)
+                            ((string-match 
"\\([-+]\\)?[0-9]+\\(?:\.[0-9]+\\)?" txt-up)
+                             (- (string-to-number txt)
+                                (string-to-number (match-string 0 txt-up))))
+                            (t 1)))
+              (t 1)))
+    (if (not txt)
+       (user-error "No non-empty field found")
+      (if (and org-table-copy-increment
+              (not (equal orig-n 0))
+              (string-match-p "^[-+^/*0-9eE.]+$" txt)
+              (< (string-to-number txt) 100000000))
+         (setq txt (calc-eval (concat txt "+" (number-to-string inc)))))
+      (insert txt)
+      (org-move-to-column col)
+      (if (and org-table-copy-increment (org-at-timestamp-p t))
+         (org-timestamp-up-day inc)
+       (org-table-maybe-recalculate-line))
+      (org-table-align)
+      (org-move-to-column col))))
 
 (defun org-table-check-inside-data-field (&optional noerror)
   "Is point inside a table data field?
 I.e. not on a hline or before the first or after the last column?
 This actually throws an error, so it aborts the current command."
-  (if (or (not (org-at-table-p))
-         (= (org-table-current-column) 0)
-         (org-at-table-hline-p)
-         (looking-at "[ \t]*$"))
-      (if noerror
-         nil
-       (user-error "Not in table data field"))
-    t))
+  (cond ((and (org-at-table-p)
+             (not (save-excursion (skip-chars-backward " \t") (bolp)))
+             (not (org-at-table-hline-p))
+             (not (looking-at "[ \t]*$"))))
+       (noerror nil)
+       (t (user-error "Not in table data field"))))
 
 (defvar org-table-clip nil
   "Clipboard for table regions.")
@@ -1166,7 +1195,7 @@ If LINE is larger than the number of data lines in the 
table, the function
 returns nil.  However, if COLUMN is too large, we will simply return an
 empty string.
 If LINE is nil, use the current line.
-If column is nil, use the current column."
+If COLUMN is nil, use the current column."
   (setq column (or column (org-table-current-column)))
   (save-excursion
     (and (or (not line) (org-table-goto-line line))
@@ -1206,7 +1235,7 @@ Return t when the line exists, nil if it does not exist."
   "Blank the current table field or active region."
   (interactive)
   (org-table-check-inside-data-field)
-  (if (and (org-called-interactively-p 'any) (org-region-active-p))
+  (if (and (called-interactively-p 'any) (org-region-active-p))
       (let (org-table-clip)
        (org-table-cut-region (region-beginning) (region-end)))
     (skip-chars-backward "^|")
@@ -1221,52 +1250,53 @@ Return t when the line exists, nil if it does not 
exist."
 
 (defun org-table-get-field (&optional n replace)
   "Return the value of the field in column N of current row.
-N defaults to current field.
-If REPLACE is a string, replace field with this value.  The return value
-is always the old value."
-  (and n (org-table-goto-column n))
+N defaults to current column.  If REPLACE is a string, replace
+field with this value.  The return value is always the old
+value."
+  (when n (org-table-goto-column n))
   (skip-chars-backward "^|\n")
-  (backward-char 1)
-  (if (looking-at "|[^|\r\n]*")
-      (let* ((pos (match-beginning 0))
-            (val (buffer-substring (1+ pos) (match-end 0))))
-       (if replace
-           (replace-match (concat "|" (if (equal replace "") " " replace))
-                          t t))
-       (goto-char (min (point-at-eol) (+ 2 pos)))
-       val)
-    (forward-char 1) ""))
+  (if (or (bolp) (looking-at-p "[ \t]*$"))
+      ;; Before first column or after last one.
+      ""
+    (looking-at "[^|\r\n]*")
+    (let* ((pos (match-beginning 0))
+          (val (buffer-substring pos (match-end 0))))
+      (when replace
+       (replace-match (if (equal replace "") " " replace) t t))
+      (goto-char (min (line-end-position) (1+ pos)))
+      val)))
 
 ;;;###autoload
-(defun org-table-field-info (arg)
+(defun org-table-field-info (_arg)
   "Show info about the current field, and highlight any reference at point."
   (interactive "P")
   (unless (org-at-table-p) (user-error "Not at a table"))
-  (org-table-get-specials)
+  (org-table-analyze)
   (save-excursion
     (let* ((pos (point))
           (col (org-table-current-column))
           (cname (car (rassoc (int-to-string col) org-table-column-names)))
-          (name (car (rassoc (list (org-current-line) col)
+          (name (car (rassoc (list (count-lines org-table-current-begin-pos
+                                                (line-beginning-position))
+                                   col)
                              org-table-named-field-locations)))
           (eql (org-table-expand-lhs-ranges
                 (mapcar
                  (lambda (e)
-                   (cons (org-table-formula-handle-first/last-rc
-                          (car e)) (cdr e)))
+                   (cons (org-table-formula-handle-first/last-rc (car e))
+                         (cdr e)))
                  (org-table-get-stored-formulas))))
           (dline (org-table-current-dline))
           (ref (format "@%d$%d" dline col))
           (ref1 (org-table-convert-refs-to-an ref))
+          ;; Prioritize field formulas over column formulas.
           (fequation (or (assoc name eql) (assoc ref eql)))
-          (cequation (assoc (int-to-string col) eql))
+          (cequation (assoc (format "$%d" col) eql))
           (eqn (or fequation cequation)))
-      (if (and eqn (get-text-property 0 :orig-eqn (car eqn)))
-         (setq eqn (get-text-property 0 :orig-eqn (car eqn))))
+      (let ((p (and eqn (get-text-property 0 :orig-eqn (car eqn)))))
+       (when p (setq eqn p)))
       (goto-char pos)
-      (condition-case nil
-         (org-table-show-reference 'local)
-       (error nil))
+      (ignore-errors (org-table-show-reference 'local))
       (message "line @%d, col $%s%s, ref @%d$%d or %s%s%s"
               dline col
               (if cname (concat " or $" cname) "")
@@ -1277,39 +1307,42 @@ is always the old value."
                   (concat ", formula: "
                           (org-table-formula-to-user
                            (concat
-                            (if (string-match "address@hidden"(car eqn)) "" 
"$")
+                            (if (or (string-prefix-p "$" (car eqn))
+                                    (string-prefix-p "@" (car eqn)))
+                                ""
+                              "$")
                             (car eqn) "=" (cdr eqn))))
                 "")))))
 
 (defun org-table-current-column ()
   "Find out which column we are in."
   (interactive)
-  (if (org-called-interactively-p 'any) (org-table-check-inside-data-field))
+  (when (called-interactively-p 'any) (org-table-check-inside-data-field))
   (save-excursion
-    (let ((cnt 0) (pos (point)))
-      (beginning-of-line 1)
-      (while (search-forward "|" pos t)
-       (setq cnt (1+ cnt)))
-      (when (org-called-interactively-p 'interactive)
-       (message "In table column %d" cnt))
-      cnt)))
+    (let ((column 0) (pos (point)))
+      (beginning-of-line)
+      (while (search-forward "|" pos t) (cl-incf column))
+      (when (called-interactively-p 'interactive)
+       (message "In table column %d" column))
+      column)))
 
 ;;;###autoload
 (defun org-table-current-dline ()
   "Find out what table data line we are in.
 Only data lines count for this."
   (interactive)
-  (when (org-called-interactively-p 'any)
+  (when (called-interactively-p 'any)
     (org-table-check-inside-data-field))
   (save-excursion
-    (let ((cnt 0) (pos (point)))
+    (let ((c 0)
+         (pos (point)))
       (goto-char (org-table-begin))
       (while (<= (point) pos)
-       (if (looking-at org-table-dataline-regexp) (setq cnt (1+ cnt)))
-       (beginning-of-line 2))
-      (when (org-called-interactively-p 'any)
-       (message "This is table line %d" cnt))
-      cnt)))
+       (when (looking-at org-table-dataline-regexp) (cl-incf c))
+       (forward-line))
+      (when (called-interactively-p 'any)
+       (message "This is table line %d" c))
+      c)))
 
 ;;;###autoload
 (defun org-table-goto-column (n &optional on-delim force)
@@ -1338,25 +1371,19 @@ However, when FORCE is non-nil, create new columns if 
necessary."
 (defun org-table-insert-column ()
   "Insert a new column into the table."
   (interactive)
-  (if (not (org-at-table-p))
-      (user-error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (org-table-find-dataline)
   (let* ((col (max 1 (org-table-current-column)))
         (beg (org-table-begin))
-        (end (org-table-end))
-        ;; Current cursor position
-        (linepos (org-current-line))
-        (colpos col))
-    (goto-char beg)
-    (while (< (point) end)
-      (if (org-at-table-hline-p)
-         nil
-       (org-table-goto-column col t)
-       (insert "|   "))
-      (beginning-of-line 2))
-    (move-marker end nil)
-    (org-goto-line linepos)
-    (org-table-goto-column colpos)
+        (end (copy-marker (org-table-end))))
+    (org-table-save-field
+     (goto-char beg)
+     (while (< (point) end)
+       (unless (org-at-table-hline-p)
+        (org-table-goto-column col t)
+        (insert "|   "))
+       (forward-line)))
+    (set-marker end nil)
     (org-table-align)
     (when (or (not org-table-fix-formulas-confirm)
              (funcall org-table-fix-formulas-confirm "Fix formulas? "))
@@ -1384,58 +1411,55 @@ However, when FORCE is non-nil, create new columns if 
necessary."
 
 (defun org-table-line-to-dline (line &optional above)
   "Turn a buffer line number into a data line number.
+
 If there is no data line in this line, return nil.
-If there is no matching dline (most likely te reference was a hline), the
-first dline below it is used.  When ABOVE is non-nil, the one above is used."
-  (catch 'exit
-    (let ((ll (length org-table-dlines))
-         i)
-      (if above
-         (progn
-           (setq i (1- ll))
-           (while (> i 0)
-             (if (<= (aref org-table-dlines i) line)
-                 (throw 'exit i))
-             (setq i (1- i))))
-       (setq i 1)
-       (while (< i ll)
-         (if (>= (aref org-table-dlines i) line)
-             (throw 'exit i))
-         (setq i (1+ i)))))
-    nil))
+
+If there is no matching dline (most likely the reference was
+a hline), the first dline below it is used.  When ABOVE is
+non-nil, the one above is used."
+  (let ((min 1)
+       (max (1- (length org-table-dlines))))
+    (cond ((or (> (aref org-table-dlines min) line)
+              (< (aref org-table-dlines max) line))
+          nil)
+         ((= (aref org-table-dlines max) line) max)
+         (t (catch 'exit
+              (while (> (- max min) 1)
+                (let* ((mean (/ (+ max min) 2))
+                       (v (aref org-table-dlines mean)))
+                  (cond ((= v line) (throw 'exit mean))
+                        ((> v line) (setq max mean))
+                        (t (setq min mean)))))
+              (if above min max))))))
 
 ;;;###autoload
 (defun org-table-delete-column ()
   "Delete a column from the table."
   (interactive)
-  (if (not (org-at-table-p))
-      (user-error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (org-table-find-dataline)
   (org-table-check-inside-data-field)
-  (let* ((col (org-table-current-column))
-        (beg (org-table-begin))
-        (end (org-table-end))
-        ;; Current cursor position
-        (linepos (org-current-line))
-        (colpos col))
-    (goto-char beg)
-    (while (< (point) end)
-      (if (org-at-table-hline-p)
-         nil
-       (org-table-goto-column col t)
-       (and (looking-at "|[^|\n]+|")
-            (replace-match "|")))
-      (beginning-of-line 2))
-    (move-marker end nil)
-    (org-goto-line linepos)
-    (org-table-goto-column colpos)
+  (let ((col (org-table-current-column))
+       (beg (org-table-begin))
+       (end (copy-marker (org-table-end))))
+    (org-table-save-field
+     (goto-char beg)
+     (while (< (point) end)
+       (if (org-at-table-hline-p)
+          nil
+        (org-table-goto-column col t)
+        (and (looking-at "|[^|\n]+|")
+             (replace-match "|")))
+       (forward-line)))
+    (set-marker end nil)
+    (org-table-goto-column (max 1 (1- col)))
     (org-table-align)
     (when (or (not org-table-fix-formulas-confirm)
              (funcall org-table-fix-formulas-confirm "Fix formulas? "))
-      (org-table-fix-formulas "$" (list (cons (number-to-string col) 
"INVALID"))
-                             col -1 col)
-      (org-table-fix-formulas "$LR" (list (cons (number-to-string col) 
"INVALID"))
-                             col -1 col))))
+      (org-table-fix-formulas
+       "$" (list (cons (number-to-string col) "INVALID")) col -1 col)
+      (org-table-fix-formulas
+       "$LR" (list (cons (number-to-string col) "INVALID")) col -1 col))))
 
 ;;;###autoload
 (defun org-table-move-column-right ()
@@ -1452,31 +1476,29 @@ first dline below it is used.  When ABOVE is non-nil, 
the one above is used."
 (defun org-table-move-column (&optional left)
   "Move the current column to the right.  With arg LEFT, move to the left."
   (interactive "P")
-  (if (not (org-at-table-p))
-      (user-error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (org-table-find-dataline)
   (org-table-check-inside-data-field)
   (let* ((col (org-table-current-column))
         (col1 (if left (1- col) col))
+        (colpos (if left (1- col) (1+ col)))
         (beg (org-table-begin))
-        (end (org-table-end))
-        ;; Current cursor position
-        (linepos (org-current-line))
-        (colpos (if left (1- col) (1+ col))))
-    (if (and left (= col 1))
-       (user-error "Cannot move column further left"))
-    (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
-       (user-error "Cannot move column further right"))
-    (goto-char beg)
-    (while (< (point) end)
-      (if (org-at-table-hline-p)
-         nil
-       (org-table-goto-column col1 t)
-       (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
-            (replace-match "|\\2|\\1|")))
-      (beginning-of-line 2))
-    (move-marker end nil)
-    (org-goto-line linepos)
+        (end (copy-marker (org-table-end))))
+    (when (and left (= col 1))
+      (user-error "Cannot move column further left"))
+    (when (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
+      (user-error "Cannot move column further right"))
+    (org-table-save-field
+     (goto-char beg)
+     (while (< (point) end)
+       (unless (org-at-table-hline-p)
+        (org-table-goto-column col1 t)
+        (when (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
+           (transpose-regions
+            (match-beginning 1) (match-end 1)
+            (match-beginning 2) (match-end 2))))
+       (forward-line)))
+    (set-marker end nil)
     (org-table-goto-column colpos)
     (org-table-align)
     (when (or (not org-table-fix-formulas-confirm)
@@ -1538,19 +1560,21 @@ first dline below it is used.  When ABOVE is non-nil, 
the one above is used."
   "Insert a new row above the current line into the table.
 With prefix ARG, insert below the current line."
   (interactive "P")
-  (if (not (org-at-table-p))
-      (user-error "Not at a table"))
-  (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
+  (unless (org-at-table-p) (user-error "Not at a table"))
+  (let* ((line (buffer-substring (line-beginning-position) 
(line-end-position)))
         (new (org-table-clean-line line)))
     ;; Fix the first field if necessary
     (if (string-match "^[ \t]*| *[#$] *|" line)
        (setq new (replace-match (match-string 0 line) t t new)))
     (beginning-of-line (if arg 2 1))
+    ;; Buffer may not end of a newline character, so ensure
+    ;; (beginning-of-line 2) moves point to a new line.
+    (unless (bolp) (insert "\n"))
     (let (org-table-may-need-update) (insert-before-markers new "\n"))
     (beginning-of-line 0)
-    (re-search-forward "| ?" (point-at-eol) t)
-    (and (or org-table-may-need-update org-table-overlay-coordinates)
-        (org-table-align))
+    (re-search-forward "| ?" (line-end-position) t)
+    (when (or org-table-may-need-update org-table-overlay-coordinates)
+      (org-table-align))
     (when (or (not org-table-fix-formulas-confirm)
              (funcall org-table-fix-formulas-confirm "Fix formulas? "))
       (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1))))
@@ -1563,7 +1587,7 @@ With prefix ABOVE, insert above the current line."
   (if (not (org-at-table-p))
       (user-error "Not at a table"))
   (when (eobp) (insert "\n") (backward-char 1))
-  (if (not (string-match "|[ \t]*$" (org-current-line-string)))
+  (if (not (string-match-p "|[ \t]*$" (org-current-line-string)))
       (org-table-align))
   (let ((line (org-table-clean-line
               (buffer-substring (point-at-bol) (point-at-eol))))
@@ -1623,7 +1647,8 @@ In particular, this does handle wide and invisible 
characters."
                              dline -1 dline))))
 
 ;;;###autoload
-(defun org-table-sort-lines (with-case &optional sorting-type)
+(defun org-table-sort-lines
+    (&optional with-case sorting-type getkey-func compare-func interactive?)
   "Sort table lines according to the column at point.
 
 The position of point indicates the column to be used for
@@ -1636,76 +1661,112 @@ should be in the last line to be included into the 
sorting.
 
 The command then prompts for the sorting type which can be
 alphabetically, numerically, or by time (as given in a time stamp
-in the field).  Sorting in reverse order is also possible.
+in the field, or as a HH:MM value).  Sorting in reverse order is
+also possible.
 
 With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive.
 
 If SORTING-TYPE is specified when this function is called from a Lisp
 program, no prompting will take place.  SORTING-TYPE must be a character,
-any of (?a ?A ?n ?N ?t ?T) where the capital letter indicate that sorting
-should be done in reverse order."
-  (interactive "P")
-  (let* ((thisline (org-current-line))
-        (thiscol (org-table-current-column))
-        (otc org-table-overlay-coordinates)
-        beg end bcol ecol tend tbeg column lns pos)
-    (when (equal thiscol 0)
-      (if (org-called-interactively-p 'any)
-         (setq thiscol
-               (string-to-number
-                (read-string "Use column N for sorting: ")))
-       (setq thiscol 1))
-      (org-table-goto-column thiscol))
-    (org-table-check-inside-data-field)
-    (if (org-region-active-p)
-       (progn
-         (setq beg (region-beginning) end (region-end))
-         (goto-char beg)
-         (setq column (org-table-current-column)
-               beg (point-at-bol))
-         (goto-char end)
-         (setq end (point-at-bol 2)))
-      (setq column (org-table-current-column)
-           pos (point)
-           tbeg (org-table-begin)
-           tend (org-table-end))
-      (if (re-search-backward org-table-hline-regexp tbeg t)
-         (setq beg (point-at-bol 2))
-       (goto-char tbeg)
-       (setq beg (point-at-bol 1)))
-      (goto-char pos)
-      (if (re-search-forward org-table-hline-regexp tend t)
-         (setq end (point-at-bol 1))
-       (goto-char tend)
-       (setq end (point-at-bol))))
-    (setq beg (move-marker (make-marker) beg)
-         end (move-marker (make-marker) end))
-    (untabify beg end)
-    (goto-char beg)
-    (org-table-goto-column column)
-    (skip-chars-backward "^|")
-    (setq bcol (current-column))
-    (org-table-goto-column (1+ column))
-    (skip-chars-backward "^|")
-    (setq ecol (1- (current-column)))
-    (org-table-goto-column column)
-    (setq lns (mapcar (lambda(x) (cons
-                                 (org-sort-remove-invisible
-                                  (nth (1- column)
-                                       (org-split-string x "[ \t]*|[ \t]*")))
-                                 x))
-                     (org-split-string (buffer-substring beg end) "\n")))
-    (setq lns (org-do-sort lns "Table" with-case sorting-type))
-    (when org-table-overlay-coordinates
-      (org-table-toggle-coordinate-overlays))
-    (delete-region beg end)
-    (move-marker beg nil)
-    (move-marker end nil)
-    (insert (mapconcat 'cdr lns "\n") "\n")
-    (org-goto-line thisline)
-    (org-table-goto-column thiscol)
-    (when otc (org-table-toggle-coordinate-overlays))
-    (message "%d lines sorted, based on column %d" (length lns) column)))
+any of (?a ?A ?n ?N ?t ?T ?f ?F) where the capital letters indicate that
+sorting should be done in reverse order.
+
+If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies
+a function to be called to extract the key.  It must return a value
+that is compatible with COMPARE-FUNC, the function used to compare
+entries.
+
+A non-nil value for INTERACTIVE? is used to signal that this
+function is being called interactively."
+  (interactive (list current-prefix-arg nil nil nil t))
+  (when (org-region-active-p) (goto-char (region-beginning)))
+  ;; Point must be either within a field or before a data line.
+  (save-excursion
+    (skip-chars-backward " \t")
+    (when (bolp) (search-forward "|" (line-end-position) t))
+    (org-table-check-inside-data-field))
+  ;; Set appropriate case sensitivity and column used for sorting.
+  (let ((column (let ((c (org-table-current-column)))
+                 (cond ((> c 0) c)
+                       (interactive?
+                        (read-number "Use column N for sorting: "))
+                       (t 1))))
+       (sorting-type
+        (or sorting-type
+            (read-char-exclusive "Sort Table: [a]lphabetic, [n]umeric, \
+\[t]ime, [f]unc.  A/N/T/F means reversed: "))))
+    (save-restriction
+      ;; Narrow buffer to appropriate sorting area.
+      (if (org-region-active-p)
+         (progn (goto-char (region-beginning))
+                (narrow-to-region
+                 (point)
+                 (save-excursion (goto-char (region-end))
+                                 (line-beginning-position 2))))
+       (let ((start (org-table-begin))
+             (end (org-table-end)))
+         (narrow-to-region
+          (save-excursion
+            (if (re-search-backward org-table-hline-regexp start t)
+                (line-beginning-position 2)
+              start))
+          (if (save-excursion (re-search-forward org-table-hline-regexp end t))
+              (match-beginning 0)
+            end))))
+      ;; Determine arguments for `sort-subr'.  Also record original
+      ;; position.  `org-table-save-field' cannot help here since
+      ;; sorting is too much destructive.
+      (let* ((sort-fold-case (not with-case))
+            (coordinates
+             (cons (count-lines (point-min) (line-beginning-position))
+                   (current-column)))
+            (extract-key-from-field
+             ;; Function to be called on the contents of the field
+             ;; used for sorting in the current row.
+             (cl-case sorting-type
+               ((?n ?N) #'string-to-number)
+               ((?a ?A) #'org-sort-remove-invisible)
+               ((?t ?T)
+                (lambda (f)
+                  (cond ((string-match org-ts-regexp-both f)
+                         (float-time
+                          (org-time-string-to-time (match-string 0 f))))
+                        ((string-match "[0-9]\\{1,2\\}:[0-9]\\{2\\}" f)
+                         (org-hh:mm-string-to-minutes f))
+                        (t 0))))
+               ((?f ?F)
+                (or getkey-func
+                    (and interactive?
+                         (org-read-function "Function for extracting keys: "))
+                    (error "Missing key extractor to sort rows")))
+               (t (user-error "Invalid sorting type `%c'" sorting-type))))
+            (predicate
+             (cl-case sorting-type
+               ((?n ?N ?t ?T) #'<)
+               ((?a ?A) #'string<)
+               ((?f ?F)
+                (or compare-func
+                    (and interactive?
+                         (org-read-function
+                          (concat "Fuction for comparing keys "
+                                  "(empty for default `sort-subr' predicate): 
")
+                          'allow-empty)))))))
+       (goto-char (point-min))
+       (sort-subr (memq sorting-type '(?A ?N ?T ?F))
+                  (lambda ()
+                    (forward-line)
+                    (while (and (not (eobp))
+                                (not (looking-at org-table-dataline-regexp)))
+                      (forward-line)))
+                  #'end-of-line
+                  (lambda ()
+                    (funcall extract-key-from-field
+                             (org-trim (org-table-get-field column))))
+                  nil
+                  predicate)
+       ;; Move back to initial field.
+       (forward-line (car coordinates))
+       (move-to-column (cdr coordinates))))))
 
 ;;;###autoload
 (defun org-table-cut-region (beg end)
@@ -1725,34 +1786,31 @@ with `org-table-paste-rectangle'."
                (if (org-region-active-p) (region-beginning) (point))
                (if (org-region-active-p) (region-end) (point))
                current-prefix-arg))
-  (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
-            region cols
-            (rpl (if cut "  " nil)))
-    (goto-char beg)
-    (org-table-check-inside-data-field)
-    (setq l01 (org-current-line)
-         c01 (org-table-current-column))
-    (goto-char end)
+  (goto-char (min beg end))
+  (org-table-check-inside-data-field)
+  (let ((beg (line-beginning-position))
+       (c01 (org-table-current-column))
+       region)
+    (goto-char (max beg end))
     (org-table-check-inside-data-field)
-    (setq l02 (org-current-line)
-         c02 (org-table-current-column))
-    (setq l1 (min l01 l02) l2 (max l01 l02)
-         c1 (min c01 c02) c2 (max c01 c02))
-    (catch 'exit
-      (while t
-       (catch 'nextline
-         (if (> l1 l2) (throw 'exit t))
-         (org-goto-line l1)
-         (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
-         (setq cols nil ic1 c1 ic2 c2)
-         (while (< ic1 (1+ ic2))
-           (push (org-table-get-field ic1 rpl) cols)
-           (setq ic1 (1+ ic1)))
-         (push (nreverse cols) region)
-         (setq l1 (1+ l1)))))
-    (setq org-table-clip (nreverse region))
-    (if cut (org-table-align))
-    org-table-clip))
+    (let* ((end (copy-marker (line-end-position)))
+          (c02 (org-table-current-column))
+          (column-start (min c01 c02))
+          (column-end (max c01 c02))
+          (column-number (1+ (- column-end column-start)))
+          (rpl (and cut "  ")))
+      (goto-char beg)
+      (while (< (point) end)
+       (unless (org-at-table-hline-p)
+         ;; Collect every cell between COLUMN-START and COLUMN-END.
+         (let (cols)
+           (dotimes (c column-number)
+             (push (org-table-get-field (+ c column-start) rpl) cols))
+           (push (nreverse cols) region)))
+       (forward-line))
+      (set-marker end nil))
+    (when cut (org-table-align))
+    (setq org-table-clip (nreverse region))))
 
 ;;;###autoload
 (defun org-table-paste-rectangle ()
@@ -1762,45 +1820,43 @@ will be overwritten.  If the rectangle does not fit 
into the present table,
 the table is enlarged as needed.  The process ignores horizontal separator
 lines."
   (interactive)
-  (unless (and org-table-clip (listp org-table-clip))
+  (unless (consp org-table-clip)
     (user-error "First cut/copy a region to paste!"))
   (org-table-check-inside-data-field)
-  (let* ((clip org-table-clip)
-        (line (org-current-line))
-        (col (org-table-current-column))
+  (let* ((column (org-table-current-column))
         (org-enable-table-editor t)
-        (org-table-automatic-realign nil)
-        c cols field)
-    (while (setq cols (pop clip))
-      (while (org-at-table-hline-p) (beginning-of-line 2))
-      (if (not (org-at-table-p))
-         (progn (end-of-line 0) (org-table-next-field)))
-      (setq c col)
-      (while (setq field (pop cols))
-       (org-table-goto-column c nil 'force)
-       (org-table-get-field nil field)
-       (setq c (1+ c)))
-      (beginning-of-line 2))
-    (org-goto-line line)
-    (org-table-goto-column col)
+        (org-table-automatic-realign nil))
+    (org-table-save-field
+     (dolist (row org-table-clip)
+       (while (org-at-table-hline-p) (forward-line))
+       ;; If we left the table, create a new row.
+       (when (and (bolp) (not (looking-at "[ \t]*|")))
+        (end-of-line 0)
+        (org-table-next-field))
+       (let ((c column))
+        (dolist (field row)
+          (org-table-goto-column c nil 'force)
+          (org-table-get-field nil field)
+          (cl-incf c)))
+       (forward-line)))
     (org-table-align)))
 
 ;;;###autoload
 (defun org-table-convert ()
   "Convert from `org-mode' table to table.el and back.
-Obviously, this only works within limits.  When an Org-mode table is
-converted to table.el, all horizontal separator lines get lost, because
-table.el uses these as cell boundaries and has no notion of horizontal lines.
-A table.el table can be converted to an Org-mode table only if it does not
-do row or column spanning.  Multiline cells will become multiple cells.
-Beware, Org-mode does not test if the table can be successfully converted - it
-blindly applies a recipe that works for simple tables."
+Obviously, this only works within limits.  When an Org table is converted
+to table.el, all horizontal separator lines get lost, because table.el uses
+these as cell boundaries and has no notion of horizontal lines.  A table.el
+table can be converted to an Org table only if it does not do row or column
+spanning.  Multiline cells will become multiple cells.  Beware, Org mode
+does not test if the table can be successfully converted - it blindly
+applies a recipe that works for simple tables."
   (interactive)
   (require 'table)
   (if (org-at-table.el-p)
-      ;; convert to Org-mode table
-      (let ((beg (move-marker (make-marker) (org-table-begin t)))
-           (end (move-marker (make-marker) (org-table-end t))))
+      ;; convert to Org table
+      (let ((beg (copy-marker (org-table-begin t)))
+           (end (copy-marker (org-table-end t))))
        (table-unrecognize-region beg end)
        (goto-char beg)
        (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
@@ -1808,8 +1864,8 @@ blindly applies a recipe that works for simple tables."
        (goto-char beg))
     (if (org-at-table-p)
        ;; convert to table.el table
-       (let ((beg (move-marker (make-marker) (org-table-begin)))
-             (end (move-marker (make-marker) (org-table-end))))
+       (let ((beg (copy-marker (org-table-begin)))
+             (end (copy-marker (org-table-end))))
          ;; first, get rid of all horizontal lines
          (goto-char beg)
          (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
@@ -1832,7 +1888,7 @@ blindly applies a recipe that works for simple tables."
          (goto-char beg)))))
 
 (defun org-table-transpose-table-at-point ()
-  "Transpose orgmode table at point and eliminate hlines.
+  "Transpose Org table at point and eliminate hlines.
 So a table like
 
 | 1 | 2 | 4 | 5 |
@@ -1847,22 +1903,31 @@ will be transposed as
 | 4 | c | g |
 | 5 | d | h |
 
-Note that horizontal lines disappeared."
+Note that horizontal lines disappear."
   (interactive)
   (let* ((table (delete 'hline (org-table-to-lisp)))
-        (contents (mapcar (lambda (p)
+        (dline_old (org-table-current-line))
+        (col_old (org-table-current-column))
+        (contents (mapcar (lambda (_)
                             (let ((tp table))
                               (mapcar
-                               (lambda (rown)
+                               (lambda (_)
                                  (prog1
                                      (pop (car tp))
                                    (setq tp (cdr tp))))
                                table)))
                           (car table))))
-    (delete-region (org-table-begin) (org-table-end))
-    (insert (mapconcat (lambda(x) (concat "| " (mapconcat 'identity x " | " ) 
"  |\n" ))
-                       contents ""))
-    (org-table-align)))
+    (goto-char (org-table-begin))
+    (re-search-forward "|")
+    (backward-char)
+    (delete-region (point) (org-table-end))
+    (insert (mapconcat
+            (lambda(x)
+              (concat "| " (mapconcat 'identity x " | " ) "  |\n" ))
+            contents ""))
+    (org-table-goto-line col_old)
+    (org-table-goto-column dline_old))
+  (org-table-align))
 
 ;;;###autoload
 (defun org-table-wrap-region (arg)
@@ -1873,7 +1938,8 @@ lines, in order to keep the table compact.
 If there is an active region, and both point and mark are in the same column,
 the text in the column is wrapped to minimum width for the given number of
 lines.  Generally, this makes the table more compact.  A prefix ARG may be
-used to change the number of desired lines.  For example, `C-2 
\\[org-table-wrap]'
+used to change the number of desired lines.  For example, \
+`C-2 \\[org-table-wrap-region]'
 formats the selected text to two lines.  If the region was longer than two
 lines, the remaining lines remain empty.  A negative prefix argument reduces
 the current number of lines by that amount.  The wrapped text is pasted back
@@ -1890,57 +1956,53 @@ blank, and the content is appended to the field above."
   (interactive "P")
   (org-table-check-inside-data-field)
   (if (org-region-active-p)
-      ;; There is a region:  fill as a paragraph
-      (let* ((beg (region-beginning))
-            (cline (save-excursion (goto-char beg) (org-current-line)))
-            (ccol (save-excursion (goto-char beg) (org-table-current-column)))
-            nlines)
+      ;; There is a region: fill as a paragraph.
+      (let ((start (region-beginning)))
        (org-table-cut-region (region-beginning) (region-end))
-       (if (> (length (car org-table-clip)) 1)
-           (user-error "Region must be limited to single column"))
-       (setq nlines (if arg
-                        (if (< arg 1)
-                            (+ (length org-table-clip) arg)
-                          arg)
-                      (length org-table-clip)))
-       (setq org-table-clip
-             (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
-                                     nil nlines)))
-       (org-goto-line cline)
-       (org-table-goto-column ccol)
+       (when (> (length (car org-table-clip)) 1)
+         (user-error "Region must be limited to single column"))
+       (let ((nlines (cond ((not arg) (length org-table-clip))
+                           ((< arg 1) (+ (length org-table-clip) arg))
+                           (t arg))))
+         (setq org-table-clip
+               (mapcar #'list
+                       (org-wrap (mapconcat #'car org-table-clip " ")
+                                 nil
+                                 nlines))))
+       (goto-char start)
        (org-table-paste-rectangle))
-    ;; No region, split the current field at point
+    ;; No region, split the current field at point.
     (unless (org-get-alist-option org-M-RET-may-split-line 'table)
       (skip-chars-forward "^\r\n|"))
-    (if arg
-       ;; combine with field above
-       (let ((s (org-table-blank-field))
-             (col (org-table-current-column)))
-         (beginning-of-line 0)
-         (while (org-at-table-hline-p) (beginning-of-line 0))
-         (org-table-goto-column col)
-         (skip-chars-forward "^|")
-         (skip-chars-backward " ")
-         (insert " " (org-trim s))
-         (org-table-align))
-      ;;  split field
-      (if (looking-at "\\([^|]+\\)+|")
-         (let ((s (match-string 1)))
-           (replace-match " |")
-           (goto-char (match-beginning 0))
-           (org-table-next-row)
-           (insert (org-trim s) " ")
-           (org-table-align))
-       (org-table-next-row)))))
+    (cond
+     (arg                              ; Combine with field above.
+      (let ((s (org-table-blank-field))
+           (col (org-table-current-column)))
+       (forward-line -1)
+       (while (org-at-table-hline-p) (forward-line -1))
+       (org-table-goto-column col)
+       (skip-chars-forward "^|")
+       (skip-chars-backward " ")
+       (insert " " (org-trim s))
+       (org-table-align)))
+     ((looking-at "\\([^|]+\\)+|")     ; Split field.
+      (let ((s (match-string 1)))
+       (replace-match " |")
+       (goto-char (match-beginning 0))
+       (org-table-next-row)
+       (insert (org-trim s) " ")
+       (org-table-align)))
+     (t (org-table-next-row)))))
 
 (defvar org-field-marker nil)
 
 ;;;###autoload
 (defun org-table-edit-field (arg)
   "Edit table field in a different window.
-This is mainly useful for fields that contain hidden parts.
-When called with a \\[universal-argument] prefix, just make the full field 
visible so that
-it can be edited in place."
+This is mainly useful for fields that contain hidden parts.  When called
+with a `\\[universal-argument]' prefix, just make the full field \
+visible so that it can be
+edited in place."
   (interactive "P")
   (cond
    ((equal arg '(16))
@@ -1980,9 +2042,9 @@ it can be edited in place."
                              '(invisible t org-cwidth t display t
                                          intangible t))
       (goto-char p)
-      (org-set-local 'org-finish-function 'org-table-finish-edit-field)
-      (org-set-local 'org-window-configuration cw)
-      (org-set-local 'org-field-marker pos)
+      (setq-local org-finish-function 'org-table-finish-edit-field)
+      (setq-local org-window-configuration cw)
+      (setq-local org-field-marker pos)
       (message "Edit and finish with C-c C-c")))))
 
 (defun org-table-finish-edit-field ()
@@ -2015,8 +2077,8 @@ current field.  The mode exits automatically when the 
cursor leaves the
 table (but see `org-table-exit-follow-field-mode-when-leaving-table')."
   nil " TblFollow" nil
   (if org-table-follow-field-mode
-      (org-add-hook 'post-command-hook 'org-table-follow-fields-with-editor
-                   'append 'local)
+      (add-hook 'post-command-hook 'org-table-follow-fields-with-editor
+               'append 'local)
     (remove-hook 'post-command-hook 'org-table-follow-fields-with-editor 
'local)
     (let* ((buf (get-buffer "*Org Table Edit Field*"))
           (win (and buf (get-buffer-window buf))))
@@ -2091,11 +2153,10 @@ If NLAST is a number, only the NLAST fields will 
actually be summed."
                           s diff)
                     (format "%.0f:%02.0f:%02.0f" h m s))))
        (kill-new sres)
-       (if (org-called-interactively-p 'interactive)
-           (message "%s"
-                    (substitute-command-keys
-                     (format "Sum of %d items: %-20s     (\\[yank] will insert 
result into buffer)"
-                             (length numbers) sres))))
+       (when (called-interactively-p 'interactive)
+           (message "%s" (substitute-command-keys
+                          (format "Sum of %d items: %-20s     \
+\(\\[yank] will insert result into buffer)" (length numbers) sres))))
        sres))))
 
 (defun org-table-get-number-for-summing (s)
@@ -2120,57 +2181,58 @@ If NLAST is a number, only the NLAST fields will 
actually be summed."
 
 (defun org-table-current-field-formula (&optional key noerror)
   "Return the formula active for the current field.
-Assumes that specials are in place.
-If KEY is given, return the key to this formula.
-Otherwise return the formula preceded with \"=\" or \":=\"."
-  (let* ((name (car (rassoc (list (org-current-line)
-                                 (org-table-current-column))
-                           org-table-named-field-locations)))
-        (col (org-table-current-column))
-        (scol (int-to-string col))
-        (ref (format "@%d$%d" (org-table-current-dline) col))
-        (stored-list (org-table-get-stored-formulas noerror))
-        (ass (or (assoc name stored-list)
-                 (assoc ref stored-list)
-                 (assoc scol stored-list))))
-    (if key
-       (car ass)
-      (if ass (concat (if (string-match "^[0-9]+$" (car ass)) "=" ":=")
-                     (cdr ass))))))
+
+Assumes that table is already analyzed.  If KEY is given, return
+the key to this formula.  Otherwise return the formula preceded
+with \"=\" or \":=\"."
+  (let* ((line (count-lines org-table-current-begin-pos
+                           (line-beginning-position)))
+        (row (org-table-line-to-dline line)))
+    (cond
+     (row
+      (let* ((col (org-table-current-column))
+            (name (car (rassoc (list line col)
+                               org-table-named-field-locations)))
+            (scol (format "$%d" col))
+            (ref (format "@%d$%d" (org-table-current-dline) col))
+            (stored-list (org-table-get-stored-formulas noerror))
+            (ass (or (assoc name stored-list)
+                     (assoc ref stored-list)
+                     (assoc scol stored-list))))
+       (cond (key (car ass))
+             (ass (concat (if (string-match-p "^[0-9]+$" (car ass)) "=" ":=")
+                          (cdr ass))))))
+     (noerror nil)
+     (t (error "No formula active for the current field")))))
 
 (defun org-table-get-formula (&optional equation named)
   "Read a formula from the minibuffer, offer stored formula as default.
 When NAMED is non-nil, look for a named equation."
   (let* ((stored-list (org-table-get-stored-formulas))
-        (name (car (rassoc (list (org-current-line)
+        (name (car (rassoc (list (count-lines org-table-current-begin-pos
+                                              (line-beginning-position))
                                  (org-table-current-column))
                            org-table-named-field-locations)))
-        (ref (format "@%d$%d" (org-table-current-dline)
+        (ref (format "@%d$%d"
+                     (org-table-current-dline)
                      (org-table-current-column)))
-        (refass (assoc ref stored-list))
-        (nameass (assoc name stored-list))
-        (scol (if named
-                  (if (and name (not (string-match "^LR[0-9]+$" name)))
-                      name
-                    ref)
-                (int-to-string (org-table-current-column))))
-        (dummy (and (or nameass refass) (not named)
-                    (not (y-or-n-p "Replace existing field formula with column 
formula? " ))
-                    (message "Formula not replaced")))
+        (scol (cond
+               ((not named) (format "$%d" (org-table-current-column)))
+               ((and name (not (string-match "\\`LR[0-9]+\\'" name))) name)
+               (t ref)))
         (name (or name ref))
         (org-table-may-need-update nil)
         (stored (cdr (assoc scol stored-list)))
         (eq (cond
-             ((and stored equation (string-match "^ *=? *$" equation))
+             ((and stored equation (string-match-p "^ *=? *$" equation))
               stored)
              ((stringp equation)
               equation)
              (t (org-table-formula-from-user
                  (read-string
                   (org-table-formula-to-user
-                   (format "%s formula %s%s="
+                   (format "%s formula %s="
                            (if named "Field" "Column")
-                           (if (member (string-to-char scol) '(?$ ?@)) "" "$")
                            scol))
                   (if stored (org-table-formula-to-user stored) "")
                   'org-table-formula-history
@@ -2194,25 +2256,27 @@ When NAMED is non-nil, look for a named equation."
        (org-table-store-formulas stored-list))
     eq))
 
-(defun org-table-store-formulas (alist)
-  "Store the list of formulas below the current table."
-  (setq alist (sort alist 'org-table-formula-less-p))
-  (let ((case-fold-search t))
-    (save-excursion
-      (goto-char (org-table-end))
-      (if (looking-at "\\([ \t]*\n\\)*[ \t]*\\(#\\+tblfm:\\)\\(.*\n?\\)")
+(defun org-table-store-formulas (alist &optional location)
+  "Store the list of formulas below the current table.
+If optional argument LOCATION is a buffer position, insert it at
+LOCATION instead."
+  (save-excursion
+    (if location
+       (progn (goto-char location) (beginning-of-line))
+      (goto-char (org-table-end)))
+    (let ((case-fold-search t))
+      (if (looking-at "\\([ \t]*\n\\)*[ \t]*\\(#\\+TBLFM:\\)\\(.*\n?\\)")
          (progn
-           ;; don't overwrite TBLFM, we might use text properties to store 
stuff
+           ;; Don't overwrite TBLFM, we might use text properties to
+           ;; store stuff.
            (goto-char (match-beginning 3))
            (delete-region (match-beginning 3) (match-end 0)))
        (org-indent-line)
        (insert (or (match-string 2) "#+TBLFM:")))
       (insert " "
-             (mapconcat (lambda (x)
-                          (concat
-                           (if (equal (string-to-char (car x)) ?@) "" "$")
-                           (car x) "=" (cdr x)))
-                        alist "::")
+             (mapconcat (lambda (x) (concat (car x) "=" (cdr x)))
+                        (sort alist #'org-table-formula-less-p)
+                        "::")
              "\n"))))
 
 (defsubst org-table-formula-make-cmp-string (a)
@@ -2241,33 +2305,47 @@ When NAMED is non-nil, look for a named equation."
     (and as bs (string< as bs))))
 
 ;;;###autoload
-(defun org-table-get-stored-formulas (&optional noerror)
-  "Return an alist with the stored formulas directly after current table."
-  (interactive) ;; FIXME interactive?
-  (let ((case-fold-search t) scol eq eq-alist strings string seen)
-    (save-excursion
-      (goto-char (org-table-end))
-      (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+tblfm: *\\(.*\\)")
-       (setq strings (org-split-string (org-match-string-no-properties 2)
-                                       " *:: *"))
-       (while (setq string (pop strings))
-         (when (string-match 
"\\`\\(@[-+I<>address@hidden|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|[<>]+\\)\\) *= 
*\\(.*[^ \t]\\)" string)
-           (setq scol (if (match-end 2)
-                          (match-string 2 string)
-                        (match-string 1 string))
-                 scol (if (member (string-to-char scol) '(?< ?>))
-                          (concat "$" scol) scol)
-                 eq (match-string 3 string)
-                 eq-alist (cons (cons scol eq) eq-alist))
-           (if (member scol seen)
-               (if noerror
-                   (progn
-                     (message "Double definition `$%s=' in TBLFM line, please 
fix by hand" scol)
-                     (ding)
-                     (sit-for 2))
-                 (user-error "Double definition `$%s=' in TBLFM line, please 
fix by hand" scol))
-             (push scol seen))))))
-    (nreverse eq-alist)))
+(defun org-table-get-stored-formulas (&optional noerror location)
+  "Return an alist with the stored formulas directly after current table.
+By default, only return active formulas, i.e., formulas located
+on the first line after the table.  However, if optional argument
+LOCATION is a buffer position, consider the formulas there."
+  (save-excursion
+    (if location
+       (progn (goto-char location) (beginning-of-line))
+      (goto-char (org-table-end)))
+    (let ((case-fold-search t))
+      (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+TBLFM: *\\(.*\\)")
+       (let ((strings (org-split-string (match-string-no-properties 2)
+                                        " *:: *"))
+             eq-alist seen)
+         (dolist (string strings (nreverse eq-alist))
+           (when (string-match 
"\\`\\(@[-+I<>address@hidden|\\$\\([_a-zA-Z0-9]+\\|\
+[<>]+\\)\\) *= *\\(.*[^ \t]\\)"
+                               string)
+             (let ((lhs
+                    (let ((m (match-string 1 string)))
+                      (cond
+                       ((not (match-end 2)) m)
+                       ;; Is it a column reference?
+                       ((string-match-p "\\`$\\([0-9]+\\|[<>]+\\)\\'" m) m)
+                       ;; Since named columns are not possible in
+                       ;; LHS, assume this is a named field.
+                       (t (match-string 2 string)))))
+                   (rhs (match-string 3 string)))
+               (push (cons lhs rhs) eq-alist)
+               (cond
+                ((not (member lhs seen)) (push lhs seen))
+                (noerror
+                 (message
+                  "Double definition `%s=' in TBLFM line, please fix by hand"
+                  lhs)
+                 (ding)
+                 (sit-for 2))
+                (t
+                 (user-error
+                  "Double definition `%s=' in TBLFM line, please fix by hand"
+                  lhs)))))))))))
 
 (defun org-table-fix-formulas (key replace &optional limit delta remove)
   "Modify the equations after the table structure has been edited.
@@ -2305,83 +2383,6 @@ For all numbers larger than LIMIT, shift them by DELTA."
              (message msg))))))
       (forward-line))))
 
-(defun org-table-get-specials ()
-  "Get the column names and local parameters for this table."
-  (save-excursion
-    (let ((beg (org-table-begin)) (end (org-table-end))
-         names name fields fields1 field cnt
-         c v l line col types dlines hlines last-dline)
-      (setq org-table-column-names nil
-           org-table-local-parameters nil
-           org-table-named-field-locations nil
-           org-table-current-begin-line nil
-           org-table-current-begin-pos nil
-           org-table-current-line-types nil
-           org-table-current-ncol 0)
-      (goto-char beg)
-      (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
-       (setq names (org-split-string (match-string 1) " *| *")
-             cnt 1)
-       (while (setq name (pop names))
-         (setq cnt (1+ cnt))
-         (if (string-match "^[a-zA-Z][_a-zA-Z0-9]*$" name)
-             (push (cons name (int-to-string cnt)) org-table-column-names))))
-      (setq org-table-column-names (nreverse org-table-column-names))
-      (setq org-table-column-name-regexp
-           (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") 
"\\)\\>"))
-      (goto-char beg)
-      (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
-       (setq fields (org-split-string (match-string 1) " *| *"))
-       (while (setq field (pop fields))
-         (if (string-match "^\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" 
field)
-             (push (cons (match-string 1 field) (match-string 2 field))
-                   org-table-local-parameters))))
-      (goto-char beg)
-      (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
-       (setq c (match-string 1)
-             fields (org-split-string (match-string 2) " *| *"))
-       (save-excursion
-         (beginning-of-line (if (equal c "_") 2 0))
-         (setq line (org-current-line) col 1)
-         (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
-              (setq fields1 (org-split-string (match-string 1) " *| *"))))
-       (while (and fields1 (setq field (pop fields)))
-         (setq v (pop fields1) col (1+ col))
-         (when (and (stringp field) (stringp v)
-                    (string-match "^[a-zA-Z][_a-zA-Z0-9]*$" field))
-           (push (cons field v) org-table-local-parameters)
-           (push (list field line col) org-table-named-field-locations))))
-      ;; Analyze the line types.
-      (goto-char beg)
-      (setq org-table-current-begin-line (org-current-line)
-           org-table-current-begin-pos (point)
-           l org-table-current-begin-line)
-      (while (looking-at "[ \t]*|\\(-\\)?")
-       (push (if (match-end 1) 'hline 'dline) types)
-       (if (match-end 1) (push l hlines) (push l dlines))
-       (beginning-of-line 2)
-       (setq l (1+ l)))
-      (push 'hline types) ;; add an imaginary extra hline to the end
-      (setq org-table-current-line-types (apply 'vector (nreverse types))
-           last-dline (car dlines)
-           org-table-dlines (apply 'vector (cons nil (nreverse dlines)))
-           org-table-hlines (apply 'vector (cons nil (nreverse hlines))))
-      (org-goto-line last-dline)
-      (let* ((l last-dline)
-            (fields (org-split-string
-                     (buffer-substring (point-at-bol) (point-at-eol))
-                     "[ \t]*|[ \t]*"))
-            (nfields (length fields))
-            al al2)
-       (setq org-table-current-ncol nfields)
-       (loop for i from 1 to nfields do
-             (push (list (format "LR%d" i) l i) al)
-             (push (cons (format "LR%d" i) (nth (1- i) fields)) al2))
-       (setq org-table-named-field-locations
-             (append org-table-named-field-locations al))
-       (setq org-table-local-parameters
-             (append org-table-local-parameters al2))))))
-
 ;;;###autoload
 (defun org-table-maybe-eval-formula ()
   "Check if the current field starts with \"=\" or \":=\".
@@ -2394,11 +2395,8 @@ If yes, store the formula and apply it."
       (when (string-match "^:?=\\(.*[^=]\\)$" field)
        (setq named (equal (string-to-char field) ?:)
              eq (match-string 1 field))
-       (if (or (fboundp 'calc-eval)
-               (equal (substring eq 0 (min 2 (length eq))) "'("))
-           (org-table-eval-formula (if named '(4) nil)
-                                   (org-table-formula-from-user eq))
-         (user-error "Calc does not seem to be installed, and is needed to 
evaluate the formula"))))))
+       (org-table-eval-formula (and named '(4))
+                               (org-table-formula-from-user eq))))))
 
 (defvar org-recalc-commands nil
   "List of commands triggering the recalculation of a line.
@@ -2424,56 +2422,199 @@ After each change, a message will be displayed 
indicating the meaning
 of the new mark."
   (interactive)
   (unless (org-at-table-p) (user-error "Not at a table"))
-  (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
-        (beg (org-table-begin))
-        (end (org-table-end))
-        (l (org-current-line))
-        (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
-        (l2 (if (org-region-active-p) (org-current-line (region-end))))
-        (have-col
-         (save-excursion
-           (goto-char beg)
-           (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end 
t))))
+  (let* ((region (org-region-active-p))
+        (l1 (and region
+                 (save-excursion (goto-char (region-beginning))
+                                 (copy-marker (line-beginning-position)))))
+        (l2 (and region
+                 (save-excursion (goto-char (region-end))
+                                 (copy-marker (line-beginning-position)))))
+        (l (copy-marker (line-beginning-position)))
         (col (org-table-current-column))
-        (forcenew (car (assoc newchar org-recalc-marks)))
-        epos new)
-    (when l1
-      (message "Change region to what mark?  Type # * ! $ or SPC: ")
-      (setq newchar (char-to-string (read-char-exclusive))
-           forcenew (car (assoc newchar org-recalc-marks))))
-    (if (and newchar (not forcenew))
-       (user-error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
-              newchar))
-    (if l1 (org-goto-line l1))
+        (newchar (if region
+                     (char-to-string
+                      (read-char-exclusive
+                       "Change region to what mark?  Type # * ! $ or SPC: "))
+                   newchar))
+        (no-special-column
+         (save-excursion
+           (goto-char (org-table-begin))
+           (re-search-forward
+            "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" (org-table-end) t))))
+    (when (and newchar (not (assoc newchar org-recalc-marks)))
+      (user-error "Invalid character `%s' in `org-table-rotate-recalc-marks'"
+                 newchar))
+    (when l1 (goto-char l1))
     (save-excursion
-      (beginning-of-line 1)
+      (beginning-of-line)
       (unless (looking-at org-table-dataline-regexp)
        (user-error "Not at a table data line")))
-    (unless have-col
+    (when no-special-column
       (org-table-goto-column 1)
-      (org-table-insert-column)
-      (org-table-goto-column (1+ col)))
-    (setq epos (point-at-eol))
+      (org-table-insert-column))
+    (let ((previous-line-end (line-end-position))
+         (newchar
+          (save-excursion
+            (beginning-of-line)
+            (cond ((not (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")) "#")
+                  (newchar)
+                  (t (cadr (member (match-string 1)
+                                   (append (mapcar #'car org-recalc-marks)
+                                           '(" ")))))))))
+      ;; Rotate mark in first row.
+      (org-table-get-field 1 (format " %s " newchar))
+      ;; Rotate marks in additional rows if a region is active.
+      (when region
+       (save-excursion
+         (forward-line)
+         (while (<= (point) l2)
+           (when (looking-at org-table-dataline-regexp)
+             (org-table-get-field 1 (format " %s " newchar)))
+           (forward-line))))
+      ;; Only align if rotation actually changed lines' length.
+      (when (/= previous-line-end (line-end-position)) (org-table-align)))
+    (goto-char l)
+    (org-table-goto-column (if no-special-column (1+ col) col))
+    (when l1 (set-marker l1 nil))
+    (when l2 (set-marker l2 nil))
+    (set-marker l nil)
+    (when (called-interactively-p 'interactive)
+      (message "%s" (cdr (assoc newchar org-recalc-marks))))))
+
+;;;###autoload
+(defun org-table-analyze ()
+  "Analyze table at point and store results.
+
+This function sets up the following dynamically scoped variables:
+
+ `org-table-column-name-regexp',
+ `org-table-column-names',
+ `org-table-current-begin-pos',
+ `org-table-current-line-types',
+ `org-table-current-ncol',
+ `org-table-dlines',
+ `org-table-hlines',
+ `org-table-local-parameters',
+ `org-table-named-field-locations'."
+  (let ((beg (org-table-begin))
+       (end (org-table-end)))
     (save-excursion
-      (beginning-of-line 1)
-      (org-table-get-field
-       1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
-            (concat " "
-                    (setq new (or forcenew
-                                  (cadr (member (match-string 1) marks))))
-                    " ")
-          " # ")))
-    (if (and l1 l2)
-       (progn
-         (org-goto-line l1)
-         (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
-           (and (looking-at org-table-dataline-regexp)
-                (org-table-get-field 1 (concat " " new " "))))
-         (org-goto-line l1)))
-    (if (not (= epos (point-at-eol))) (org-table-align))
-    (org-goto-line l)
-    (and (org-called-interactively-p 'interactive)
-        (message "%s" (cdr (assoc new org-recalc-marks))))))
+      (goto-char beg)
+      ;; Extract column names.
+      (setq org-table-column-names nil)
+      (when (save-excursion
+             (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t))
+       (let ((c 1))
+         (dolist (name (org-split-string (match-string 1) " *| *"))
+           (cl-incf c)
+           (when (string-match "\\`[a-zA-Z][_a-zA-Z0-9]*\\'" name)
+             (push (cons name (int-to-string c)) org-table-column-names)))))
+      (setq org-table-column-names (nreverse org-table-column-names))
+      (setq org-table-column-name-regexp
+           (format "\\$\\(%s\\)\\>"
+                   (regexp-opt (mapcar #'car org-table-column-names) t)))
+      ;; Extract local parameters.
+      (setq org-table-local-parameters nil)
+      (save-excursion
+       (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
+         (dolist (field (org-split-string (match-string 1) " *| *"))
+           (when (string-match
+                  "\\`\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
+             (push (cons (match-string 1 field) (match-string 2 field))
+                   org-table-local-parameters)))))
+      ;; Update named fields locations.  We minimize `count-lines'
+      ;; processing by storing last known number of lines in LAST.
+      (setq org-table-named-field-locations nil)
+      (save-excursion
+       (let ((last (cons (point) 0)))
+         (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
+           (let ((c (match-string 1))
+                 (fields (org-split-string (match-string 2) " *| *")))
+             (save-excursion
+               (forward-line (if (equal c "_") 1 -1))
+               (let ((fields1
+                      (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
+                           (org-split-string (match-string 1) " *| *")))
+                     (line (cl-incf (cdr last) (count-lines (car last) 
(point))))
+                     (col 1))
+                 (setcar last (point)) ; Update last known position.
+                 (while (and fields fields1)
+                   (let ((field (pop fields))
+                         (v (pop fields1)))
+                     (cl-incf col)
+                     (when (and (stringp field)
+                                (stringp v)
+                                (string-match "\\`[a-zA-Z][_a-zA-Z0-9]*\\'"
+                                              field))
+                       (push (cons field v) org-table-local-parameters)
+                       (push (list field line col)
+                             org-table-named-field-locations))))))))))
+      ;; Re-use existing markers when possible.
+      (if (markerp org-table-current-begin-pos)
+         (move-marker org-table-current-begin-pos (point))
+       (setq org-table-current-begin-pos (point-marker)))
+      ;; Analyze the line types.
+      (let ((l 0) hlines dlines types)
+       (while (looking-at "[ \t]*|\\(-\\)?")
+         (push (if (match-end 1) 'hline 'dline) types)
+         (if (match-end 1) (push l hlines) (push l dlines))
+         (forward-line)
+         (cl-incf l))
+       (push 'hline types) ; Add an imaginary extra hline to the end.
+       (setq org-table-current-line-types (apply #'vector (nreverse types)))
+       (setq org-table-dlines (apply #'vector (cons nil (nreverse dlines))))
+       (setq org-table-hlines (apply #'vector (cons nil (nreverse hlines)))))
+      ;; Get the number of columns from the first data line in table.
+      (goto-char beg)
+      (forward-line (aref org-table-dlines 1))
+      (let* ((fields
+             (org-split-string
+              (buffer-substring (line-beginning-position) (line-end-position))
+              "[ \t]*|[ \t]*"))
+            (nfields (length fields))
+            al al2)
+       (setq org-table-current-ncol nfields)
+       (let ((last-dline
+              (aref org-table-dlines (1- (length org-table-dlines)))))
+         (dotimes (i nfields)
+           (let ((column (1+ i)))
+             (push (list (format "LR%d" column) last-dline column) al)
+             (push (cons (format "LR%d" column) (nth i fields)) al2))))
+       (setq org-table-named-field-locations
+             (append org-table-named-field-locations al))
+       (setq org-table-local-parameters
+             (append org-table-local-parameters al2))))))
+
+(defun org-table-goto-field (ref &optional create-column-p)
+  "Move point to a specific field in the current table.
+
+REF is either the name of a field its absolute reference, as
+a string.  No column is created unless CREATE-COLUMN-P is
+non-nil.  If it is a function, it is called with the column
+number as its argument as is used as a predicate to know if the
+column can be created.
+
+This function assumes the table is already analyzed (i.e., using
+`org-table-analyze')."
+  (let* ((coordinates
+         (cond
+          ((cdr (assoc ref org-table-named-field-locations)))
+          ((string-match 
"address@hidden([1-9][0-9]*\\)\\$\\([1-9][0-9]*\\)\\'" ref)
+           (list (condition-case nil
+                     (aref org-table-dlines
+                           (string-to-number (match-string 1 ref)))
+                   (error (user-error "Invalid row number in %s" ref)))
+                 (string-to-number (match-string 2 ref))))
+          (t (user-error "Unknown field: %s" ref))))
+        (line (car coordinates))
+        (column (nth 1 coordinates))
+        (create-new-column (if (functionp create-column-p)
+                               (funcall create-column-p column)
+                             create-column-p)))
+    (when coordinates
+      (goto-char org-table-current-begin-pos)
+      (forward-line line)
+      (org-table-goto-column column nil create-new-column))))
 
 ;;;###autoload
 (defun org-table-maybe-recalculate-line ()
@@ -2481,7 +2622,7 @@ of the new mark."
   (interactive)
   (and org-table-allow-automatic-line-recalculation
        (not (and (memq last-command org-recalc-commands)
-                (equal org-last-recalc-line (org-current-line))))
+                (eq org-last-recalc-line (line-beginning-position))))
        (save-excursion (beginning-of-line 1)
                       (looking-at org-table-auto-recalculate-regexp))
        (org-table-recalculate) t))
@@ -2505,20 +2646,18 @@ of the new mark."
                                         suppress-store suppress-analysis)
   "Replace the table field value at the cursor by the result of a calculation.
 
-This function makes use of Dave Gillespie's Calc package, in my view the
-most exciting program ever written for GNU Emacs.  So you need to have Calc
-installed in order to use this function.
-
 In a table, this command replaces the value in the current field with the
 result of a formula.  It also installs the formula as the \"current\" column
 formula, by storing it in a special line below the table.  When called
-with a `C-u' prefix, the current field must be a named field, and the
-formula is installed as valid in only this specific field.
+with a `\\[universal-argument]' prefix the formula is installed as a \
+field formula.
 
-When called with two `C-u' prefixes, insert the active equation
-for the field back into the current field, so that it can be
-edited there.  This is useful in order to use \\[org-table-show-reference]
-to check the referenced fields.
+When called with a `\\[universal-argument] \\[universal-argument]' prefix, \
+insert the active equation for the field
+back into the current field, so that it can be edited there.  This is \
+useful
+in order to use \\<org-table-fedit-map>`\\[org-table-show-reference]' to \
+check the referenced fields.
 
 When called, the command first prompts for a formula, which is read in
 the minibuffer.  Previously entered formulas are available through the
@@ -2527,7 +2666,7 @@ These stored formulas are adapted correctly when moving, 
inserting, or
 deleting columns with the corresponding commands.
 
 The formula can be any algebraic expression understood by the Calc package.
-For details, see the Org-mode manual.
+For details, see the Org mode manual.
 
 This function can also be called from Lisp programs and offers
 additional arguments: EQUATION can be the formula to apply.  If this
@@ -2537,13 +2676,13 @@ SUPPRESS-CONST suppresses the interpretation of 
constants in the
 formula, assuming that this has been done already outside the function.
 SUPPRESS-STORE means the formula should not be stored, either because
 it is already stored, or because it is a modified equation that should
-not overwrite the stored one."
+not overwrite the stored one.  SUPPRESS-ANALYSIS prevents any call to
+`org-table-analyze'."
   (interactive "P")
   (org-table-check-inside-data-field)
-  (or suppress-analysis (org-table-get-specials))
+  (or suppress-analysis (org-table-analyze))
   (if (equal arg '(16))
       (let ((eq (org-table-current-field-formula)))
-       (or eq (user-error "No equation active for current field"))
        (org-table-get-field nil eq)
        (org-table-align)
        (setq org-table-may-need-update t))
@@ -2557,7 +2696,7 @@ not overwrite the stored one."
                      (org-table-get-formula equation (equal arg '(4)))))
           (n0 (org-table-current-column))
           (org-tbl-calc-modes (copy-sequence org-calc-default-modes))
-          (numbers nil) ; was a variable, now fixed default
+          (numbers nil)           ; was a variable, now fixed default
           (keep-empty nil)
           n form form0 formrpl formrg bw fmt x ev orig c lispp literal
           duration duration-output-format)
@@ -2603,12 +2742,15 @@ not overwrite the stored one."
              (setq fmt (replace-match "" t t fmt)))
            (unless (string-match "\\S-" fmt)
              (setq fmt nil))))
-      (if (and (not suppress-const) org-table-formula-use-constants)
-         (setq formula (org-table-formula-substitute-names formula)))
+      (when (and (not suppress-const) org-table-formula-use-constants)
+       (setq formula (org-table-formula-substitute-names formula)))
       (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
+      (setq formula (org-table-formula-handle-first/last-rc formula))
       (while (> ndown 0)
        (setq fields (org-split-string
-                     (buffer-substring-no-properties (point-at-bol) 
(point-at-eol))
+                     (org-trim
+                      (buffer-substring-no-properties
+                       (line-beginning-position) (line-end-position)))
                      " *| *"))
        ;; replace fields with duration values if relevant
        (if duration
@@ -2641,9 +2783,10 @@ not overwrite the stored one."
                 t t form)))
 
        ;; Check for old vertical references
-       (setq form (org-table-rewrite-old-row-references form))
+       (org-table--error-on-old-row-references form)
        ;; Insert remote references
-       (while (string-match "\\<remote([ \t]*\\([-_a-zA-Z0-9]+\\)[ \t]*,[ 
\t]*\\([^\n)]+\\))" form)
+       (setq form (org-table-remote-reference-indirection form))
+       (while (string-match "\\<remote([ \t]*\\([^,)]+\\)[ \t]*,[ 
\t]*\\([^\n)]+\\))" form)
          (setq form
                (replace-match
                 (save-match-data
@@ -2660,8 +2803,10 @@ not overwrite the stored one."
        ;; Insert complex ranges
        (while (and (string-match org-table-range-regexp form)
                    (> (length (match-string 0 form)) 1))
-         (setq formrg (save-match-data
-                        (org-table-get-range (match-string 0 form) nil n0)))
+         (setq formrg
+               (save-match-data
+                 (org-table-get-range
+                  (match-string 0 form) org-table-current-begin-pos n0)))
          (setq formrpl
                (save-match-data
                  (org-table-make-reference
@@ -2676,15 +2821,20 @@ not overwrite the stored one."
                     (string-match (regexp-quote form) formrpl)))
              (setq form (replace-match formrpl t t form))
            (user-error "Spreadsheet error: invalid reference \"%s\"" form)))
-       ;; Insert simple ranges
-       (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)"  form)
+       ;; Insert simple ranges, i.e. included in the current row.
+       (while (string-match
+               "\\$\\(\\([-+]\\)?[0-9]+\\)\\.\\.\\$\\(\\([-+]\\)?[0-9]+\\)"
+               form)
          (setq form
                (replace-match
                 (save-match-data
                   (org-table-make-reference
-                   (org-sublist
-                    fields (string-to-number (match-string 1 form))
-                    (string-to-number (match-string 2 form)))
+                   (cl-subseq fields
+                              (+ (if (match-end 2) n0 0)
+                                 (string-to-number (match-string 1 form))
+                                 -1)
+                              (+ (if (match-end 4) n0 0)
+                                 (string-to-number (match-string 3 form))))
                    keep-empty numbers lispp))
                 t t form)))
        (setq form0 form)
@@ -2692,14 +2842,16 @@ not overwrite the stored one."
        (while (string-match "\\$\\(\\([-+]\\)?[0-9]+\\)" form)
          (setq n (+ (string-to-number (match-string 1 form))
                     (if (match-end 2) n0 0))
-               x (nth (1- (if (= n 0) n0 (max n 1))) fields))
-         (unless x (user-error "Invalid field specifier \"%s\""
-                          (match-string 0 form)))
-         (setq form (replace-match
-                     (save-match-data
-                       (org-table-make-reference
-                        x keep-empty numbers lispp))
-                     t t form)))
+               x (nth (1- (if (= n 0) n0 (max n 1))) fields)
+               formrpl (save-match-data
+                         (org-table-make-reference
+                          x keep-empty numbers lispp)))
+         (when (or (not x)
+                   (save-match-data
+                     (string-match (regexp-quote formula) formrpl)))
+           (user-error "Invalid field specifier \"%s\""
+                       (match-string 0 form)))
+         (setq form (replace-match formrpl t t form)))
 
        (if lispp
            (setq ev (condition-case nil
@@ -2709,20 +2861,23 @@ not overwrite the stored one."
                  ev (if duration (org-table-time-seconds-to-string
                                   (string-to-number ev)
                                   duration-output-format) ev))
-         (or (fboundp 'calc-eval)
-             (user-error "Calc does not seem to be installed, and is needed to 
evaluate the formula"))
-         ;; Use <...> time-stamps so that Calc can handle them
-         (while (string-match (concat "\\[" org-ts-regexp1 "\\]") form)
-           (setq form (replace-match "<\\1>" nil nil form)))
-         ;; I18n-ize local time-stamps by setting (system-time-locale "C")
-         (when (string-match org-ts-regexp2 form)
-           (let* ((ts (match-string 0 form))
-                  (tsp (apply 'encode-time (save-match-data 
(org-parse-time-string ts))))
-                  (system-time-locale "C")
-                  (tf (or (and (save-match-data (string-match 
"[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
-                               (cdr org-time-stamp-formats))
-                          (car org-time-stamp-formats))))
-             (setq form (replace-match (format-time-string tf tsp) t t form))))
+
+         ;; Use <...> time-stamps so that Calc can handle them.
+         (setq form
+               (replace-regexp-in-string org-ts-regexp-inactive "<\\1>" form))
+         ;; Internationalize local time-stamps by setting locale to
+         ;; "C".
+         (setq form
+               (replace-regexp-in-string
+                org-ts-regexp
+                (lambda (ts)
+                  (let ((system-time-locale "C"))
+                    (format-time-string
+                     (org-time-stamp-format
+                      (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
+                     (apply #'encode-time
+                            (save-match-data (org-parse-time-string ts))))))
+                form t t))
 
          (setq ev (if (and duration (string-match 
"^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" form))
                       form
@@ -2742,7 +2897,7 @@ Orig:   %s
 $xyz->  %s
 @r$c->  %s
 $1->    %s\n" orig formula form0 form))
-           (if (listp ev)
+           (if (consp ev)
                (princ (format "        %s^\nError:  %s"
                               (make-string (car ev) ?\-) (nth 1 ev)))
              (princ (format "Result: %s\nFormat: %s\nFinal:  %s"
@@ -2750,14 +2905,14 @@ $1->    %s\n" orig formula form0 form))
                             (if fmt (format fmt (string-to-number ev)) ev)))))
          (setq bw (get-buffer-window "*Substitution History*"))
          (org-fit-window-to-buffer bw)
-         (unless (and (org-called-interactively-p 'any) (not ndown))
+         (unless (and (called-interactively-p 'any) (not ndown))
            (unless (let (inhibit-redisplay)
                      (y-or-n-p "Debugging Formula.  Continue to next? "))
              (org-table-align)
              (user-error "Abort"))
            (delete-window bw)
            (message "")))
-       (if (listp ev) (setq fmt nil ev "#ERROR"))
+       (when (consp ev) (setq fmt nil ev "#ERROR"))
        (org-table-justify-field-maybe
         (format org-table-formula-field-format
                 (if fmt (format fmt (string-to-number ev)) ev)))
@@ -2776,146 +2931,152 @@ $1->    %s\n" orig formula form0 form))
 
 (defun org-table-get-range (desc &optional tbeg col highlight corners-only)
   "Get a calc vector from a column, according to descriptor DESC.
+
 Optional arguments TBEG and COL can give the beginning of the table and
 the current column, to avoid unnecessary parsing.
 
 HIGHLIGHT means just highlight the range.
 
 When CORNERS-ONLY is set, only return the corners of the range as
-a list (line1 column1 line2 column2) where line1 and line2 are line numbers
-in the buffer and column1 and column2 are table column numbers."
-  (if (not (equal (string-to-char desc) ?@))
-      (setq desc (concat "@" desc)))
-  (save-excursion
-    (or tbeg (setq tbeg (org-table-begin)))
-    (or col (setq col (org-table-current-column)))
-    (let ((thisline (org-current-line))
-         beg end c1 c2 r1 r2 rangep tmp)
-      (unless (string-match org-table-range-regexp desc)
-       (user-error "Invalid table range specifier `%s'" desc))
-      (setq rangep (match-end 3)
-           r1 (and (match-end 1) (match-string 1 desc))
-           r2 (and (match-end 4) (match-string 4 desc))
-           c1 (and (match-end 2) (substring (match-string 2 desc) 1))
-           c2 (and (match-end 5) (substring (match-string 5 desc) 1)))
-
-      (and c1 (setq c1 (+ (string-to-number c1)
-                         (if (memq (string-to-char c1) '(?- ?+)) col 0))))
-      (and c2 (setq c2 (+ (string-to-number c2)
-                         (if (memq (string-to-char c2) '(?- ?+)) col 0))))
-      (if (equal r1 "") (setq r1 nil))
-      (if (equal r2 "") (setq r2 nil))
-      (if r1 (setq r1 (org-table-get-descriptor-line r1)))
-      (if r2 (setq r2 (org-table-get-descriptor-line r2)))
-                                       ;      (setq r2 (or r2 r1) c2 (or c2 
c1))
-      (if (not r1) (setq r1 thisline))
-      (if (not r2) (setq r2 thisline))
-      (if (or (not c1) (= 0 c1)) (setq c1 col))
-      (if (or (not c2) (= 0 c2)) (setq c2 col))
-      (if (and (not corners-only)
-              (or (not rangep) (and (= r1 r2) (= c1 c2))))
-         ;; just one field
-         (progn
-           (org-goto-line r1)
-           (while (not (looking-at org-table-dataline-regexp))
-             (beginning-of-line 2))
-           (prog1 (org-trim (org-table-get-field c1))
-             (if highlight (org-table-highlight-rectangle (point) (point)))))
-       ;; A range, return a vector
-       ;; First sort the numbers to get a regular rectangle
-       (if (< r2 r1) (setq tmp r1 r1 r2 r2 tmp))
-       (if (< c2 c1) (setq tmp c1 c1 c2 c2 tmp))
-       (if corners-only
-           ;; Only return the corners of the range
-           (list r1 c1 r2 c2)
-         ;; Copy the range values into a list
-         (org-goto-line r1)
-         (while (not (looking-at org-table-dataline-regexp))
-           (beginning-of-line 2))
-         (org-table-goto-column c1)
-         (setq beg (point))
-         (org-goto-line r2)
-         (while (not (looking-at org-table-dataline-regexp))
-           (beginning-of-line 0))
-         (org-table-goto-column c2)
-         (setq end (point))
-         (if highlight
-             (org-table-highlight-rectangle
-              beg (progn (skip-chars-forward "^|\n") (point))))
-         ;; return string representation of calc vector
-         (mapcar 'org-trim
-                 (apply 'append (org-table-copy-region beg end))))))))
-
-(defun org-table-get-descriptor-line (desc &optional cline bline table)
-  "Analyze descriptor DESC and retrieve the corresponding line number.
-The cursor is currently in line CLINE, the table begins in line BLINE,
-and TABLE is a vector with line types."
-  (if (string-match "^[0-9]+$" desc)
+a list (line1 column1 line2 column2) where line1 and line2 are
+line numbers relative to beginning of table, or TBEG, and column1
+and column2 are table column numbers."
+  (let* ((desc (if (string-match-p "\\`\\$[0-9]+\\.\\.\\$[0-9]+\\'" desc)
+                  (replace-regexp-in-string "\\$" "@0$" desc)
+                desc))
+        (col (or col (org-table-current-column)))
+        (tbeg (or tbeg (org-table-begin)))
+        (thisline (count-lines tbeg (line-beginning-position))))
+    (unless (string-match org-table-range-regexp desc)
+      (user-error "Invalid table range specifier `%s'" desc))
+    (let ((rangep (match-end 3))
+         (r1 (let ((r (and (match-end 1) (match-string 1 desc))))
+               (or (save-match-data
+                     (and (org-string-nw-p r)
+                          (org-table--descriptor-line r thisline)))
+                   thisline)))
+         (r2 (let ((r (and (match-end 4) (match-string 4 desc))))
+               (or (save-match-data
+                     (and (org-string-nw-p r)
+                          (org-table--descriptor-line r thisline)))
+                   thisline)))
+         (c1 (let ((c (and (match-end 2) (substring (match-string 2 desc) 1))))
+               (if (or (not c) (= (string-to-number c) 0)) col
+                 (+ (string-to-number c)
+                    (if (memq (string-to-char c) '(?- ?+)) col 0)))))
+         (c2 (let ((c (and (match-end 5) (substring (match-string 5 desc) 1))))
+               (if (or (not c) (= (string-to-number c) 0)) col
+                 (+ (string-to-number c)
+                    (if (memq (string-to-char c) '(?- ?+)) col 0))))))
+      (save-excursion
+       (if (and (not corners-only)
+                (or (not rangep) (and (= r1 r2) (= c1 c2))))
+           ;; Just one field.
+           (progn
+             (forward-line (- r1 thisline))
+             (while (not (looking-at org-table-dataline-regexp))
+               (forward-line))
+             (prog1 (org-trim (org-table-get-field c1))
+               (when highlight (org-table-highlight-rectangle))))
+         ;; A range, return a vector.  First sort the numbers to get
+         ;; a regular rectangle.
+         (let ((first-row (min r1 r2))
+               (last-row (max r1 r2))
+               (first-column (min c1 c2))
+               (last-column (max c1 c2)))
+           (if corners-only (list first-row first-column last-row last-column)
+             ;; Copy the range values into a list.
+             (forward-line (- first-row thisline))
+             (while (not (looking-at org-table-dataline-regexp))
+               (forward-line)
+               (cl-incf first-row))
+             (org-table-goto-column first-column)
+             (let ((beg (point)))
+               (forward-line (- last-row first-row))
+               (while (not (looking-at org-table-dataline-regexp))
+                 (forward-line -1))
+               (org-table-goto-column last-column)
+               (let ((end (point)))
+                 (when highlight
+                   (org-table-highlight-rectangle
+                    beg (progn (skip-chars-forward "^|\n") (point))))
+                 ;; Return string representation of calc vector.
+                 (mapcar #'org-trim
+                         (apply #'append
+                                (org-table-copy-region beg end))))))))))))
+
+(defun org-table--descriptor-line (desc cline)
+  "Return relative line number corresponding to descriptor DESC.
+The cursor is currently in relative line number CLINE."
+  (if (string-match "\\`[0-9]+\\'" desc)
       (aref org-table-dlines (string-to-number desc))
-    (setq cline (or cline (org-current-line))
-         bline (or bline org-table-current-begin-line)
-         table (or table org-table-current-line-types))
-    (if (or
-        (not (string-match 
"^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" desc))
-        ;;                     1  2          3           4  5          6
-        (and (not (match-end 3)) (not (match-end 6)))
-        (and (match-end 3) (match-end 6) (not (match-end 5))))
-       (user-error "Invalid row descriptor `%s'" desc))
-    (let* ((hdir (and (match-end 2) (match-string 2 desc)))
-          (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil))
-          (odir (and (match-end 5) (match-string 5 desc)))
-          (on (if (match-end 6) (string-to-number (match-string 6 desc))))
-          (i (- cline bline))
+    (when (or (not (string-match
+                   "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?"
+                   ;;  1  2          3           4  5          6
+                   desc))
+             (and (not (match-end 3)) (not (match-end 6)))
+             (and (match-end 3) (match-end 6) (not (match-end 5))))
+      (user-error "Invalid row descriptor `%s'" desc))
+    (let* ((hn (and (match-end 3) (- (match-end 3) (match-beginning 3))))
+          (hdir (match-string 2 desc))
+          (odir (match-string 5 desc))
+          (on (and (match-end 6) (string-to-number (match-string 6 desc))))
           (rel (and (match-end 6)
                     (or (and (match-end 1) (not (match-end 3)))
                         (match-end 5)))))
-      (if (and hn (not hdir))
-         (progn
-           (setq i 0 hdir "+")
-           (if (eq (aref table 0) 'hline) (setq hn (1- hn)))))
-      (if (and (not hn) on (not odir))
-         (user-error "Should never happen");;(aref org-table-dlines on)
-       (if (and hn (> hn 0))
-           (setq i (org-table-find-row-type table i 'hline (equal hdir "-")
-                                            nil hn cline desc)))
-       (if on
-           (setq i (org-table-find-row-type table i 'dline (equal odir "-")
-                                            rel on cline desc)))
-       (+ bline i)))))
-
-(defun org-table-find-row-type (table i type backwards relative n cline desc)
-  "FIXME: Needs more documentation."
-  (let ((l (length table)))
-    (while (> n 0)
-      (while (and (setq i (+ i (if backwards -1 1)))
-                 (>= i 0) (< i l)
-                 (not (eq (aref table i) type))
-                 (if (and relative (eq (aref table i) 'hline))
-                     (cond
-                      ((eq org-table-relative-ref-may-cross-hline t) t)
-                      ((eq org-table-relative-ref-may-cross-hline 'error)
-                       (user-error "Row descriptor %s used in line %d crosses 
hline" desc cline))
-                      (t (setq i (- i (if backwards -1 1))
-                               n 1)
-                         nil))
-                   t)))
-      (setq n (1- n)))
-    (if (or (< i 0) (>= i l))
-       (user-error "Row descriptor %s used in line %d leads outside table"
-              desc cline)
-      i)))
-
-(defun org-table-rewrite-old-row-references (s)
-  (if (string-match "&[-+0-9I]" s)
-      (user-error "Formula contains old &row reference, please rewrite using 
@-syntax")
-    s))
+      (when (and hn (not hdir))
+       (setq cline 0)
+       (setq hdir "+")
+       (when (eq (aref org-table-current-line-types 0) 'hline) (cl-decf hn)))
+      (when (and (not hn) on (not odir)) (user-error "Should never happen"))
+      (when hn
+       (setq cline
+             (org-table--row-type 'hline hn cline (equal hdir "-") nil desc)))
+      (when on
+       (setq cline
+             (org-table--row-type 'dline on cline (equal odir "-") rel desc)))
+      cline)))
+
+(defun org-table--row-type (type n i backwards relative desc)
+  "Return relative line of Nth row with type TYPE.
+Search starts from relative line I.  When BACKWARDS in non-nil,
+look before I.  When RELATIVE is non-nil, the reference is
+relative.  DESC is the original descriptor that started the
+search, as a string."
+  (let ((l (length org-table-current-line-types)))
+    (catch :exit
+      (dotimes (_ n)
+       (while (and (cl-incf i (if backwards -1 1))
+                   (>= i 0)
+                   (< i l)
+                   (not (eq (aref org-table-current-line-types i) type))
+                   ;; We are going to cross a hline.  Check if this is
+                   ;; an authorized move.
+                   (cond
+                    ((not relative))
+                    ((not (eq (aref org-table-current-line-types i) 'hline)))
+                    ((eq org-table-relative-ref-may-cross-hline t))
+                    ((eq org-table-relative-ref-may-cross-hline 'error)
+                     (user-error "Row descriptor %s crosses hline" desc))
+                    (t (cl-decf i (if backwards -1 1)) ; Step back.
+                       (throw :exit nil)))))))
+    (cond ((or (< i 0) (>= i l))
+          (user-error "Row descriptor %s leads outside table" desc))
+         ;; The last hline doesn't exist.  Instead, point to last row
+         ;; in table.
+         ((= i (1- l)) (1- i))
+         (t i))))
+
+(defun org-table--error-on-old-row-references (s)
+  (when (string-match "&[-+0-9I]" s)
+    (user-error "Formula contains old &row reference, please rewrite using 
@-syntax")))
 
 (defun org-table-make-reference (elements keep-empty numbers lispp)
   "Convert list ELEMENTS to something appropriate to insert into formula.
 KEEP-EMPTY indicated to keep empty fields, default is to skip them.
 NUMBERS indicates that everything should be converted to numbers.
 LISPP non-nil means to return something appropriate for a Lisp
-list, 'literal is for the format specifier L."
+list, `literal' is for the format specifier L."
   ;; Calc nan (not a number) is used for the conversion of the empty
   ;; field to a reference for several reasons: (i) It is accepted in a
   ;; Calc formula (e. g. "" or "()" would result in a Calc error).
@@ -2961,162 +3122,185 @@ list, 'literal is for the format specifier L."
                   elements
                   ",") "]"))))
 
-;;;###autoload
-(defun org-table-set-constants ()
-  "Set `org-table-formula-constants-local' in the current buffer."
-  (let (cst consts const-str)
-    (save-excursion
-      (goto-char (point-min))
-      (while (re-search-forward "^[ \t]*#\\+CONSTANTS: \\(.*\\)" nil t)
-       (setq const-str (substring-no-properties (match-string 1)))
-       (setq consts (append consts (org-split-string const-str "[ \t]+")))
-       (when consts
-         (let (e)
-           (while (setq e (pop consts))
-             (when (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
-               (if (assoc-string (match-string 1 e) cst)
-                   (setq cst (delete (assoc-string (match-string 1 e) cst) 
cst)))
-               (push (cons (match-string 1 e) (match-string 2 e)) cst)))
-           (setq org-table-formula-constants-local cst)))))))
+(defun org-table-message-once-per-second (t1 &rest args)
+  "If there has been more than one second since T1, display message.
+ARGS are passed as arguments to the `message' function.  Returns
+current time if a message is printed, otherwise returns T1.  If
+T1 is nil, always messages."
+  (let ((curtime (current-time)))
+    (if (or (not t1) (< 0 (nth 1 (time-subtract curtime t1))))
+       (progn (apply 'message args)
+              curtime)
+      t1)))
 
 ;;;###autoload
 (defun org-table-recalculate (&optional all noalign)
   "Recalculate the current table line by applying all stored formulas.
+
 With prefix arg ALL, do this for all lines in the table.
-With the prefix argument ALL is `(16)' \
-\(a double \\[universal-prefix] \\[universal-prefix] prefix), or if
-it is the symbol `iterate', recompute the table until it no longer changes.
+
+When called with a `\\[universal-argument] \\[universal-argument]' prefix, or \
+if ALL is the symbol `iterate',
+recompute the table until it no longer changes.
+
 If NOALIGN is not nil, do not re-align the table after the computations
 are done.  This is typically used internally to save time, if it is
 known that the table will be realigned a little later anyway."
   (interactive "P")
-  (or (memq this-command org-recalc-commands)
-      (setq org-recalc-commands (cons this-command org-recalc-commands)))
+  (unless (memq this-command org-recalc-commands)
+    (push this-command org-recalc-commands))
   (unless (org-at-table-p) (user-error "Not at a table"))
   (if (or (eq all 'iterate) (equal all '(16)))
       (org-table-iterate)
-    (org-table-get-specials)
+    (org-table-analyze)
     (let* ((eqlist (sort (org-table-get-stored-formulas)
                         (lambda (a b) (string< (car a) (car b)))))
-          (eqlist1 (copy-sequence eqlist))
           (inhibit-redisplay (not debug-on-error))
           (line-re org-table-dataline-regexp)
-          (thisline (org-current-line))
-          (thiscol (org-table-current-column))
-          seen-fields lhs1
-          beg end entry eqlnum eqlname eqlname1 eql (cnt 0) eq a name name1)
-      ;; Insert constants in all formulas
-      (setq eqlist
-           (mapcar (lambda (x)
-                     (when (string-match "\\`$[<>]" (car x))
-                       (setq lhs1 (car x))
-                       (setq x (cons (substring
-                                      (org-table-formula-handle-first/last-rc
-                                       (car x)) 1)
-                                     (cdr x)))
-                       (if (assoc (car x) eqlist1)
-                           (user-error "\"%s=\" formula tries to overwrite 
existing formula for column %s"
-                                  lhs1 (car x))))
-                     (cons
-                      (org-table-formula-handle-first/last-rc (car x))
-                      (org-table-formula-substitute-names
-                       (org-table-formula-handle-first/last-rc (cdr x)))))
-                   eqlist))
-      ;; Split the equation list
-      (while (setq eq (pop eqlist))
-       (if (<= (string-to-char (car eq)) ?9)
-           (push eq eqlnum)
-         (push eq eqlname)))
-      (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
-      ;; Expand ranges in lhs of formulas
-      (setq eqlname (org-table-expand-lhs-ranges eqlname))
-
-      ;; Get the correct line range to process
-      (if all
-         (progn
-           (setq end (move-marker (make-marker) (1+ (org-table-end))))
-           (goto-char (setq beg (org-table-begin)))
-           (if (re-search-forward org-table-calculate-mark-regexp end t)
-               ;; This is a table with marked lines, compute selected lines
-               (setq line-re org-table-recalculate-regexp)
-             ;; Move forward to the first non-header line
-             (if (and (re-search-forward org-table-dataline-regexp end t)
-                      (re-search-forward org-table-hline-regexp end t)
-                      (re-search-forward org-table-dataline-regexp end t))
-                 (setq beg (match-beginning 0))
-               nil))) ;; just leave beg where it is
-       (setq beg (point-at-bol)
-             end (move-marker (make-marker) (1+ (point-at-eol)))))
-      (goto-char beg)
-      (and all (message "Re-applying formulas to full table..."))
-
-      ;; First find the named fields, and mark them untouchable.
-      ;; Also check if several field/range formulas try to set the same field.
-      (remove-text-properties beg end '(org-untouchable t))
-      (while (setq eq (pop eqlname))
-       (setq name (car eq)
-             a (assoc name org-table-named-field-locations))
-       (setq name1 name)
-       (if a (setq name1 (format "@%d$%d" (org-table-line-to-dline (nth 1 a))
-                                 (nth 2 a))))
-       (when (member name1 seen-fields)
-         (user-error "Several field/range formulas try to set %s" name1))
-       (push name1 seen-fields)
-
-       (and (not a)
-            (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name)
-            (setq a (list name
-                          (condition-case nil
-                              (aref org-table-dlines
-                                    (string-to-number (match-string 1 name)))
-                            (error (user-error "Invalid row number in %s"
-                                          name)))
-                          (string-to-number (match-string 2 name)))))
-       (when (and a (or all (equal (nth 1 a) thisline)))
-         (message "Re-applying formula to field: %s" name)
-         (org-goto-line (nth 1 a))
-         (org-table-goto-column (nth 2 a))
-         (push (append a (list (cdr eq))) eqlname1)
-         (org-table-put-field-property :org-untouchable t)))
-      (setq eqlname1 (nreverse eqlname1))
-
-      ;; Now evaluate the column formulas, but skip fields covered by
-      ;; field formulas
-      (goto-char beg)
-      (while (re-search-forward line-re end t)
-       (unless (string-match "^ *[_^!$/] *$" (org-table-get-field 1))
-         ;; Unprotected line, recalculate
-         (and all (message "Re-applying formulas to full table...(line %d)"
-                           (setq cnt (1+ cnt))))
-         (setq org-last-recalc-line (org-current-line))
-         (setq eql eqlnum)
-         (while (setq entry (pop eql))
-           (org-goto-line org-last-recalc-line)
-           (org-table-goto-column (string-to-number (car entry)) nil 'force)
-           (unless (get-text-property (point) :org-untouchable)
-             (org-table-eval-formula nil (cdr entry)
-                                     'noalign 'nocst 'nostore 'noanalysis)))))
-
-      ;; Now evaluate the field formulas
-      (while (setq eq (pop eqlname1))
-       (message "Re-applying formula to field: %s" (car eq))
-       (org-goto-line (nth 1 eq))
-       (org-table-goto-column (nth 2 eq))
-       (org-table-eval-formula nil (nth 3 eq) 'noalign 'nocst
-                               'nostore 'noanalysis))
-
-      (org-goto-line thisline)
-      (org-table-goto-column thiscol)
-      (remove-text-properties (point-min) (point-max) '(org-untouchable t))
-      (or noalign (and org-table-may-need-update (org-table-align))
-         (and all (message "Re-applying formulas to %d lines...done" cnt)))
-
-      ;; back to initial position
-      (message "Re-applying formulas...done")
-      (org-goto-line thisline)
-      (org-table-goto-column thiscol)
-      (or noalign (and org-table-may-need-update (org-table-align))
-         (and all (message "Re-applying formulas...done"))))))
+          (log-first-time (current-time))
+          (log-last-time log-first-time)
+          (cnt 0)
+          beg end eqlcol eqlfield)
+      ;; Insert constants in all formulas.
+      (when eqlist
+       (org-table-save-field
+        ;; Expand equations, then split the equation list between
+        ;; column formulas and field formulas.
+        (dolist (eq eqlist)
+          (let* ((rhs (org-table-formula-substitute-names
+                       (org-table-formula-handle-first/last-rc (cdr eq))))
+                 (old-lhs (car eq))
+                 (lhs
+                  (org-table-formula-handle-first/last-rc
+                   (cond
+                    ((string-match "address@hidden" old-lhs)
+                     (user-error "Can't assign to hline relative reference"))
+                    ((string-match "\\`$[<>]" old-lhs)
+                     (let ((new (org-table-formula-handle-first/last-rc
+                                 old-lhs)))
+                       (when (assoc new eqlist)
+                         (user-error "\"%s=\" formula tries to overwrite \
+existing formula for column %s"
+                                     old-lhs
+                                     new))
+                       new))
+                    (t old-lhs)))))
+            (if (string-match-p "\\`\\$[0-9]+\\'" lhs)
+                (push (cons lhs rhs) eqlcol)
+              (push (cons lhs rhs) eqlfield))))
+        (setq eqlcol (nreverse eqlcol))
+        ;; Expand ranges in lhs of formulas
+        (setq eqlfield (org-table-expand-lhs-ranges (nreverse eqlfield)))
+        ;; Get the correct line range to process.
+        (if all
+            (progn
+              (setq end (copy-marker (org-table-end)))
+              (goto-char (setq beg org-table-current-begin-pos))
+              (cond
+               ((re-search-forward org-table-calculate-mark-regexp end t)
+                ;; This is a table with marked lines, compute selected
+                ;; lines.
+                (setq line-re org-table-recalculate-regexp))
+               ;; Move forward to the first non-header line.
+               ((and (re-search-forward org-table-dataline-regexp end t)
+                     (re-search-forward org-table-hline-regexp end t)
+                     (re-search-forward org-table-dataline-regexp end t))
+                (setq beg (match-beginning 0)))
+               ;; Just leave BEG at the start of the table.
+               (t nil)))
+          (setq beg (line-beginning-position)
+                end (copy-marker (line-beginning-position 2))))
+        (goto-char beg)
+        ;; Mark named fields untouchable.  Also check if several
+        ;; field/range formulas try to set the same field.
+        (remove-text-properties beg end '(org-untouchable t))
+        (let ((current-line (count-lines org-table-current-begin-pos
+                                         (line-beginning-position)))
+              seen-fields)
+          (dolist (eq eqlfield)
+            (let* ((name (car eq))
+                   (location (assoc name org-table-named-field-locations))
+                   (eq-line (or (nth 1 location)
+                                (and (string-match "address@hidden([0-9]+\\)" 
name)
+                                     (aref org-table-dlines
+                                           (string-to-number
+                                            (match-string 1 name))))))
+                   (reference
+                    (if location
+                        ;; Turn field coordinates associated to NAME
+                        ;; into an absolute reference.
+                        (format "@%d$%d"
+                                (org-table-line-to-dline eq-line)
+                                (nth 2 location))
+                      name)))
+              (when (member reference seen-fields)
+                (user-error "Several field/range formulas try to set %s"
+                            reference))
+              (push reference seen-fields)
+              (when (or all (eq eq-line current-line))
+                (org-table-goto-field name)
+                (org-table-put-field-property :org-untouchable t)))))
+        ;; Evaluate the column formulas, but skip fields covered by
+        ;; field formulas.
+        (goto-char beg)
+        (while (re-search-forward line-re end t)
+          (unless (string-match "\\` *[_^!$/] *\\'" (org-table-get-field 1))
+            ;; Unprotected line, recalculate.
+            (cl-incf cnt)
+            (when all
+              (setq log-last-time
+                    (org-table-message-once-per-second
+                     log-last-time
+                     "Re-applying formulas to full table...(line %d)" cnt)))
+            (if (markerp org-last-recalc-line)
+                (move-marker org-last-recalc-line (line-beginning-position))
+              (setq org-last-recalc-line
+                    (copy-marker (line-beginning-position))))
+            (dolist (entry eqlcol)
+              (goto-char org-last-recalc-line)
+              (org-table-goto-column
+               (string-to-number (substring (car entry) 1)) nil 'force)
+              (unless (get-text-property (point) :org-untouchable)
+                (org-table-eval-formula
+                 nil (cdr entry) 'noalign 'nocst 'nostore 'noanalysis)))))
+        ;; Evaluate the field formulas.
+        (dolist (eq eqlfield)
+          (let ((reference (car eq))
+                (formula (cdr eq)))
+            (setq log-last-time
+                  (org-table-message-once-per-second
+                   (and all log-last-time)
+                   "Re-applying formula to field: %s" (car eq)))
+            (org-table-goto-field
+             reference
+             ;; Possibly create a new column, as long as
+             ;; `org-table-formula-create-columns' allows it.
+             (let ((column-count (progn (end-of-line)
+                                        (1- (org-table-current-column)))))
+               (lambda (column)
+                 (when (> column 1000)
+                   (user-error "Formula column target too large"))
+                 (and (> column column-count)
+                      (or (eq org-table-formula-create-columns t)
+                          (and (eq org-table-formula-create-columns 'warn)
+                               (progn
+                                 (org-display-warning
+                                  "Out-of-bounds formula added columns")
+                                 t))
+                          (and (eq org-table-formula-create-columns 'prompt)
+                               (yes-or-no-p
+                                "Out-of-bounds formula.  Add columns? ")))))))
+            (org-table-eval-formula nil formula t t t t))))
+       ;; Clean up markers and internal text property.
+       (remove-text-properties (point-min) (point-max) '(org-untouchable t))
+       (set-marker end nil)
+       (unless noalign
+         (when org-table-may-need-update (org-table-align))
+         (when all
+           (org-table-message-once-per-second
+            log-first-time "Re-applying formulas to %d lines... done" cnt)))
+       (org-table-message-once-per-second
+        (and all log-first-time) "Re-applying formulas... done")))))
 
 ;;;###autoload
 (defun org-table-iterate (&optional arg)
@@ -3145,10 +3329,15 @@ with the prefix ARG."
 (defun org-table-recalculate-buffer-tables ()
   "Recalculate all tables in the current buffer."
   (interactive)
-  (save-excursion
-    (save-restriction
-      (widen)
-      (org-table-map-tables (lambda () (org-table-recalculate t)) t))))
+  (org-with-wide-buffer
+   (org-table-map-tables
+    (lambda ()
+      ;; Reason for separate `org-table-align': When repeating
+      ;; (org-table-recalculate t) `org-table-may-need-update' gets in
+      ;; the way.
+      (org-table-recalculate t t)
+      (org-table-align))
+    t)))
 
 ;;;###autoload
 (defun org-table-iterate-buffer-tables ()
@@ -3158,85 +3347,90 @@ with the prefix ARG."
         (i imax)
         (checksum (md5 (buffer-string)))
         c1)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (catch 'exit
-         (while (> i 0)
-           (setq i (1- i))
-           (org-table-map-tables (lambda () (org-table-recalculate t)) t)
-           (if (equal checksum (setq c1 (md5 (buffer-string))))
-               (progn
-                 (message "Convergence after %d iterations" (- imax i))
-                 (throw 'exit t))
-             (setq checksum c1)))
-         (user-error "No convergence after %d iterations" imax))))))
+    (org-with-wide-buffer
+     (catch 'exit
+       (while (> i 0)
+        (setq i (1- i))
+        (org-table-map-tables (lambda () (org-table-recalculate t t)) t)
+        (if (equal checksum (setq c1 (md5 (buffer-string))))
+            (progn
+              (org-table-map-tables #'org-table-align t)
+              (message "Convergence after %d iterations" (- imax i))
+              (throw 'exit t))
+          (setq checksum c1)))
+       (org-table-map-tables #'org-table-align t)
+       (user-error "No convergence after %d iterations" imax)))))
 
 (defun org-table-calc-current-TBLFM (&optional arg)
   "Apply the #+TBLFM in the line at point to the table."
   (interactive "P")
   (unless (org-at-TBLFM-p) (user-error "Not at a #+TBLFM line"))
   (let ((formula (buffer-substring
-                 (point-at-bol)
-                 (point-at-eol)))
-       s e)
+                 (line-beginning-position)
+                 (line-end-position))))
     (save-excursion
       ;; Insert a temporary formula at right after the table
       (goto-char (org-table-TBLFM-begin))
-      (setq s (point-marker))
-      (insert (concat formula "\n"))
-      (setq e (point-marker))
-      ;; Recalculate the table
-      (beginning-of-line 0)            ; move to the inserted line
-      (skip-chars-backward " \r\n\t")
-      (if (org-at-table-p)
+      (let ((s (point-marker)))
+       (insert formula "\n")
+       (let ((e (point-marker)))
+         ;; Recalculate the table.
+         (beginning-of-line 0)         ; move to the inserted line
+         (skip-chars-backward " \r\n\t")
          (unwind-protect
-             (org-call-with-arg 'org-table-recalculate (or arg t))
-           ;; delete the formula inserted temporarily
-           (delete-region s e))))))
+             (org-call-with-arg #'org-table-recalculate (or arg t))
+           ;; Delete the formula inserted temporarily.
+           (delete-region s e)
+           (set-marker s nil)
+           (set-marker e nil)))))))
 
 (defun org-table-TBLFM-begin ()
   "Find the beginning of the TBLFM lines and return its position.
 Return nil when the beginning of TBLFM line was not found."
   (save-excursion
     (when (progn (forward-line 1)
-             (re-search-backward
-              org-table-TBLFM-begin-regexp
-              nil t))
-         (point-at-bol 2))))
+                (re-search-backward org-table-TBLFM-begin-regexp nil t))
+      (line-beginning-position 2))))
 
 (defun org-table-expand-lhs-ranges (equations)
   "Expand list of formulas.
-If some of the RHS in the formulas are ranges or a row reference, expand
-them to individual field equations for each field."
-  (let (e res lhs rhs range r1 r2 c1 c2)
-    (while (setq e (pop equations))
-      (setq lhs (car e) rhs (cdr e))
-      (cond
-       ((string-match "address@hidden" lhs)
-       ;; This just refers to one fixed field
-       (push e res))
-       ((string-match "^[a-zA-Z][_a-zA-Z0-9]*$" lhs)
-       ;; This just refers to one fixed named field
-       (push e res))
-       ((string-match "address@hidden" lhs)
-       (loop for ic from 1 to org-table-current-ncol do
-             (push (cons (format "%s$%d" lhs ic) rhs) res)
-             (put-text-property 0 (length (caar res))
-                                :orig-eqn e (caar res))))
-       (t
-       (setq range (org-table-get-range lhs org-table-current-begin-pos
-                                        1 nil 'corners))
-       (setq r1 (nth 0 range) c1 (nth 1 range)
-             r2 (nth 2 range) c2 (nth 3 range))
-       (setq r1 (org-table-line-to-dline r1))
-       (setq r2 (org-table-line-to-dline r2 'above))
-       (loop for ir from r1 to r2 do
-             (loop for ic from c1 to c2 do
-                   (push (cons (format "@%d$%d" ir ic) rhs) res)
-                   (put-text-property 0 (length (caar res))
-                                      :orig-eqn e (caar res)))))))
-    (nreverse res)))
+If some of the RHS in the formulas are ranges or a row reference,
+expand them to individual field equations for each field.  This
+function assumes the table is already analyzed (i.e., using
+`org-table-analyze')."
+  (let (res)
+    (dolist (e equations (nreverse res))
+      (let ((lhs (car e))
+           (rhs (cdr e)))
+       (cond
+        ((string-match-p "address@hidden'" lhs)
+         ;; This just refers to one fixed field.
+         (push e res))
+        ((string-match-p "\\`[a-zA-Z][_a-zA-Z0-9]*\\'" lhs)
+         ;; This just refers to one fixed named field.
+         (push e res))
+        ((string-match-p "\\`\\$[0-9]+\\'" lhs)
+         ;; Column formulas are treated specially and are not
+         ;; expanded.
+         (push e res))
+        ((string-match "address@hidden'" lhs)
+         (dotimes (ic org-table-current-ncol)
+           (push (cons (propertize (format "%s$%d" lhs (1+ ic)) :orig-eqn e)
+                       rhs)
+                 res)))
+        (t
+         (let* ((range (org-table-get-range
+                        lhs org-table-current-begin-pos 1 nil 'corners))
+                (r1 (org-table-line-to-dline (nth 0 range)))
+                (c1 (nth 1 range))
+                (r2 (org-table-line-to-dline (nth 2 range) 'above))
+                (c2 (nth 3 range)))
+           (cl-loop for ir from r1 to r2 do
+                    (cl-loop for ic from c1 to c2 do
+                             (push (cons (propertize
+                                          (format "@%d$%d" ir ic) :orig-eqn e)
+                                         rhs)
+                                   res))))))))))
 
 (defun org-table-formula-handle-first/last-rc (s)
   "Replace @<, @>, $<, $> with first/last row/column of the table.
@@ -3262,32 +3456,40 @@ borders of the table using the @< @> $< $> makers."
                  (- nmax len -1)))
        (if (or (< n 1) (> n nmax))
            (user-error "Reference \"%s\" in expression \"%s\" points outside 
table"
-                  (match-string 0 s) s))
+                       (match-string 0 s) s))
        (setq start (match-beginning 0))
        (setq s (replace-match (format "%s%d" (match-string 1 s) n) t t s)))))
   s)
 
 (defun org-table-formula-substitute-names (f)
   "Replace $const with values in string F."
-  (let ((start 0) a (f1 f) (pp (/= (string-to-char f) ?')))
-    ;; First, check for column names
-    (while (setq start (string-match org-table-column-name-regexp f start))
-      (setq start (1+ start))
-      (setq a (assoc (match-string 1 f) org-table-column-names))
-      (setq f (replace-match (concat "$" (cdr a)) t t f)))
-    ;; Parameters and constants
-    (setq start 0)
-    (while (setq start (string-match 
"\\$\\([a-zA-Z][_a-zA-Z0-9]*\\)\\|\\(\\<remote([^)]*)\\)" f start))
-      (if (match-end 2)
-         (setq start (match-end 2))
-       (setq start (1+ start))
-       (if (setq a (save-match-data
-                     (org-table-get-constant (match-string 1 f))))
-           (setq f (replace-match
-                    (concat (if pp "(") a (if pp ")")) t t f)))))
-    (if org-table-formula-debug
-       (put-text-property 0 (length f) :orig-formula f1 f))
-    f))
+  (let ((start 0)
+       (pp (/= (string-to-char f) ?'))
+       (duration (string-match-p ";.*[Tt].*\\'" f))
+       (new (replace-regexp-in-string  ; Check for column names.
+             org-table-column-name-regexp
+             (lambda (m)
+               (concat "$" (cdr (assoc (match-string 1 m)
+                                       org-table-column-names))))
+             f t t)))
+    ;; Parameters and constants.
+    (while (setq start
+                (string-match
+                 "\\$\\([a-zA-Z][_a-zA-Z0-9]*\\)\\|\\(\\<remote([^)]*)\\)"
+                 new start))
+      (if (match-end 2) (setq start (match-end 2))
+       (cl-incf start)
+       ;; When a duration is expected, convert value on the fly.
+       (let ((value
+              (save-match-data
+                (let ((v (org-table-get-constant (match-string 1 new))))
+                  (if (and (org-string-nw-p v) duration)
+                      (org-table-time-string-to-seconds v)
+                    v)))))
+         (when value
+           (setq new (replace-match
+                      (concat (and pp "(") value (and pp ")")) t t new))))))
+    (if org-table-formula-debug (propertize new :orig-formula f) new)))
 
 (defun org-table-get-constant (const)
   "Find the value for a parameter or constant in a formula.
@@ -3353,66 +3555,75 @@ Parameters get priority."
      :style toggle :selected org-table-buffer-is-an]))
 
 (defvar org-pos)
+(defvar org-table--fedit-source nil
+  "Position of the TBLFM line being edited.")
 
 ;;;###autoload
 (defun org-table-edit-formulas ()
   "Edit the formulas of the current table in a separate buffer."
   (interactive)
-  (when (save-excursion (beginning-of-line 1) (let ((case-fold-search t)) 
(looking-at "[ \t]*#\\+TBLFM")))
-    (beginning-of-line 0))
-  (unless (org-at-table-p) (user-error "Not at a table"))
-  (org-table-get-specials)
-  (let ((key (org-table-current-field-formula 'key 'noerror))
-       (eql (sort (org-table-get-stored-formulas 'noerror)
-                  'org-table-formula-less-p))
-       (pos (point-marker))
-       (startline 1)
-       (wc (current-window-configuration))
-       (sel-win (selected-window))
-       (titles '((column . "# Column Formulas\n")
-                 (field . "# Field and Range Formulas\n")
-                 (named . "# Named Field Formulas\n")))
-       entry s type title)
-    (org-switch-to-buffer-other-window "*Edit Formulas*")
-    (erase-buffer)
-    ;; Keep global-font-lock-mode from turning on font-lock-mode
-    (let ((font-lock-global-modes '(not fundamental-mode)))
-      (fundamental-mode))
-    (org-set-local 'font-lock-global-modes (list 'not major-mode))
-    (org-set-local 'org-pos pos)
-    (org-set-local 'org-window-configuration wc)
-    (org-set-local 'org-selected-window sel-win)
-    (use-local-map org-table-fedit-map)
-    (org-add-hook 'post-command-hook 'org-table-fedit-post-command t t)
-    (easy-menu-add org-table-fedit-menu)
-    (setq startline (org-current-line))
-    (while (setq entry (pop eql))
-      (setq type (cond
-                 ((string-match "\\`$[<>]" (car entry)) 'column)
-                 ((equal (string-to-char (car entry)) ?@) 'field)
-                 ((string-match "^[0-9]" (car entry)) 'column)
-                 (t 'named)))
-      (when (setq title (assq type titles))
-       (or (bobp) (insert "\n"))
-       (insert (org-add-props (cdr title) nil 'face font-lock-comment-face))
-       (setq titles (remove title titles)))
-      (if (equal key (car entry)) (setq startline (org-current-line)))
-      (setq s (concat (if (member (string-to-char (car entry)) '(?@ ?$)) "" 
"$")
-                     (car entry) " = " (cdr entry) "\n"))
-      (remove-text-properties 0 (length s) '(face nil) s)
-      (insert s))
-    (if (eq org-table-use-standard-references t)
+  (let ((at-tblfm (org-at-TBLFM-p)))
+    (unless (or at-tblfm (org-at-table-p))
+      (user-error "Not at a table"))
+    (save-excursion
+      ;; Move point within the table before analyzing it.
+      (when at-tblfm (re-search-backward "^[ \t]*|"))
+      (org-table-analyze))
+    (let ((key (org-table-current-field-formula 'key 'noerror))
+         (eql (sort (org-table-get-stored-formulas t (and at-tblfm (point)))
+                    #'org-table-formula-less-p))
+         (pos (point-marker))
+         (source (copy-marker (line-beginning-position)))
+         (startline 1)
+         (wc (current-window-configuration))
+         (sel-win (selected-window))
+         (titles '((column . "# Column Formulas\n")
+                   (field . "# Field and Range Formulas\n")
+                   (named . "# Named Field Formulas\n"))))
+      (org-switch-to-buffer-other-window "*Edit Formulas*")
+      (erase-buffer)
+      ;; Keep global-font-lock-mode from turning on font-lock-mode
+      (let ((font-lock-global-modes '(not fundamental-mode)))
+       (fundamental-mode))
+      (setq-local font-lock-global-modes (list 'not major-mode))
+      (setq-local org-pos pos)
+      (setq-local org-table--fedit-source source)
+      (setq-local org-window-configuration wc)
+      (setq-local org-selected-window sel-win)
+      (use-local-map org-table-fedit-map)
+      (add-hook 'post-command-hook #'org-table-fedit-post-command t t)
+      (easy-menu-add org-table-fedit-menu)
+      (setq startline (org-current-line))
+      (dolist (entry eql)
+       (let* ((type (cond
+                     ((string-match "\\`$\\([0-9]+\\|[<>]+\\)\\'" (car entry))
+                      'column)
+                     ((equal (string-to-char (car entry)) ?@) 'field)
+                     (t 'named)))
+              (title (assq type titles)))
+         (when title
+           (unless (bobp) (insert "\n"))
+           (insert
+            (org-add-props (cdr title) nil 'face font-lock-comment-face))
+           (setq titles (remove title titles)))
+         (when (equal key (car entry)) (setq startline (org-current-line)))
+         (let ((s (concat
+                   (if (memq (string-to-char (car entry)) '(?@ ?$)) "" "$")
+                   (car entry) " = " (cdr entry) "\n")))
+           (remove-text-properties 0 (length s) '(face nil) s)
+           (insert s))))
+      (when (eq org-table-use-standard-references t)
        (org-table-fedit-toggle-ref-type))
-    (org-goto-line startline)
-    (message "%s" "Edit formulas, finish with C-c C-c or C-c '.  See menu for 
more commands.")))
+      (org-goto-line startline)
+      (message "%s" (substitute-command-keys "\\<org-mode-map>\
+Edit formulas, finish with `\\[org-ctrl-c-ctrl-c]' or `\\[org-edit-special]'.  
\
+See menu for more commands.")))))
 
 (defun org-table-fedit-post-command ()
   (when (not (memq this-command '(lisp-complete-symbol)))
     (let ((win (selected-window)))
       (save-excursion
-       (condition-case nil
-           (org-table-show-reference)
-         (error nil))
+       (ignore-errors (org-table-show-reference))
        (select-window win)))))
 
 (defun org-table-formula-to-user (s)
@@ -3537,23 +3748,24 @@ minutes or seconds."
                 (format "%.1f" (/ (float secs0) 60)))
                ((eq output-format 'seconds)
                 (format "%d" secs0))
-               (t (org-format-seconds "%.2h:%.2m:%.2s" secs0)))))
+               (t (format-seconds "%.2h:%.2m:%.2s" secs0)))))
     (if (< secs 0) (concat "-" res) res)))
 
 (defun org-table-fedit-convert-buffer (function)
   "Convert all references in this buffer, using FUNCTION."
-  (let ((line (org-current-line)))
+  (let ((origin (copy-marker (line-beginning-position))))
     (goto-char (point-min))
     (while (not (eobp))
-      (insert (funcall function (buffer-substring (point) (point-at-eol))))
-      (delete-region (point) (point-at-eol))
-      (or (eobp) (forward-char 1)))
-    (org-goto-line line)))
+      (insert (funcall function (buffer-substring (point) 
(line-end-position))))
+      (delete-region (point) (line-end-position))
+      (forward-line))
+    (goto-char origin)
+    (set-marker origin nil)))
 
 (defun org-table-fedit-toggle-ref-type ()
   "Convert all references in the buffer from B3 to @3$2 and back."
   (interactive)
-  (org-set-local 'org-table-buffer-is-an (not org-table-buffer-is-an))
+  (setq-local org-table-buffer-is-an (not org-table-buffer-is-an))
   (org-table-fedit-convert-buffer
    (if org-table-buffer-is-an
        'org-table-convert-refs-to-an 'org-table-convert-refs-to-rc))
@@ -3579,16 +3791,16 @@ minutes or seconds."
 
 (defun org-table-fedit-shift-reference (dir)
   (cond
-   ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&")
+   ((org-in-regexp "\\(\\<[a-zA-Z]\\)&")
     (if (memq dir '(left right))
        (org-rematch-and-replace 1 (eq dir 'left))
       (user-error "Cannot shift reference in this direction")))
-   ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
+   ((org-in-regexp "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
     ;; A B3-like reference
     (if (memq dir '(up down))
        (org-rematch-and-replace 2 (eq dir 'up))
       (org-rematch-and-replace 1 (eq dir 'left))))
-   ((org-at-regexp-p
+   ((org-in-regexp
      
"\\(@\\|\\.\\.\\)\\([-+]?\\(I+\\>\\|[0-9]+\\)\\)\\(\\$\\([-+]?[0-9]+\\)\\)?")
     ;; An internal reference
     (if (memq dir '(up down))
@@ -3649,32 +3861,31 @@ a translation reference."
 With prefix ARG, apply the new formulas to the table."
   (interactive "P")
   (org-table-remove-rectangle-highlight)
-  (if org-table-use-standard-references
-      (progn
-       (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc)
-       (setq org-table-buffer-is-an nil)))
-  (let ((pos org-pos) (sel-win org-selected-window) eql var form)
+  (when org-table-use-standard-references
+    (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc)
+    (setq org-table-buffer-is-an nil))
+  (let ((pos org-pos)
+       (sel-win org-selected-window)
+       (source org-table--fedit-source)
+       eql)
     (goto-char (point-min))
     (while (re-search-forward
            
"^\\(@[-+I<>address@hidden|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|[<>]+\\)\\) *= 
*\\(.*\\(\n[ \t]+.*$\\)*\\)"
            nil t)
-      (setq var (if (match-end 2) (match-string 2) (match-string 1))
-           form (match-string 3))
-      (setq form (org-trim form))
-      (when (not (equal form ""))
-       (while (string-match "[ \t]*\n[ \t]*" form)
-         (setq form (replace-match " " t t form)))
-       (when (assoc var eql)
-         (user-error "Double formulas for %s" var))
-       (push (cons var form) eql)))
-    (setq org-pos nil)
+      (let ((var (match-string 1))
+           (form (org-trim (match-string 3))))
+       (unless (equal form "")
+         (while (string-match "[ \t]*\n[ \t]*" form)
+           (setq form (replace-match " " t t form)))
+         (when (assoc var eql)
+           (user-error "Double formulas for %s" var))
+         (push (cons var form) eql))))
     (set-window-configuration org-window-configuration)
     (select-window sel-win)
-    (goto-char pos)
-    (unless (org-at-table-p)
-      (user-error "Lost table position - cannot install formulas"))
+    (goto-char source)
     (org-table-store-formulas eql)
-    (move-marker pos nil)
+    (set-marker pos nil)
+    (set-marker source nil)
     (kill-buffer "*Edit Formulas*")
     (if arg
        (org-table-recalculate 'all)
@@ -3733,9 +3944,11 @@ With prefix ARG, apply the new formulas to the table."
 (defvar org-show-positions nil)
 
 (defun org-table-show-reference (&optional local)
-  "Show the location/value of the $ expression at point."
+  "Show the location/value of the $ expression at point.
+When LOCAL is non-nil, show references for the table at point."
   (interactive)
   (org-table-remove-rectangle-highlight)
+  (when local (org-table-analyze))
   (catch 'exit
     (let ((pos (if local (point) org-pos))
          (face2 'highlight)
@@ -3743,41 +3956,41 @@ With prefix ARG, apply the new formulas to the table."
          (win (selected-window))
          (org-show-positions nil)
          var name e what match dest)
-      (if local (org-table-get-specials))
       (setq what (cond
-                 ((org-at-regexp-p "address@hidden \t=]")
+                 ((org-in-regexp "address@hidden \t=]")
                   (setq match (concat (substring (match-string 0) 0 -1)
                                       "$1.."
                                       (substring (match-string 0) 0 -1)
                                       "$100"))
                   'range)
-                 ((or (org-at-regexp-p org-table-range-regexp2)
-                      (org-at-regexp-p org-table-translate-regexp)
-                      (org-at-regexp-p org-table-range-regexp))
+                 ((or (org-in-regexp org-table-range-regexp2)
+                      (org-in-regexp org-table-translate-regexp)
+                      (org-in-regexp org-table-range-regexp))
                   (setq match
                         (save-match-data
                           (org-table-convert-refs-to-rc (match-string 0))))
                   'range)
-                 ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
-                 ((org-at-regexp-p "\\$[0-9]+") 'column)
+                 ((org-in-regexp "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
+                 ((org-in-regexp "\\$[0-9]+") 'column)
                  ((not local) nil)
                  (t (user-error "No reference at point")))
            match (and what (or match (match-string 0))))
       (when (and  match (not (equal (match-beginning 0) (point-at-bol))))
        (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0)
                                         'secondary-selection))
-      (org-add-hook 'before-change-functions
-                   'org-table-remove-rectangle-highlight)
-      (if (eq what 'name) (setq var (substring match 1)))
+      (add-hook 'before-change-functions
+               #'org-table-remove-rectangle-highlight)
+      (when (eq what 'name) (setq var (substring match 1)))
       (when (eq what 'range)
-       (or (equal (string-to-char match) ?@) (setq match (concat "@" match)))
+       (unless (eq (string-to-char match) ?@) (setq match (concat "@" match)))
        (setq match (org-table-formula-substitute-names match)))
       (unless local
        (save-excursion
-         (end-of-line 1)
+         (end-of-line)
          (re-search-backward "^\\S-" nil t)
-         (beginning-of-line 1)
-         (when (looking-at 
"\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\\([0-9]+\\|&\\)\\) *=")
+         (beginning-of-line)
+         (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\
+\\([0-9]+\\|&\\)\\) *=")
            (setq dest
                  (save-match-data
                    (org-table-convert-refs-to-rc (match-string 1))))
@@ -3790,60 +4003,52 @@ With prefix ARG, apply the new formulas to the table."
                                                (marker-buffer pos)))))
       (goto-char pos)
       (org-table-force-dataline)
-      (when dest
-       (setq name (substring dest 1))
-       (cond
-        ((string-match "^\\$[a-zA-Z][a-zA-Z0-9]*" dest)
-         (setq e (assoc name org-table-named-field-locations))
-         (org-goto-line (nth 1 e))
-         (org-table-goto-column (nth 2 e)))
-        ((string-match "address@hidden([0-9]+\\)\\$\\([0-9]+\\)" dest)
-         (let ((l (string-to-number (match-string 1 dest)))
-               (c (string-to-number (match-string 2 dest))))
-           (org-goto-line (aref org-table-dlines l))
-           (org-table-goto-column c)))
-        (t (org-table-goto-column (string-to-number name))))
-       (move-marker pos (point))
-       (org-table-highlight-rectangle nil nil face2))
-      (cond
-       ((equal dest match))
-       ((not match))
-       ((eq what 'range)
-       (condition-case nil
-           (save-excursion
-             (org-table-get-range match nil nil 'highlight))
-         (error nil)))
-       ((setq e (assoc var org-table-named-field-locations))
-       (org-goto-line (nth 1 e))
-       (org-table-goto-column (nth 2 e))
-       (org-table-highlight-rectangle (point) (point))
-       (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
-       ((setq e (assoc var org-table-column-names))
-       (org-table-goto-column (string-to-number (cdr e)))
-       (org-table-highlight-rectangle (point) (point))
-       (goto-char (org-table-begin))
-       (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
-                              (org-table-end) t)
-           (progn
-             (goto-char (match-beginning 1))
-             (org-table-highlight-rectangle)
-             (message "Named column (column %s)" (cdr e)))
-         (user-error "Column name not found")))
-       ((eq what 'column)
-       ;; column number
-       (org-table-goto-column (string-to-number (substring match 1)))
-       (org-table-highlight-rectangle (point) (point))
-       (message "Column %s" (substring match 1)))
-       ((setq e (assoc var org-table-local-parameters))
-       (goto-char (org-table-begin))
-       (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") 
nil t)
-           (progn
-             (goto-char (match-beginning 1))
-             (org-table-highlight-rectangle)
-             (message "Local parameter."))
-         (user-error "Parameter not found")))
-       (t
+      (let ((table-start
+            (if local org-table-current-begin-pos (org-table-begin))))
+       (when dest
+         (setq name (substring dest 1))
+         (cond
+          ((string-match-p "\\`\\$[a-zA-Z][a-zA-Z0-9]*" dest)
+           (org-table-goto-field dest))
+          ((string-match-p 
"address@hidden([1-9][0-9]*\\)\\$\\([1-9][0-9]*\\)\\'"
+                           dest)
+           (org-table-goto-field dest))
+          (t (org-table-goto-column (string-to-number name))))
+         (move-marker pos (point))
+         (org-table-highlight-rectangle nil nil face2))
        (cond
+        ((equal dest match))
+        ((not match))
+        ((eq what 'range)
+         (ignore-errors (org-table-get-range match table-start nil 
'highlight)))
+        ((setq e (assoc var org-table-named-field-locations))
+         (org-table-goto-field var)
+         (org-table-highlight-rectangle)
+         (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
+        ((setq e (assoc var org-table-column-names))
+         (org-table-goto-column (string-to-number (cdr e)))
+         (org-table-highlight-rectangle)
+         (goto-char table-start)
+         (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
+                                (org-table-end) t)
+             (progn
+               (goto-char (match-beginning 1))
+               (org-table-highlight-rectangle)
+               (message "Named column (column %s)" (cdr e)))
+           (user-error "Column name not found")))
+        ((eq what 'column)
+         ;; Column number.
+         (org-table-goto-column (string-to-number (substring match 1)))
+         (org-table-highlight-rectangle)
+         (message "Column %s" (substring match 1)))
+        ((setq e (assoc var org-table-local-parameters))
+         (goto-char table-start)
+         (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") 
nil t)
+             (progn
+               (goto-char (match-beginning 1))
+               (org-table-highlight-rectangle)
+               (message "Local parameter."))
+           (user-error "Parameter not found")))
         ((not var) (user-error "No reference at point"))
         ((setq e (assoc var org-table-formula-constants-local))
          (message "Local Constant: $%s=%s in #+CONSTANTS line."
@@ -3854,19 +4059,19 @@ With prefix ARG, apply the new formulas to the table."
         ((setq e (and (fboundp 'constants-get) (constants-get var)))
          (message "Constant: $%s=%s, from `constants.el'%s."
                   var e (format " (%s units)" constants-unit-system)))
-        (t (user-error "Undefined name $%s" var)))))
-      (goto-char pos)
-      (when (and org-show-positions
-                (not (memq this-command '(org-table-fedit-scroll
-                                          org-table-fedit-scroll-down))))
-       (push pos org-show-positions)
-       (push org-table-current-begin-pos org-show-positions)
-       (let ((min (apply 'min org-show-positions))
-             (max (apply 'max org-show-positions)))
-         (set-window-start (selected-window) min)
-         (goto-char max)
-         (or (pos-visible-in-window-p max)
-             (set-window-start (selected-window) max))))
+        (t (user-error "Undefined name $%s" var)))
+       (goto-char pos)
+       (when (and org-show-positions
+                  (not (memq this-command '(org-table-fedit-scroll
+                                            org-table-fedit-scroll-down))))
+         (push pos org-show-positions)
+         (push table-start org-show-positions)
+         (let ((min (apply 'min org-show-positions))
+               (max (apply 'max org-show-positions)))
+           (set-window-start (selected-window) min)
+           (goto-char max)
+           (or (pos-visible-in-window-p max)
+               (set-window-start (selected-window) max)))))
       (select-window win))))
 
 (defun org-table-force-dataline ()
@@ -3926,43 +4131,49 @@ Use COMMAND to do the motion, repeat if necessary to 
end up in a data line."
     (push ov org-table-rectangle-overlays)))
 
 (defun org-table-highlight-rectangle (&optional beg end face)
-  "Highlight rectangular region in a table."
-  (setq beg (or beg (point)) end (or end (point)))
-  (let ((b (min beg end))
-       (e (max beg end))
-       l1 c1 l2 c2 tmp)
-    (and (boundp 'org-show-positions)
-        (setq org-show-positions (cons b (cons e org-show-positions))))
-    (goto-char (min beg end))
-    (setq l1 (org-current-line)
-         c1 (org-table-current-column))
-    (goto-char (max beg end))
-    (setq l2 (org-current-line)
-         c2 (org-table-current-column))
-    (if (> c1 c2) (setq tmp c1 c1 c2 c2 tmp))
-    (org-goto-line l1)
-    (beginning-of-line 1)
-    (loop for line from l1 to l2 do
-         (when (looking-at org-table-dataline-regexp)
-           (org-table-goto-column c1)
-           (skip-chars-backward "^|\n") (setq beg (point))
-           (org-table-goto-column c2)
-           (skip-chars-forward "^|\n")  (setq end (point))
-           (org-table-add-rectangle-overlay beg end face))
-         (beginning-of-line 2))
-    (goto-char b))
-  (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight))
-
-(defun org-table-remove-rectangle-highlight (&rest ignore)
+  "Highlight rectangular region in a table.
+When buffer positions BEG and END are provided, use them to
+delimit the region to highlight.  Otherwise, refer to point.  Use
+FACE, when non-nil, for the highlight."
+  (let* ((beg (or beg (point)))
+        (end (or end (point)))
+        (b (min beg end))
+        (e (max beg end))
+        (start-coordinates
+         (save-excursion
+           (goto-char b)
+           (cons (line-beginning-position) (org-table-current-column))))
+        (end-coordinates
+         (save-excursion
+           (goto-char e)
+           (cons (line-beginning-position) (org-table-current-column)))))
+    (when (boundp 'org-show-positions)
+      (setq org-show-positions (cons b (cons e org-show-positions))))
+    (goto-char (car start-coordinates))
+    (let ((column-start (min (cdr start-coordinates) (cdr end-coordinates)))
+         (column-end (max (cdr start-coordinates) (cdr end-coordinates)))
+         (last-row (car end-coordinates)))
+      (while (<= (point) last-row)
+       (when (looking-at org-table-dataline-regexp)
+         (org-table-goto-column column-start)
+         (skip-chars-backward "^|\n")
+         (let ((p (point)))
+           (org-table-goto-column column-end)
+           (skip-chars-forward "^|\n")
+           (org-table-add-rectangle-overlay p (point) face)))
+       (forward-line)))
+    (goto-char (car start-coordinates)))
+  (add-hook 'before-change-functions #'org-table-remove-rectangle-highlight))
+
+(defun org-table-remove-rectangle-highlight (&rest _ignore)
   "Remove the rectangle overlays."
   (unless org-inhibit-highlight-removal
     (remove-hook 'before-change-functions 
'org-table-remove-rectangle-highlight)
     (mapc 'delete-overlay org-table-rectangle-overlays)
     (setq org-table-rectangle-overlays nil)))
 
-(defvar org-table-coordinate-overlays nil
+(defvar-local org-table-coordinate-overlays nil
   "Collects the coordinate grid overlays, so that they can be removed.")
-(make-variable-buffer-local 'org-table-coordinate-overlays)
 
 (defun org-table-overlay-coordinates ()
   "Add overlays to the table at point, to show row/column coordinates."
@@ -4017,19 +4228,20 @@ Use COMMAND to do the motion, repeat if necessary to 
end up in a data line."
 ;;; The orgtbl minor mode
 
 ;; Define a minor mode which can be used in other modes in order to
-;; integrate the org-mode table editor.
-
-;; This is really a hack, because the org-mode table editor uses several
-;; keys which normally belong to the major mode, for example the TAB and
-;; RET keys.  Here is how it works: The minor mode defines all the keys
-;; necessary to operate the table editor, but wraps the commands into a
-;; function which tests if the cursor is currently inside a table.  If that
-;; is the case, the table editor command is executed.  However, when any of
-;; those keys is used outside a table, the function uses `key-binding' to
-;; look up if the key has an associated command in another currently active
-;; keymap (minor modes, major mode, global), and executes that command.
-;; There might be problems if any of the keys used by the table editor is
-;; otherwise used as a prefix key.
+;; integrate the Org table editor.
+
+;; This is really a hack, because the Org table editor uses several
+;; keys which normally belong to the major mode, for example the TAB
+;; and RET keys.  Here is how it works: The minor mode defines all the
+;; keys necessary to operate the table editor, but wraps the commands
+;; into a function which tests if the cursor is currently inside
+;; a table.  If that is the case, the table editor command is
+;; executed.  However, when any of those keys is used outside a table,
+;; the function uses `key-binding' to look up if the key has an
+;; associated command in another currently active keymap (minor modes,
+;; major mode, global), and executes that command.  There might be
+;; problems if any of the keys used by the table editor is otherwise
+;; used as a prefix key.
 
 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
 ;; likewise the binding for RET can be return or \C-m.  Orgtbl-mode
@@ -4079,16 +4291,16 @@ Use COMMAND to do the motion, repeat if necessary to 
end up in a data line."
       ;; FIXME: maybe it should use emulation-mode-map-alists?
       (and c (setq minor-mode-map-alist
                    (cons c (delq c minor-mode-map-alist)))))
-    (org-set-local (quote org-table-may-need-update) t)
-    (org-add-hook 'before-change-functions 'org-before-change-function
-                  nil 'local)
-    (org-set-local 'org-old-auto-fill-inhibit-regexp
-                   auto-fill-inhibit-regexp)
-    (org-set-local 'auto-fill-inhibit-regexp
-                   (if auto-fill-inhibit-regexp
-                       (concat orgtbl-line-start-regexp "\\|"
-                               auto-fill-inhibit-regexp)
-                     orgtbl-line-start-regexp))
+    (setq-local org-table-may-need-update t)
+    (add-hook 'before-change-functions 'org-before-change-function
+             nil 'local)
+    (setq-local org-old-auto-fill-inhibit-regexp
+               auto-fill-inhibit-regexp)
+    (setq-local auto-fill-inhibit-regexp
+               (if auto-fill-inhibit-regexp
+                   (concat orgtbl-line-start-regexp "\\|"
+                           auto-fill-inhibit-regexp)
+                 orgtbl-line-start-regexp))
     (add-to-invisibility-spec '(org-cwidth))
     (when (fboundp 'font-lock-add-keywords)
       (font-lock-add-keywords nil orgtbl-extra-font-lock-keywords)
@@ -4188,27 +4400,26 @@ to execute outside of tables."
            cmd (orgtbl-make-binding fun nfunc key))
       (org-defkey orgtbl-mode-map key cmd))
 
-    ;; Special treatment needed for TAB and RET
+    ;; Special treatment needed for TAB, RET and DEL
     (org-defkey orgtbl-mode-map [(return)]
                (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
     (org-defkey orgtbl-mode-map "\C-m"
                (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
-
     (org-defkey orgtbl-mode-map [(tab)]
                (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
     (org-defkey orgtbl-mode-map "\C-i"
                (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
-
     (org-defkey orgtbl-mode-map [(shift tab)]
                (orgtbl-make-binding 'org-table-previous-field 104
                                     [(shift tab)] [(tab)] "\C-i"))
+    (org-defkey orgtbl-mode-map [backspace]
+               (orgtbl-make-binding 'org-delete-backward-char 109
+                                    [backspace] (kbd "DEL")))
 
-
-    (unless (featurep 'xemacs)
-      (org-defkey orgtbl-mode-map [S-iso-lefttab]
-                 (orgtbl-make-binding 'org-table-previous-field 107
-                                      [S-iso-lefttab] [backtab] [(shift tab)]
-                                      [(tab)] "\C-i")))
+    (org-defkey orgtbl-mode-map [S-iso-lefttab]
+               (orgtbl-make-binding 'org-table-previous-field 107
+                                    [S-iso-lefttab] [backtab] [(shift tab)]
+                                    [(tab)] "\C-i"))
 
     (org-defkey orgtbl-mode-map [backtab]
                (orgtbl-make-binding 'org-table-previous-field 108
@@ -4290,7 +4501,10 @@ to execute outside of tables."
         org-table-toggle-coordinate-overlays :active (org-at-table-p)
         :keys "C-c }"
         :style toggle :selected org-table-overlay-coordinates]
-       ))
+       "--"
+       ("Plot"
+        ["Ascii plot" orgtbl-ascii-plot :active (org-at-table-p) :keys "C-c \" 
a"]
+        ["Gnuplot" org-plot/gnuplot :active (org-at-table-p) :keys "C-c \" 
g"])))
     t))
 
 (defun orgtbl-ctrl-c-ctrl-c (arg)
@@ -4316,7 +4530,6 @@ With prefix arg, also recompute table."
       (when (orgtbl-send-table 'maybe)
        (run-hooks 'orgtbl-after-send-table-hook)))
      ((eq action 'recalc)
-      (org-table-set-constants)
       (save-excursion
        (beginning-of-line 1)
        (skip-chars-backward " \r\n\t")
@@ -4325,7 +4538,7 @@ With prefix arg, also recompute table."
      (t (let (orgtbl-mode)
          (call-interactively (key-binding "\C-c\C-c")))))))
 
-(defun orgtbl-create-or-convert-from-region (arg)
+(defun orgtbl-create-or-convert-from-region (_arg)
   "Create table or convert region to table, if no conflicting binding.
 This installs the table binding `C-c |', but only if there is no
 conflicting binding to this key outside orgtbl-mode."
@@ -4369,11 +4582,9 @@ overwritten, and the table is not marked as requiring 
realignment."
                 (org-table-blank-field))
            t)
           (eq N 1)
-          (looking-at "[^|\n]*  +|"))
+          (looking-at "[^|\n]* \\( \\)|"))
       (let (org-table-may-need-update)
-       (goto-char (1- (match-end 0)))
-       (org-delete-backward-char 1)
-       (goto-char (match-beginning 0))
+       (delete-region (match-beginning 1) (match-end 1))
        (self-insert-command N))
     (setq org-table-may-need-update t)
     (let* (orgtbl-mode
@@ -4398,6 +4609,7 @@ overwritten, and the table is not marked as requiring 
realignment."
              (setq org-self-insert-command-undo-counter
                    (1+ org-self-insert-command-undo-counter))))))))
 
+;;;###autoload
 (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$"
   "Regular expression matching exponentials as produced by calc.")
 
@@ -4418,23 +4630,24 @@ a radio table."
          (beginning-of-line 0)))
       rtn)))
 
-(defun orgtbl-send-replace-tbl (name txt)
-  "Find and replace table NAME with TXT."
+(defun orgtbl-send-replace-tbl (name text)
+  "Find and replace table NAME with TEXT."
   (save-excursion
     (goto-char (point-min))
-    (unless (re-search-forward
-            (concat "BEGIN +RECEIVE +ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
-      (user-error "Don't know where to insert translated table"))
-    (goto-char (match-beginning 0))
-    (beginning-of-line 2)
-    (save-excursion
-      (let ((beg (point)))
-       (unless (re-search-forward
-                (concat "END +RECEIVE +ORGTBL +" name) nil t)
-         (user-error "Cannot find end of insertion region"))
-       (beginning-of-line 1)
-       (delete-region beg (point))))
-    (insert txt "\n")))
+    (let* ((location-flag nil)
+          (name (regexp-quote name))
+          (begin-re (format "BEGIN +RECEIVE +ORGTBL +%s\\([ \t]\\|$\\)" name))
+          (end-re (format "END +RECEIVE +ORGTBL +%s\\([ \t]\\|$\\)" name)))
+      (while (re-search-forward begin-re nil t)
+       (unless location-flag (setq location-flag t))
+       (let ((beg (line-beginning-position 2)))
+         (unless (re-search-forward end-re nil t)
+           (user-error "Cannot find end of receiver location at %d" beg))
+         (beginning-of-line)
+         (delete-region beg (point))
+         (insert text "\n")))
+      (unless location-flag
+       (user-error "No valid receiver location found in the buffer")))))
 
 ;;;###autoload
 (defun org-table-to-lisp (&optional txt)
@@ -4442,76 +4655,43 @@ a radio table."
 The structure will be a list.  Each item is either the symbol `hline'
 for a horizontal separator line, or a list of field values as strings.
 The table is taken from the parameter TXT, or from the buffer at point."
-  (unless txt
-    (unless (org-at-table-p)
-      (user-error "No table at point")))
-  (let* ((txt (or txt
-                 (buffer-substring-no-properties (org-table-begin)
-                                                 (org-table-end))))
-        (lines (org-split-string txt "[ \t]*\n[ \t]*")))
-
-    (mapcar
-     (lambda (x)
-       (if (string-match org-table-hline-regexp x)
-          'hline
-        (org-split-string (org-trim x) "\\s-*|\\s-*")))
-     lines)))
+  (unless (or txt (org-at-table-p)) (user-error "No table at point"))
+  (let ((txt (or txt
+                (buffer-substring-no-properties (org-table-begin)
+                                                (org-table-end)))))
+    (mapcar (lambda (x)
+             (if (string-match org-table-hline-regexp x) 'hline
+               (org-split-string (org-trim x) "\\s-*|\\s-*")))
+           (org-split-string txt "[ \t]*\n[ \t]*"))))
 
 (defun orgtbl-send-table (&optional maybe)
-  "Send a transformed version of this table to the receiver position.
-With argument MAYBE, fail quietly if no transformation is defined for
-this table."
+  "Send a transformed version of table at point to the receiver position.
+With argument MAYBE, fail quietly if no transformation is defined
+for this table."
   (interactive)
   (catch 'exit
     (unless (org-at-table-p) (user-error "Not at a table"))
     ;; when non-interactive, we assume align has just happened.
-    (when (org-called-interactively-p 'any) (org-table-align))
+    (when (called-interactively-p 'any) (org-table-align))
     (let ((dests (orgtbl-gather-send-defs))
-         (txt (buffer-substring-no-properties (org-table-begin)
-                                              (org-table-end)))
+         (table (org-table-to-lisp
+                 (buffer-substring-no-properties (org-table-begin)
+                                                 (org-table-end))))
          (ntbl 0))
-      (unless dests (if maybe (throw 'exit nil)
-                     (user-error "Don't know how to transform this table")))
+      (unless dests
+       (if maybe (throw 'exit nil)
+         (user-error "Don't know how to transform this table")))
       (dolist (dest dests)
-       (let* ((name (plist-get dest :name))
-              (transform (plist-get dest :transform))
-              (params (plist-get dest :params))
-              (skip (plist-get params :skip))
-              (skipcols (plist-get params :skipcols))
-              (no-escape (plist-get params :no-escape))
-              beg
-              (lines (org-table-clean-before-export
-                      (nthcdr (or skip 0)
-                              (org-split-string txt "[ \t]*\n[ \t]*"))))
-              (i0 (if org-table-clean-did-remove-column 2 1))
-              (lines (if no-escape lines
-                       (mapcar (lambda(l) (replace-regexp-in-string
-                                           "\\([&%#_^]\\)" "\\\\\\1{}" l)) 
lines)))
-              (table (mapcar
-                      (lambda (x)
-                        (if (string-match org-table-hline-regexp x)
-                            'hline
-                          (org-remove-by-index
-                           (org-split-string (org-trim x) "\\s-*|\\s-*")
-                           skipcols i0)))
-                      lines))
-              (fun (if (= i0 2) 'cdr 'identity))
-              (org-table-last-alignment
-               (org-remove-by-index (funcall fun org-table-last-alignment)
-                                    skipcols i0))
-              (org-table-last-column-widths
-               (org-remove-by-index (funcall fun org-table-last-column-widths)
-                                    skipcols i0))
-              (txt (if (fboundp transform)
-                       (funcall transform table params)
-                     (user-error "No such transformation function %s" 
transform))))
-         (orgtbl-send-replace-tbl name txt))
-       (setq ntbl (1+ ntbl)))
+       (let ((name (plist-get dest :name))
+             (transform (plist-get dest :transform))
+             (params (plist-get dest :params)))
+         (unless (fboundp transform)
+           (user-error "No such transformation function %s" transform))
+         (orgtbl-send-replace-tbl name (funcall transform table params)))
+       (cl-incf ntbl))
       (message "Table converted and installed at %d receiver location%s"
               ntbl (if (> ntbl 1) "s" ""))
-      (if (> ntbl 0)
-         ntbl
-       nil))))
+      (and (> ntbl 0) ntbl))))
 
 (defun org-remove-by-index (list indices &optional i0)
   "Remove the elements in LIST with indices in INDICES.
@@ -4561,356 +4741,512 @@ First element has index 0, or I0 if given."
     (insert txt)
     (goto-char pos)))
 
-;; Dynamically bound input and output for table formatting.
-(defvar *orgtbl-table* nil
-  "Carries the current table through formatting routines.")
-(defvar *orgtbl-rtn* nil
-  "Formatting routines push the output lines here.")
-;; Formatting parameters for the current table section.
-(defvar *orgtbl-hline* nil "Text used for horizontal lines.")
-(defvar *orgtbl-sep* nil "Text used as a column separator.")
-(defvar *orgtbl-default-fmt* nil "Default format for each entry.")
-(defvar *orgtbl-fmt* nil "Format for each entry.")
-(defvar *orgtbl-efmt* nil "Format for numbers.")
-(defvar *orgtbl-lfmt* nil "Format for an entire line, overrides fmt.")
-(defvar *orgtbl-llfmt* nil "Specializes lfmt for the last row.")
-(defvar *orgtbl-lstart* nil "Text starting a row.")
-(defvar *orgtbl-llstart* nil "Specializes lstart for the last row.")
-(defvar *orgtbl-lend* nil "Text ending a row.")
-(defvar *orgtbl-llend* nil "Specializes lend for the last row.")
-
-(defsubst orgtbl-get-fmt (fmt i)
-  "Retrieve the format from FMT corresponding to the Ith column."
-  (if (and (not (functionp fmt)) (consp fmt))
-      (plist-get fmt i)
-    fmt))
-
-(defsubst orgtbl-apply-fmt (fmt &rest args)
-  "Apply format FMT to arguments ARGS.
-When FMT is nil, return the first argument from ARGS."
-  (cond ((functionp fmt) (apply fmt args))
-       (fmt (apply 'format fmt args))
-       (args (car args))
-       (t args)))
-
-(defsubst orgtbl-eval-str (str)
-  "If STR is a function, evaluate it with no arguments."
-  (if (functionp str)
-      (funcall str)
-    str))
-
-(defun orgtbl-format-line (line)
-  "Format LINE as a table row."
-  (if (eq line 'hline) (if *orgtbl-hline* (push *orgtbl-hline* *orgtbl-rtn*))
-    (let* ((i 0)
-          (line
-           (mapcar
-            (lambda (f)
-              (setq i (1+ i))
-              (let* ((efmt (orgtbl-get-fmt *orgtbl-efmt* i))
-                     (f (if (and efmt (string-match orgtbl-exp-regexp f))
-                            (orgtbl-apply-fmt efmt (match-string 1 f)
-                                              (match-string 2 f))
-                          f)))
-                (orgtbl-apply-fmt (or (orgtbl-get-fmt *orgtbl-fmt* i)
-                                      *orgtbl-default-fmt*)
-                                  f)))
-            line)))
-      (push (if *orgtbl-lfmt*
-               (apply #'orgtbl-apply-fmt *orgtbl-lfmt* line)
-             (concat (orgtbl-eval-str *orgtbl-lstart*)
-                     (mapconcat 'identity line *orgtbl-sep*)
-                     (orgtbl-eval-str *orgtbl-lend*)))
-           *orgtbl-rtn*))))
-
-(defun orgtbl-format-section (section-stopper)
-  "Format lines until the first occurrence of SECTION-STOPPER."
-  (let (prevline)
-    (progn
-      (while (not (eq (car *orgtbl-table*) section-stopper))
-       (if prevline (orgtbl-format-line prevline))
-       (setq prevline (pop *orgtbl-table*)))
-      (if prevline (let ((*orgtbl-lstart* *orgtbl-llstart*)
-                        (*orgtbl-lend* *orgtbl-llend*)
-                        (*orgtbl-lfmt* *orgtbl-llfmt*))
-                    (orgtbl-format-line prevline))))))
-
 ;;;###autoload
-(defun orgtbl-to-generic (table params &optional backend)
+(defun orgtbl-to-generic (table params)
   "Convert the orgtbl-mode TABLE to some other format.
+
 This generic routine can be used for many standard cases.
-TABLE is a list, each entry either the symbol `hline' for a horizontal
-separator line, or a list of fields for that line.
-PARAMS is a property list of parameters that can influence the conversion.
-A third optional argument BACKEND can be used to convert the content of
-the cells using a specific export back-end.
 
-For the generic converter, some parameters are obligatory: you need to
-specify either :lfmt, or all of (:lstart :lend :sep).
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that
+line.  PARAMS is a property list of parameters that can
+influence the conversion.
 
 Valid parameters are:
 
-:splice     When set to t, return only table body lines, don't wrap
-            them into :tstart and :tend.  Default is nil.  When :splice
-            is non-nil, this also means that the exporter should not look
-            for and interpret header and footer sections.
+:backend, :raw
+
+  Export back-end used as a basis to transcode elements of the
+  table, when no specific parameter applies to it.  It is also
+  used to translate cells contents.  You can prevent this by
+  setting :raw property to a non-nil value.
 
-:hline      String to be inserted on horizontal separation lines.
-            May be nil to ignore hlines.
+:splice
 
-:sep        Separator between two fields
-:remove-nil-lines Do not include lines that evaluate to nil.
+  When non-nil, only convert rows, not the table itself.  This is
+  equivalent to setting to the empty string both :tstart
+  and :tend, which see.
+
+:skip
+
+  When set to an integer N, skip the first N lines of the table.
+  Horizontal separation lines do count for this parameter!
+
+:skipcols
+
+  List of columns that should be skipped.  If the table has
+  a column with calculation marks, that column is automatically
+  discarded beforehand.
+
+:hline
+
+  String to be inserted on horizontal separation lines.  May be
+  nil to ignore these lines altogether.
+
+:sep
+
+  Separator between two fields, as a string.
 
 Each in the following group may be either a string or a function
 of no arguments returning a string:
 
-:tstart     String to start the table.  Ignored when :splice is t.
-:tend       String to end the table.  Ignored when :splice is t.
-:lstart     String to start a new table line.
-:llstart    String to start the last table line, defaults to :lstart.
-:lend       String to end a table line
-:llend      String to end the last table line, defaults to :lend.
-
-Each in the following group may be a string, a function of one
-argument (the field or line) returning a string, or a plist
-mapping columns to either of the above:
-
-:lfmt       Format for entire line, with enough %s to capture all fields.
-            If this is present, :lstart, :lend, and :sep are ignored.
-:llfmt      Format for the entire last line, defaults to :lfmt.
-:fmt        A format to be used to wrap the field, should contain
-            %s for the original field value.  For example, to wrap
-            everything in dollars, you could use :fmt \"$%s$\".
-            This may also be a property list with column numbers and
-            formats.  For example :fmt (2 \"$%s$\" 4 \"%s%%\")
-:hlstart :hllstart :hlend :hllend :hlsep :hlfmt :hllfmt :hfmt
-            Same as above, specific for the header lines in the table.
-            All lines before the first hline are treated as header.
-            If any of these is not present, the data line value is used.
+:tstart, :tend
+
+  Strings to start and end the table.  Ignored when :splice is t.
+
+:lstart, :lend
+
+  Strings to start and end a new table line.
+
+:llstart, :llend
+
+  Strings to start and end the last table line.  Default,
+  respectively, to :lstart and :lend.
+
+Each in the following group may be a string or a function of one
+argument (either the cells in the current row, as a list of
+strings, or the current cell) returning a string:
+
+:lfmt
+
+  Format string for an entire row, with enough %s to capture all
+  fields.  When non-nil, :lstart, :lend, and :sep are ignored.
+
+:llfmt
+
+  Format for the entire last line, defaults to :lfmt.
+
+:fmt
+
+  A format to be used to wrap the field, should contain %s for
+  the original field value.  For example, to wrap everything in
+  dollars, you could use :fmt \"$%s$\".  This may also be
+  a property list with column numbers and format strings, or
+  functions, e.g.,
+
+    (:fmt (2 \"$%s$\" 4 (lambda (c) (format \"$%s$\" c))))
+
+:hlstart :hllstart :hlend :hllend :hsep :hlfmt :hllfmt :hfmt
+
+ Same as above, specific for the header lines in the table.
+ All lines before the first hline are treated as header.  If
+ any of these is not present, the data line value is used.
 
 This may be either a string or a function of two arguments:
 
-:efmt       Use this format to print numbers with exponentials.
-            The format should have %s twice for inserting mantissa
-            and exponent, for example \"%s\\\\times10^{%s}\".  This
-            may also be a property list with column numbers and
-            formats.  :fmt will still be applied after :efmt.
-
-In addition to this, the parameters :skip and :skipcols are always handled
-directly by `orgtbl-send-table'.  See manual."
-  (let* ((splicep (plist-get params :splice))
-        (hline (plist-get params :hline))
-        (skipheadrule (plist-get params :skipheadrule))
-        (remove-nil-linesp (plist-get params :remove-nil-lines))
-        (remove-newlines (plist-get params :remove-newlines))
-        (*orgtbl-hline* hline)
-        (*orgtbl-table* table)
-        (*orgtbl-sep* (plist-get params :sep))
-        (*orgtbl-efmt* (plist-get params :efmt))
-        (*orgtbl-lstart* (plist-get params :lstart))
-        (*orgtbl-llstart* (or (plist-get params :llstart) *orgtbl-lstart*))
-        (*orgtbl-lend* (plist-get params :lend))
-        (*orgtbl-llend* (or (plist-get params :llend) *orgtbl-lend*))
-        (*orgtbl-lfmt* (plist-get params :lfmt))
-        (*orgtbl-llfmt* (or (plist-get params :llfmt) *orgtbl-lfmt*))
-        (*orgtbl-fmt* (plist-get params :fmt))
-        *orgtbl-rtn*)
-    ;; Convert cells content to backend BACKEND
-    (when backend
-      (setq *orgtbl-table*
-           (mapcar
-            (lambda(r)
-              (if (listp r)
-                  (mapcar
-                   (lambda (c)
-                     (org-trim (org-export-string-as c backend t 
'(:with-tables t))))
-                   r)
-                r))
-            *orgtbl-table*)))
-    ;; Put header
-    (unless splicep
-      (when (plist-member params :tstart)
-       (let ((tstart (orgtbl-eval-str (plist-get params :tstart))))
-         (if tstart (push tstart *orgtbl-rtn*)))))
-    ;; If we have a heading, format it and handle the trailing hline.
-    (if (and (not splicep)
-            (or (consp (car *orgtbl-table*))
-                (consp (nth 1 *orgtbl-table*)))
-            (memq 'hline (cdr *orgtbl-table*)))
-       (progn
-         (when (eq 'hline (car *orgtbl-table*))
-           ;; There is a hline before the first data line
-           (and hline (push hline *orgtbl-rtn*))
-           (pop *orgtbl-table*))
-         (let* ((*orgtbl-lstart* (or (plist-get params :hlstart)
-                                     *orgtbl-lstart*))
-                (*orgtbl-llstart* (or (plist-get params :hllstart)
-                                      *orgtbl-llstart*))
-                (*orgtbl-lend* (or (plist-get params :hlend) *orgtbl-lend*))
-                (*orgtbl-llend* (or (plist-get params :hllend)
-                                    (plist-get params :hlend) *orgtbl-llend*))
-                (*orgtbl-lfmt* (or (plist-get params :hlfmt) *orgtbl-lfmt*))
-                (*orgtbl-llfmt* (or (plist-get params :hllfmt)
-                                    (plist-get params :hlfmt) *orgtbl-llfmt*))
-                (*orgtbl-sep* (or (plist-get params :hlsep) *orgtbl-sep*))
-                (*orgtbl-fmt* (or (plist-get params :hfmt) *orgtbl-fmt*)))
-           (orgtbl-format-section 'hline))
-         (if (and hline (not skipheadrule)) (push hline *orgtbl-rtn*))
-         (pop *orgtbl-table*)))
-    ;; Now format the main section.
-    (orgtbl-format-section nil)
-    (unless splicep
-      (when (plist-member params :tend)
-       (let ((tend (orgtbl-eval-str (plist-get params :tend))))
-         (if tend (push tend *orgtbl-rtn*)))))
-    (mapconcat (if remove-newlines
-                  (lambda (tend)
-                    (replace-regexp-in-string "[\n\r\t\f]" "\\\\n" tend))
-                'identity)
-              (nreverse (if remove-nil-linesp
-                            (remq nil *orgtbl-rtn*)
-                          *orgtbl-rtn*)) "\n")))
+:efmt
+
+  Use this format to print numbers with exponential.  The format
+  should have %s twice for inserting mantissa and exponent, for
+  example \"%s\\\\times10^{%s}\".  This may also be a property
+  list with column numbers and format strings or functions.
+  :fmt will still be applied after :efmt."
+  ;; Make sure `org-export-create-backend' is available.
+  (require 'ox)
+  (let* ((backend (plist-get params :backend))
+        (custom-backend
+         ;; Build a custom back-end according to PARAMS.  Before
+         ;; defining a translator, check if there is anything to do.
+         ;; When there isn't, let BACKEND handle the element.
+         (org-export-create-backend
+          :parent (or backend 'org)
+          :transcoders
+          `((table . ,(org-table--to-generic-table params))
+            (table-row . ,(org-table--to-generic-row params))
+            (table-cell . ,(org-table--to-generic-cell params))
+            ;; Macros are not going to be expanded.  However, no
+            ;; regular back-end has a transcoder for them.  We
+            ;; provide one so they are not ignored, but displayed
+            ;; as-is instead.
+            (macro . (lambda (m c i) (org-element-macro-interpreter m nil))))))
+        data info)
+    ;; Store TABLE as Org syntax in DATA.  Tolerate non-string cells.
+    ;; Initialize communication channel in INFO.
+    (with-temp-buffer
+      (let ((org-inhibit-startup t)) (org-mode))
+      (let ((standard-output (current-buffer)))
+       (dolist (e table)
+         (cond ((eq e 'hline) (princ "|--\n"))
+               ((consp e)
+                (princ "| ") (dolist (c e) (princ c) (princ " |"))
+                (princ "\n")))))
+      ;; Add back-end specific filters, but not user-defined ones.  In
+      ;; particular, make sure to call parse-tree filters on the
+      ;; table.
+      (setq info
+           (let ((org-export-filters-alist nil))
+             (org-export-install-filters
+              (org-combine-plists
+               (org-export-get-environment backend nil params)
+               `(:back-end ,(org-export-get-backend backend))))))
+      (setq data
+           (org-export-filter-apply-functions
+            (plist-get info :filter-parse-tree)
+            (org-element-map (org-element-parse-buffer) 'table
+              #'identity nil t)
+            info)))
+    (when (and backend (symbolp backend) (not (org-export-get-backend 
backend)))
+      (user-error "Unknown :backend value"))
+    (when (or (not backend) (plist-get info :raw)) (require 'ox-org))
+    ;; Handle :skip parameter.
+    (let ((skip (plist-get info :skip)))
+      (when skip
+       (unless (wholenump skip) (user-error "Wrong :skip value"))
+       (let ((n 0))
+         (org-element-map data 'table-row
+           (lambda (row)
+             (if (>= n skip) t
+               (org-element-extract-element row)
+               (cl-incf n)
+               nil))
+           nil t))))
+    ;; Handle :skipcols parameter.
+    (let ((skipcols (plist-get info :skipcols)))
+      (when skipcols
+       (unless (consp skipcols) (user-error "Wrong :skipcols value"))
+       (org-element-map data 'table
+         (lambda (table)
+           (let ((specialp (org-export-table-has-special-column-p table)))
+             (dolist (row (org-element-contents table))
+               (when (eq (org-element-property :type row) 'standard)
+                 (let ((c 1))
+                   (dolist (cell (nthcdr (if specialp 1 0)
+                                         (org-element-contents row)))
+                     (when (memq c skipcols)
+                       (org-element-extract-element cell))
+                     (cl-incf c))))))))))
+    ;; Since we are going to export using a low-level mechanism,
+    ;; ignore special column and special rows manually.
+    (let ((special? (org-export-table-has-special-column-p data))
+         ignore)
+      (org-element-map data (if special? '(table-cell table-row) 'table-row)
+       (lambda (datum)
+         (when (if (eq (org-element-type datum) 'table-row)
+                   (org-export-table-row-is-special-p datum nil)
+                 (org-export-first-sibling-p datum nil))
+           (push datum ignore))))
+      (setq info (plist-put info :ignore-list ignore)))
+    ;; We use a low-level mechanism to export DATA so as to skip all
+    ;; usual pre-processing and post-processing, i.e., hooks, Babel
+    ;; code evaluation, include keywords and macro expansion.  Only
+    ;; back-end specific filters are retained.
+    (let ((output (org-export-data-with-backend data custom-backend info)))
+      ;; Remove final newline.
+      (if (org-string-nw-p output) (substring-no-properties output 0 -1) ""))))
+
+(defun org-table--generic-apply (value name &optional with-cons &rest args)
+  (cond ((null value) nil)
+        ((functionp value) `(funcall ',value ,@args))
+        ((stringp value)
+        (cond ((consp (car args)) `(apply #'format ,value ,@args))
+              (args `(format ,value ,@args))
+              (t value)))
+       ((and with-cons (consp value))
+        `(let ((val (cadr (memq column ',value))))
+           (cond ((null val) contents)
+                 ((stringp val) (format val ,@args))
+                 ((functionp val) (funcall val ,@args))
+                 (t (user-error "Wrong %s value" ,name)))))
+        (t (user-error "Wrong %s value" name))))
+
+(defun org-table--to-generic-table (params)
+  "Return custom table transcoder according to PARAMS.
+PARAMS is a plist.  See `orgtbl-to-generic' for more
+information."
+  (let ((backend (plist-get params :backend))
+       (splice (plist-get params :splice))
+       (tstart (plist-get params :tstart))
+       (tend (plist-get params :tend)))
+    `(lambda (table contents info)
+       (concat
+       ,(and tstart (not splice)
+             `(concat ,(org-table--generic-apply tstart ":tstart") "\n"))
+       ,(if (or (not backend) tstart tend splice) 'contents
+          `(org-export-with-backend ',backend table contents info))
+       ,(org-table--generic-apply (and (not splice) tend) ":tend")))))
+
+(defun org-table--to-generic-row (params)
+  "Return custom table row transcoder according to PARAMS.
+PARAMS is a plist.  See `orgtbl-to-generic' for more
+information."
+  (let* ((backend (plist-get params :backend))
+        (lstart (plist-get params :lstart))
+        (llstart (plist-get params :llstart))
+        (hlstart (plist-get params :hlstart))
+        (hllstart (plist-get params :hllstart))
+        (lend (plist-get params :lend))
+        (llend (plist-get params :llend))
+        (hlend (plist-get params :hlend))
+        (hllend (plist-get params :hllend))
+        (lfmt (plist-get params :lfmt))
+        (llfmt (plist-get params :llfmt))
+        (hlfmt (plist-get params :hlfmt))
+        (hllfmt (plist-get params :hllfmt)))
+    `(lambda (row contents info)
+       (if (eq (org-element-property :type row) 'rule)
+          ,(cond
+            ((plist-member params :hline)
+             (org-table--generic-apply (plist-get params :hline) ":hline"))
+            (backend `(org-export-with-backend ',backend row nil info)))
+        (let ((headerp (org-export-table-row-in-header-p row info))
+              (lastp (not (org-export-get-next-element row info)))
+              (last-header-p (org-export-table-row-ends-header-p row info)))
+          (when contents
+            ;; Check if we can apply `:lfmt', `:llfmt', `:hlfmt', or
+            ;; `:hllfmt' to CONTENTS.  Otherwise, fallback on
+            ;; `:lstart', `:lend' and their relatives.
+            ,(let ((cells
+                    '(org-element-map row 'table-cell
+                       (lambda (cell)
+                         ;; Export all cells, without separators.
+                         ;;
+                         ;; Use `org-export-data-with-backend'
+                         ;; instead of `org-export-data' to eschew
+                         ;; cached values, which
+                         ;; ignore :orgtbl-ignore-sep parameter.
+                         (org-export-data-with-backend
+                          cell
+                          (plist-get info :back-end)
+                          (org-combine-plists info '(:orgtbl-ignore-sep t))))
+                       info)))
+               `(cond
+                 ,(and hllfmt
+                       `(last-header-p ,(org-table--generic-apply
+                                         hllfmt ":hllfmt" nil cells)))
+                 ,(and hlfmt
+                       `(headerp ,(org-table--generic-apply
+                                   hlfmt ":hlfmt" nil cells)))
+                 ,(and llfmt
+                       `(lastp ,(org-table--generic-apply
+                                 llfmt ":llfmt" nil cells)))
+                 (t
+                  ,(if lfmt (org-table--generic-apply lfmt ":lfmt" nil cells)
+                     `(concat
+                       (cond
+                        ,(and
+                          (or hllstart hllend)
+                          `(last-header-p
+                            (concat
+                             ,(org-table--generic-apply hllstart ":hllstart")
+                             contents
+                             ,(org-table--generic-apply hllend ":hllend"))))
+                        ,(and
+                          (or hlstart hlend)
+                          `(headerp
+                            (concat
+                             ,(org-table--generic-apply hlstart ":hlstart")
+                             contents
+                             ,(org-table--generic-apply hlend ":hlend"))))
+                        ,(and
+                          (or llstart llend)
+                          `(lastp
+                            (concat
+                             ,(org-table--generic-apply llstart ":llstart")
+                             contents
+                             ,(org-table--generic-apply llend ":llend"))))
+                        (t
+                         ,(cond
+                           ((or lstart lend)
+                            `(concat
+                              ,(org-table--generic-apply lstart ":lstart")
+                              contents
+                              ,(org-table--generic-apply lend ":lend")))
+                           (backend
+                            `(org-export-with-backend
+                              ',backend row contents info))
+                           (t 'contents)))))))))))))))
+
+(defun org-table--to-generic-cell (params)
+  "Return custom table cell transcoder according to PARAMS.
+PARAMS is a plist.  See `orgtbl-to-generic' for more
+information."
+  (let* ((backend (plist-get params :backend))
+        (efmt (plist-get params :efmt))
+        (fmt (plist-get params :fmt))
+        (hfmt (plist-get params :hfmt))
+        (sep (plist-get params :sep))
+        (hsep (plist-get params :hsep)))
+    `(lambda (cell contents info)
+       (let ((headerp (org-export-table-row-in-header-p
+                      (org-export-get-parent-element cell) info))
+            (column (1+ (cdr (org-export-table-cell-address cell info)))))
+        ;; Make sure that contents are exported as Org data when :raw
+        ;; parameter is non-nil.
+        ,(when (and backend (plist-get params :raw))
+           `(setq contents
+                  ;; Since we don't know what are the pseudo object
+                  ;; types defined in backend, we cannot pass them to
+                  ;; `org-element-interpret-data'.  As a consequence,
+                  ;; they will be treated as pseudo elements, and
+                  ;; will have newlines appended instead of spaces.
+                  ;; Therefore, we must make sure :post-blank value
+                  ;; is really turned into spaces.
+                  (replace-regexp-in-string
+                   "\n" " "
+                   (org-trim
+                    (org-element-interpret-data
+                     (org-element-contents cell))))))
+        (when contents
+          ;; Check if we can apply `:efmt' on CONTENTS.
+          ,(when efmt
+             `(when (string-match orgtbl-exp-regexp contents)
+                (let ((mantissa (match-string 1 contents))
+                      (exponent (match-string 2 contents)))
+                  (setq contents ,(org-table--generic-apply
+                                   efmt ":efmt" t 'mantissa 'exponent)))))
+          ;; Check if we can apply FMT (or HFMT) on CONTENTS.
+          (cond
+           ,(and hfmt `(headerp (setq contents ,(org-table--generic-apply
+                                                 hfmt ":hfmt" t 'contents))))
+           ,(and fmt `(t (setq contents ,(org-table--generic-apply
+                                          fmt ":fmt" t 'contents))))))
+        ;; If a separator is provided, use it instead of BACKEND's.
+        ;; Separators are ignored when LFMT (or equivalent) is
+        ;; provided.
+        ,(cond
+          ((or hsep sep)
+           `(if (or ,(and (not sep) '(not headerp))
+                    (plist-get info :orgtbl-ignore-sep)
+                    (not (org-export-get-next-element cell info)))
+                ,(if (not backend) 'contents
+                   `(org-export-with-backend ',backend cell contents info))
+              (concat contents
+                      ,(if (and sep hsep) `(if headerp ,hsep ,sep)
+                         (or hsep sep)))))
+          (backend `(org-export-with-backend ',backend cell contents info))
+          (t 'contents))))))
 
 ;;;###autoload
 (defun orgtbl-to-tsv (table params)
   "Convert the orgtbl-mode table to TAB separated material."
   (orgtbl-to-generic table (org-combine-plists '(:sep "\t") params)))
+
 ;;;###autoload
 (defun orgtbl-to-csv (table params)
   "Convert the orgtbl-mode table to CSV material.
 This does take care of the proper quoting of fields with comma or quotes."
-  (orgtbl-to-generic table (org-combine-plists
-                           '(:sep "," :fmt org-quote-csv-field)
-                           params)))
+  (orgtbl-to-generic table
+                    (org-combine-plists '(:sep "," :fmt org-quote-csv-field)
+                                        params)))
 
 ;;;###autoload
 (defun orgtbl-to-latex (table params)
   "Convert the orgtbl-mode TABLE to LaTeX.
-TABLE is a list, each entry either the symbol `hline' for a horizontal
-separator line, or a list of fields for that line.
-PARAMS is a property list of parameters that can influence the conversion.
-Supports all parameters from `orgtbl-to-generic'.  Most important for
-LaTeX are:
-
-:splice    When set to t, return only table body lines, don't wrap
-           them into a tabular environment.  Default is nil.
-
-:fmt       A format to be used to wrap the field, should contain %s for the
-           original field value.  For example, to wrap everything in dollars,
-           use :fmt \"$%s$\".  This may also be a property list with column
-           numbers and formats.  For example :fmt (2 \"$%s$\" 4 \"%s%%\")
-           The format may also be a function that formats its one argument.
-
-:efmt      Format for transforming numbers with exponentials.  The format
-           should have %s twice for inserting mantissa and exponent, for
-           example \"%s\\\\times10^{%s}\".  LaTeX default is \"%s\\\\,(%s)\".
-           This may also be a property list with column numbers and formats.
-           The format may also be a function that formats its two arguments.
-
-:llend     If you find too much space below the last line of a table,
-           pass a value of \"\" for :llend to suppress the final \\\\.
-
-The general parameters :skip and :skipcols have already been applied when
-this function is called."
-  (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
-                              org-table-last-alignment ""))
-        (params2
-         (list
-          :tstart (concat "\\begin{tabular}{" alignment "}")
-          :tend "\\end{tabular}"
-          :lstart "" :lend " \\\\" :sep " & "
-          :efmt "%s\\,(%s)" :hline "\\hline")))
-    (require 'ox-latex)
-    (orgtbl-to-generic table (org-combine-plists params2 params) 'latex)))
+
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported.  It is also possible to use the following ones:
+
+:booktabs
+
+  When non-nil, use formal \"booktabs\" style.
+
+:environment
+
+  Specify environment to use, as a string.  If you use
+  \"longtable\", you may also want to specify :language property,
+  as a string, to get proper continuation strings."
+  (require 'ox-latex)
+  (orgtbl-to-generic
+   table
+   (org-combine-plists
+    ;; Provide sane default values.
+    (list :backend 'latex
+         :latex-default-table-mode 'table
+         :latex-tables-centered nil
+         :latex-tables-booktabs (plist-get params :booktabs)
+         :latex-table-scientific-notation nil
+         :latex-default-table-environment
+         (or (plist-get params :environment) "tabular"))
+    params)))
 
 ;;;###autoload
 (defun orgtbl-to-html (table params)
   "Convert the orgtbl-mode TABLE to HTML.
-TABLE is a list, each entry either the symbol `hline' for a horizontal
-separator line, or a list of fields for that line.
-PARAMS is a property list of parameters that can influence the conversion.
-Currently this function recognizes the following parameters:
 
-:splice    When set to t, return only table body lines, don't wrap
-           them into a <table> environment.  Default is nil.
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported.  It is also possible to use the following one:
 
-The general parameters :skip and :skipcols have already been applied when
-this function is called.  The function does *not* use `orgtbl-to-generic',
-so you cannot specify parameters for it."
+:attributes
+
+  Attributes and values, as a plist, which will be used in
+  <table> tag."
   (require 'ox-html)
-  (let ((output (org-export-string-as
-                (orgtbl-to-orgtbl table nil) 'html t '(:with-tables t))))
-    (if (not (plist-get params :splice)) output
-      (org-trim
-       (replace-regexp-in-string
-       "\\`<table .*>\n" ""
-       (replace-regexp-in-string "</table>\n*\\'" "" output))))))
+  (orgtbl-to-generic
+   table
+   (org-combine-plists
+    ;; Provide sane default values.
+    (list :backend 'html
+         :html-table-data-tags '("<td%s>" . "</td>")
+         :html-table-use-header-tags-for-first-column nil
+         :html-table-align-individual-fields t
+         :html-table-row-tags '("<tr>" . "</tr>")
+         :html-table-attributes
+         (if (plist-member params :attributes)
+             (plist-get params :attributes)
+           '(:border "2" :cellspacing "0" :cellpadding "6" :rules "groups"
+                     :frame "hsides")))
+    params)))
 
 ;;;###autoload
 (defun orgtbl-to-texinfo (table params)
-  "Convert the orgtbl-mode TABLE to TeXInfo.
-TABLE is a list, each entry either the symbol `hline' for a horizontal
-separator line, or a list of fields for that line.
-PARAMS is a property list of parameters that can influence the conversion.
-Supports all parameters from `orgtbl-to-generic'.  Most important for
-TeXInfo are:
-
-:splice nil/t      When set to t, return only table body lines, don't wrap
-                   them into a multitable environment.  Default is nil.
-
-:fmt fmt           A format to be used to wrap the field, should contain
-                   %s for the original field value.  For example, to wrap
-                   everything in @kbd{}, you could use :fmt \"@kbd{%s}\".
-                   This may also be a property list with column numbers and
-                   formats.  For example :fmt (2 \"@kbd{%s}\" 4 \"@code{%s}\").
-                   Each format also may be a function that formats its one
-                   argument.
-
-:cf \"f1 f2..\"    The column fractions for the table.  By default these
-                   are computed automatically from the width of the columns
-                   under org-mode.
-
-The general parameters :skip and :skipcols have already been applied when
-this function is called."
-  (let* ((total (float (apply '+ org-table-last-column-widths)))
-        (colfrac (or (plist-get params :cf)
-                     (mapconcat
-                      (lambda (x) (format "%.3f" (/ (float x) total)))
-                      org-table-last-column-widths " ")))
-        (params2
-         (list
-          :tstart (concat "@multitable @columnfractions " colfrac)
-          :tend "@end multitable"
-          :lstart "@item " :lend "" :sep " @tab "
-          :hlstart "@headitem ")))
-    (require 'ox-texinfo)
-    (orgtbl-to-generic table (org-combine-plists params2 params) 'texinfo)))
+  "Convert the orgtbl-mode TABLE to Texinfo.
+
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported.  It is also possible to use the following one:
+
+:columns
+
+  Column widths, as a string.  When providing column fractions,
+  \"@columnfractions\" command can be omitted."
+  (require 'ox-texinfo)
+  (let ((output
+        (orgtbl-to-generic
+         table
+         (org-combine-plists
+          (list :backend 'texinfo
+                :texinfo-tables-verbatim nil
+                :texinfo-table-scientific-notation nil)
+          params)))
+       (columns (let ((w (plist-get params :columns)))
+                  (cond ((not w) nil)
+                        ((string-match-p "{\\|@columnfractions " w) w)
+                        (t (concat "@columnfractions " w))))))
+    (if (not columns) output
+      (replace-regexp-in-string
+       "@multitable \\(.*\\)" columns output t nil 1))))
 
 ;;;###autoload
 (defun orgtbl-to-orgtbl (table params)
   "Convert the orgtbl-mode TABLE into another orgtbl-mode table.
+
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported.
+
 Useful when slicing one table into many.  The :hline, :sep,
-:lstart, and :lend provide orgtbl framing.  The default nil :tstart
-and :tend suppress strings without splicing; they can be set to
-provide ORGTBL directives for the generated table."
-  (let* ((params2
-         (list
-          :remove-newlines t
-          :tstart nil :tend nil
-          :hline "|---"
-          :sep " | "
-          :lstart "| "
-          :lend " |"))
-        (params (org-combine-plists params2 params)))
-    (with-temp-buffer
-      (insert (orgtbl-to-generic table params))
-      (goto-char (point-min))
-      (while (re-search-forward org-table-hline-regexp nil t)
-       (org-table-align))
-      (buffer-substring 1 (buffer-size)))))
+:lstart, and :lend provide orgtbl framing.  :tstart and :tend can
+be set to provide ORGTBL directives for the generated table."
+  (require 'ox-org)
+  (orgtbl-to-generic table (org-combine-plists params (list :backend 'org))))
 
 (defun orgtbl-to-table.el (table params)
-  "Convert the orgtbl-mode TABLE into a table.el table."
+  "Convert the orgtbl-mode TABLE into a table.el table.
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported."
   (with-temp-buffer
     (insert (orgtbl-to-orgtbl table params))
     (org-table-align)
@@ -4920,19 +5256,137 @@ provide ORGTBL directives for the generated table."
 
 (defun orgtbl-to-unicode (table params)
   "Convert the orgtbl-mode TABLE into a table with unicode characters.
-You need the ascii-art-to-unicode.el package for this.  You can download
-it here: http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el.";
-  (with-temp-buffer
-    (insert (orgtbl-to-table.el table params))
-    (goto-char (point-min))
-    (if (or (featurep 'ascii-art-to-unicode)
-           (require 'ascii-art-to-unicode nil t))
-       (aa2u)
-      (unless (delq nil (mapcar (lambda (l) (string-match "aa2u" (car l))) 
org-stored-links))
-       (push '("http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el";
-               "Link to ascii-art-to-unicode.el") org-stored-links))
-      (user-error "Please download ascii-art-to-unicode.el (use C-c C-l to 
insert the link to it)"))
-    (buffer-string)))
+
+TABLE is a list, each entry either the symbol `hline' for
+a horizontal separator line, or a list of fields for that line.
+PARAMS is a property list of parameters that can influence the
+conversion.  All parameters from `orgtbl-to-generic' are
+supported.  It is also possible to use the following ones:
+
+:ascii-art
+
+  When non-nil, use \"ascii-art-to-unicode\" package to translate
+  the table.  You can download it here:
+  http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el.
+
+:narrow
+
+  When non-nil, narrow columns width than provided width cookie,
+  using \"=>\" as an ellipsis, just like in an Org mode buffer."
+  (require 'ox-ascii)
+  (orgtbl-to-generic
+   table
+   (org-combine-plists
+    (list :backend 'ascii
+         :ascii-charset 'utf-8
+         :ascii-table-widen-columns (not (plist-get params :narrow))
+         :ascii-table-use-ascii-art (plist-get params :ascii-art))
+    params)))
+
+;; Put the cursor in a column containing numerical values
+;; of an Org table,
+;; type C-c " a
+;; A new column is added with a bar plot.
+;; When the table is refreshed (C-u C-c *),
+;; the plot is updated to reflect the new values.
+
+(defun orgtbl-ascii-draw (value min max &optional width characters)
+  "Draw an ascii bar in a table.
+VALUE is the value to plot, it determines the width of the bar to draw.
+MIN is the value that will be displayed as empty (zero width bar).
+MAX is the value that will draw a bar filling all the WIDTH.
+WIDTH is the span in characters from MIN to MAX.
+CHARACTERS is a string that will compose the bar, with shades of grey
+from pure white to pure black.  It defaults to a 10 characters string
+of regular ascii characters."
+  (let* ((width      (ceiling (or width 12)))
+        (characters (or characters " .:;c!lhVHW"))
+        (len        (1- (length characters)))
+        (value      (float (if (numberp value)
+                               value (string-to-number value))))
+        (relative   (/ (- value min) (- max min)))
+        (steps      (round (* relative width len))))
+    (cond ((< steps             0) "too small")
+         ((> steps (* width len)) "too large")
+         (t (let* ((int-division (/ steps len))
+                   (remainder    (- steps (* int-division len))))
+              (concat (make-string int-division (elt characters len))
+                      (string (elt characters remainder))))))))
+
+;;;###autoload
+(defun orgtbl-ascii-plot (&optional ask)
+  "Draw an ASCII bar plot in a column.
+
+With cursor in a column containing numerical values, this function
+will draw a plot in a new column.
+
+ASK, if given, is a numeric prefix to override the default 12
+characters width of the plot.  ASK may also be the `\\[universal-argument]' \
+prefix,
+which will prompt for the width."
+  (interactive "P")
+  (let ((col (org-table-current-column))
+       (min  1e999)             ; 1e999 will be converted to infinity
+       (max -1e999)             ; which is the desired result
+       (table (org-table-to-lisp))
+       (length
+        (cond ((consp ask)
+               (read-number "Length of column " 12))
+              ((numberp ask) ask)
+              (t 12))))
+    ;; Skip any hline a the top of table.
+    (while (eq (car table) 'hline) (setq table (cdr table)))
+    ;; Skip table header if any.
+    (dolist (x (or (cdr (memq 'hline table)) table))
+      (when (consp x)
+       (setq x (nth (1- col) x))
+       (when (string-match
+              "^[-+]?\\([0-9]*[.]\\)?[0-9]*\\([eE][+-]?[0-9]+\\)?$"
+              x)
+         (setq x (string-to-number x))
+         (when (> min x) (setq min x))
+         (when (< max x) (setq max x)))))
+    (org-table-insert-column)
+    (org-table-move-column-right)
+    (org-table-store-formulas
+     (cons
+      (cons
+       (concat "$" (number-to-string (1+ col)))
+       (format "'(%s $%s %s %s %s)"
+              "orgtbl-ascii-draw" col min max length))
+      (org-table-get-stored-formulas)))
+    (org-table-recalculate t)))
+
+;; Example of extension: unicode characters
+;; Here are two examples of different styles.
+
+;; Unicode block characters are used to give a smooth effect.
+;; See http://en.wikipedia.org/wiki/Block_Elements
+;; Use one of those drawing functions
+;; - orgtbl-ascii-draw   (the default ascii)
+;; - orgtbl-uc-draw-grid (unicode with a grid effect)
+;; - orgtbl-uc-draw-cont (smooth unicode)
+
+;; This is best viewed with the "DejaVu Sans Mono" font
+;; (use M-x set-default-font).
+
+(defun orgtbl-uc-draw-grid (value min max &optional width)
+  "Draw a bar in a table using block unicode characters.
+It is a variant of orgtbl-ascii-draw with Unicode block
+characters, for a smooth display.  Bars appear as grids (to the
+extent the font allows)."
+  ;; http://en.wikipedia.org/wiki/Block_Elements
+  ;; best viewed with the "DejaVu Sans Mono" font.
+  (orgtbl-ascii-draw value min max width
+                    " \u258F\u258E\u258D\u258C\u258B\u258A\u2589"))
+
+(defun orgtbl-uc-draw-cont (value min max &optional width)
+  "Draw a bar in a table using block unicode characters.
+It is a variant of orgtbl-ascii-draw with Unicode block
+characters, for a smooth display.  Bars are solid (to the extent
+the font allows)."
+  (orgtbl-ascii-draw value min max width
+                    " \u258F\u258E\u258D\u258C\u258B\u258A\u2589\u2588"))
 
 (defun org-table-get-remote-range (name-or-id form)
   "Get a field value or a list of values in a range from table at ID.
@@ -4949,57 +5403,74 @@ The return value is either a single string for a single 
field, or a
 list of the fields in the rectangle."
   (save-match-data
     (let ((case-fold-search t) (id-loc nil)
-         ;; Protect a bunch of variables from being overwritten
-         ;; by the context of the remote table
+         ;; Protect a bunch of variables from being overwritten by
+         ;; the context of the remote table.
          org-table-column-names org-table-column-name-regexp
          org-table-local-parameters org-table-named-field-locations
-         org-table-current-line-types org-table-current-begin-line
+         org-table-current-line-types
          org-table-current-begin-pos org-table-dlines
          org-table-current-ncol
          org-table-hlines org-table-last-alignment
          org-table-last-column-widths org-table-last-alignment
-         org-table-last-column-widths tbeg
+         org-table-last-column-widths
          buffer loc)
       (setq form (org-table-convert-refs-to-rc form))
-      (save-excursion
-       (save-restriction
-         (widen)
-         (save-excursion
-           (goto-char (point-min))
-           (if (re-search-forward
-                (concat "^[ \t]*#\\+\\(tbl\\)?name:[ \t]*"
-                        (regexp-quote name-or-id) "[ \t]*$")
-                nil t)
-               (setq buffer (current-buffer) loc (match-beginning 0))
-             (setq id-loc (org-id-find name-or-id 'marker))
-             (unless (and id-loc (markerp id-loc))
-               (user-error "Can't find remote table \"%s\"" name-or-id))
-             (setq buffer (marker-buffer id-loc)
-                   loc (marker-position id-loc))
-             (move-marker id-loc nil)))
-         (with-current-buffer buffer
-           (save-excursion
-             (save-restriction
-               (widen)
-               (goto-char loc)
-               (forward-char 1)
-               (unless (and (re-search-forward "^\\(\\*+ \\)\\|[ \t]*|" nil t)
-                            (not (match-beginning 1)))
-                 (user-error "Cannot find a table at NAME or ID %s" 
name-or-id))
-               (setq tbeg (point-at-bol))
-               (org-table-get-specials)
-               (setq form (org-table-formula-substitute-names
-                           (org-table-formula-handle-first/last-rc form)))
-               (if (and (string-match org-table-range-regexp form)
-                        (> (length (match-string 0 form)) 1))
-                   (save-match-data
-                     (org-table-get-range (match-string 0 form) tbeg 1))
-                 form)))))))))
+      (org-with-wide-buffer
+       (goto-char (point-min))
+       (if (re-search-forward
+           (concat "^[ \t]*#\\+\\(tbl\\)?name:[ \t]*"
+                   (regexp-quote name-or-id) "[ \t]*$")
+           nil t)
+          (setq buffer (current-buffer) loc (match-beginning 0))
+        (setq id-loc (org-id-find name-or-id 'marker))
+        (unless (and id-loc (markerp id-loc))
+          (user-error "Can't find remote table \"%s\"" name-or-id))
+        (setq buffer (marker-buffer id-loc)
+              loc (marker-position id-loc))
+        (move-marker id-loc nil))
+       (with-current-buffer buffer
+        (org-with-wide-buffer
+         (goto-char loc)
+         (forward-char 1)
+         (unless (and (re-search-forward "^\\(\\*+ \\)\\|^[ \t]*|" nil t)
+                      (not (match-beginning 1)))
+           (user-error "Cannot find a table at NAME or ID %s" name-or-id))
+         (org-table-analyze)
+         (setq form (org-table-formula-substitute-names
+                     (org-table-formula-handle-first/last-rc form)))
+         (if (and (string-match org-table-range-regexp form)
+                  (> (length (match-string 0 form)) 1))
+             (org-table-get-range
+              (match-string 0 form) org-table-current-begin-pos 1)
+           form)))))))
+
+(defun org-table-remote-reference-indirection (form)
+  "Return formula with table remote references substituted by indirection.
+For example \"remote($1, @>$2)\" => \"remote(year_2013, @>$1)\".
+This indirection works only with the format @ROW$COLUMN.  The
+format \"B3\" is not supported because it can not be
+distinguished from a plain table name or ID."
+  (let ((regexp
+        ;; Same as in `org-table-eval-formula'.
+        (concat "\\<remote([ \t]*\\("
+                ;; Allow "$1", "@<", "$-1", "@<<$1" etc.
+                "address@hidden \t,]+"
+                "\\)[ \t]*,[ \t]*\\([^\n)]+\\))")))
+    (replace-regexp-in-string
+     regexp
+     (lambda (m)
+       (save-match-data
+        (let ((eq (org-table-formula-handle-first/last-rc (match-string 1 m))))
+          (org-table-get-range
+           (if (string-match-p "\\`\\$[0-9]+\\'" eq)
+               (concat "@0" eq)
+             eq)))))
+     form t t 1)))
 
 (defmacro org-define-lookup-function (mode)
   (let ((mode-str (symbol-name mode))
-       (first-p (equal mode 'first))
-       (all-p (equal mode 'all)))
+       (first-p (eq mode 'first))
+       (all-p (eq mode 'all)))
     (let ((plural-str (if all-p "s" "")))
       `(defun ,(intern (format "org-lookup-%s" mode-str)) (val s-list r-list 
&optional predicate)
         ,(format "Find %s occurrence%s of VAL in S-LIST; return corresponding 
element%s of R-LIST.
@@ -5012,16 +5483,13 @@ This function is generated by a call to the macro 
`org-define-lookup-function'."
                              (sl s-list)
                              (rl (or r-list s-list))
                              (ret nil))))
-                (if first-p (add-to-list 'lvars '(match-p nil)))
-                lvars)
+                (if first-p (cons '(match-p nil) lvars) lvars))
           (while ,(if first-p '(and (not match-p) sl) 'sl)
-            (progn
-              (if (funcall p val (car sl))
-                  (progn
-                    ,(if first-p '(setq match-p t))
-                    (let ((rval (car rl)))
-                      (setq ret ,(if all-p '(append ret (list rval)) 'rval)))))
-              (setq sl (cdr sl) rl (cdr rl))))
+            (when (funcall p val (car sl))
+              ,(when first-p '(setq match-p t))
+              (let ((rval (car rl)))
+                (setq ret ,(if all-p '(append ret (list rval)) 'rval))))
+            (setq sl (cdr sl) rl (cdr rl)))
           ret)))))
 
 (org-define-lookup-function first)
diff --git a/lisp/org/org-timer.el b/lisp/org/org-timer.el
index 9573747..146775b 100644
--- a/lisp/org/org-timer.el
+++ b/lisp/org/org-timer.el
@@ -1,4 +1,4 @@
-;;; org-timer.el --- The relative timer code for Org-mode
+;;; org-timer.el --- Timer code for Org mode         -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 
@@ -24,13 +24,20 @@
 ;;
 ;;; Commentary:
 
-;; This file contains the relative timer code for Org-mode
+;; This file implements two types of timers for Org buffers:
+;;
+;; - A relative timer that counts up (from 0 or a specified offset)
+;; - A countdown timer that counts down from a specified time
+;;
+;; The relative and countdown timers differ in their entry points.
+;; Use `org-timer' or `org-timer-start' to start the relative timer,
+;; and `org-timer-set-timer' to start the countdown timer.
 
 ;;; Code:
 
-(require 'org)
+(require 'cl-lib)
+(require 'org-clock)
 
-(declare-function org-notify "org-clock" (notification &optional play-sound))
 (declare-function org-agenda-error "org-agenda" ())
 
 (defvar org-timer-start-time nil
@@ -39,27 +46,37 @@
 (defvar org-timer-pause-time nil
   "Time when the timer was paused.")
 
+(defvar org-timer-countdown-timer nil
+  "Current countdown timer.
+This is a timer object if there is an active countdown timer,
+`paused' if there is a paused countdown timer, and nil
+otherwise.")
+
+(defvar org-timer-countdown-timer-title nil
+  "Title for notification displayed when a countdown finishes.")
+
 (defconst org-timer-re 
"\\([-+]?[0-9]+\\):\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)"
   "Regular expression used to match timer stamps.")
 
 (defcustom org-timer-format "%s "
   "The format to insert the time of the timer.
 This format must contain one instance of \"%s\" which will be replaced by
-the value of the relative timer."
+the value of the timer."
   :group 'org-time
   :type 'string)
 
-(defcustom org-timer-default-timer 0
-  "The default timer when a timer is set.
+(defcustom org-timer-default-timer "0"
+  "The default timer when a timer is set, in minutes or hh:mm:ss format.
 When 0, the user is prompted for a value."
   :group 'org-time
-  :version "24.1"
-  :type 'number)
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'string)
 
 (defcustom org-timer-display 'mode-line
-  "When a timer is running, org-mode can display it in the mode
-line and/or frame title.
-Allowed values are:
+  "Define where running timer is displayed, if at all.
+When a timer is running, Org can display it in the mode line
+and/or frame title.  Allowed values are:
 
 both         displays in both mode line and frame title
 mode-line    displays only in mode line (default)
@@ -76,13 +93,13 @@ nil          current timer is not displayed"
   "Hook run after relative timer is started.")
 
 (defvar org-timer-stop-hook nil
-  "Hook run before relative timer is stopped.")
+  "Hook run before relative or countdown timer is stopped.")
 
 (defvar org-timer-pause-hook nil
-  "Hook run before relative timer is paused.")
+  "Hook run before relative or countdown timer is paused.")
 
 (defvar org-timer-continue-hook nil
-  "Hook run after relative timer is continued.")
+  "Hook run after relative or countdown timer is continued.")
 
 (defvar org-timer-set-hook nil
   "Hook run after countdown timer is set.")
@@ -90,9 +107,6 @@ nil          current timer is not displayed"
 (defvar org-timer-done-hook nil
   "Hook run after countdown timer reaches zero.")
 
-(defvar org-timer-cancel-hook nil
-  "Hook run before countdown timer is canceled.")
-
 ;;;###autoload
 (defun org-timer-start (&optional offset)
   "Set the starting time for the relative timer to now.
@@ -105,8 +119,12 @@ region will be shifted by a specific amount.  You will be 
prompted for
 the amount, with the default to make the first timer string in
 the region 0:00:00."
   (interactive "P")
-  (if (equal offset '(16))
-      (call-interactively 'org-timer-change-times-in-region)
+  (cond
+   ((equal offset '(16))
+    (call-interactively 'org-timer-change-times-in-region))
+   (org-timer-countdown-timer
+    (user-error "Countdown timer is running.  Cancel first"))
+   (t
     (let (delta def s)
       (if (not offset)
          (setq org-timer-start-time (current-time))
@@ -123,67 +141,90 @@ the region 0:00:00."
          (setq delta (org-timer-hms-to-secs (org-timer-fix-incomplete s)))))
        (setq org-timer-start-time
              (seconds-to-time
-              (- (float-time) delta))))
+              ;; Pass `current-time' result to `float-time' (instead
+              ;; of calling without arguments) so that only
+              ;; `current-time' has to be overriden in tests.
+              (- (float-time (current-time)) delta))))
+      (setq org-timer-pause-time nil)
       (org-timer-set-mode-line 'on)
       (message "Timer start time set to %s, current value is %s"
               (format-time-string "%T" org-timer-start-time)
               (org-timer-secs-to-hms (or delta 0)))
-      (run-hooks 'org-timer-start-hook))))
+      (run-hooks 'org-timer-start-hook)))))
 
 (defun org-timer-pause-or-continue (&optional stop)
-  "Pause or continue the relative timer.
+  "Pause or continue the relative or countdown timer.
 With prefix arg STOP, stop it entirely."
   (interactive "P")
   (cond
    (stop (org-timer-stop))
    ((not org-timer-start-time) (error "No timer is running"))
    (org-timer-pause-time
-    ;; timer is paused, continue
-    (setq org-timer-start-time
-         (seconds-to-time
-          (-
-           (float-time)
-           (- (float-time org-timer-pause-time)
-              (float-time org-timer-start-time))))
-         org-timer-pause-time nil)
-    (org-timer-set-mode-line 'on)
-    (run-hooks 'org-timer-continue-hook)
-    (message "Timer continues at %s" (org-timer-value-string)))
+    (let ((start-secs (float-time org-timer-start-time))
+         (pause-secs (float-time org-timer-pause-time)))
+      (if org-timer-countdown-timer
+         (let ((new-secs (- start-secs pause-secs)))
+           (setq org-timer-countdown-timer
+                 (org-timer--run-countdown-timer
+                  new-secs org-timer-countdown-timer-title))
+           (setq org-timer-start-time
+                 (time-add (current-time) (seconds-to-time new-secs))))
+       (setq org-timer-start-time
+             ;; Pass `current-time' result to `float-time' (instead
+             ;; of calling without arguments) so that only
+             ;; `current-time' has to be overriden in tests.
+             (seconds-to-time (- (float-time (current-time))
+                                 (- pause-secs start-secs)))))
+      (setq org-timer-pause-time nil)
+      (org-timer-set-mode-line 'on)
+      (run-hooks 'org-timer-continue-hook)
+      (message "Timer continues at %s" (org-timer-value-string))))
    (t
     ;; pause timer
+    (when org-timer-countdown-timer
+      (cancel-timer org-timer-countdown-timer)
+      (setq org-timer-countdown-timer 'paused))
     (run-hooks 'org-timer-pause-hook)
     (setq org-timer-pause-time (current-time))
-    (org-timer-set-mode-line 'pause)
+    (org-timer-set-mode-line 'paused)
     (message "Timer paused at %s" (org-timer-value-string)))))
 
-(defvar org-timer-current-timer nil)
 (defun org-timer-stop ()
-  "Stop the relative timer."
+  "Stop the relative or countdown timer."
   (interactive)
+  (unless org-timer-start-time
+    (user-error "No timer running"))
+  (when (timerp org-timer-countdown-timer)
+    (cancel-timer org-timer-countdown-timer))
   (run-hooks 'org-timer-stop-hook)
   (setq org-timer-start-time nil
        org-timer-pause-time nil
-       org-timer-current-timer nil)
+       org-timer-countdown-timer nil)
   (org-timer-set-mode-line 'off)
   (message "Timer stopped"))
 
 ;;;###autoload
-(defun org-timer (&optional restart no-insert-p)
+(defun org-timer (&optional restart no-insert)
   "Insert a H:MM:SS string from the timer into the buffer.
-The first time this command is used, the timer is started.  When used with
-a \\[universal-argument] prefix, force restarting the timer.
-When used with a double prefix argument \\[universal-argument], change all the 
timer string
-in the region by a fixed amount.  This can be used to recalibrate a timer
-that was not started at the correct moment.
+The first time this command is used, the timer is started.
+
+When used with a `\\[universal-argument]' prefix, force restarting the timer.
+
+When used with a `\\[universal-argument] \\[universal-argument]' \
+prefix, change all the timer strings
+in the region by a fixed amount.  This can be used to re-calibrate
+a timer that was not started at the correct moment.
 
-If NO-INSERT-P is non-nil, return the string instead of inserting
+If NO-INSERT is non-nil, return the string instead of inserting
 it in the buffer."
   (interactive "P")
-  (when (or (equal restart '(4)) (not org-timer-start-time))
-    (org-timer-start))
-  (if no-insert-p
-      (org-timer-value-string)
-    (insert (org-timer-value-string))))
+  (if (equal restart '(16))
+      (org-timer-start restart)
+    (when (or (equal restart '(4)) (not org-timer-start-time))
+      (org-timer-start))
+    (if no-insert
+       (org-timer-value-string)
+      (insert (org-timer-value-string)))))
 
 (defun org-timer-value-string ()
   "Set the timer string."
@@ -191,12 +232,14 @@ it in the buffer."
          (org-timer-secs-to-hms
           (abs (floor (org-timer-seconds))))))
 
-(defvar org-timer-timer-is-countdown nil)
 (defun org-timer-seconds ()
-  (if org-timer-timer-is-countdown
+  ;; Pass `current-time' result to `float-time' (instead of calling
+  ;; without arguments) so that only `current-time' has to be
+  ;; overriden in tests.
+  (if org-timer-countdown-timer
       (- (float-time org-timer-start-time)
-        (float-time))
-    (- (float-time org-timer-pause-time)
+        (float-time (or org-timer-pause-time (current-time))))
+    (- (float-time (or org-timer-pause-time (current-time)))
        (float-time org-timer-start-time))))
 
 ;;;###autoload
@@ -290,8 +333,8 @@ If the integer is negative, the string will start with 
\"-\"."
 (defvar org-timer-mode-line-string nil)
 
 (defun org-timer-set-mode-line (value)
-  "Set the mode-line display of the relative timer.
-VALUE can be `on', `off', or `pause'."
+  "Set the mode-line display for relative or countdown timer.
+VALUE can be `on', `off', or `paused'."
   (when (or (eq org-timer-display 'mode-line)
            (eq org-timer-display 'both))
     (or global-mode-string (setq global-mode-string '("")))
@@ -303,43 +346,43 @@ VALUE can be `on', `off', or `pause'."
     (or (memq 'org-timer-mode-line-string frame-title-format)
        (setq frame-title-format
              (append frame-title-format '(org-timer-mode-line-string)))))
-  (cond
-   ((equal value 'off)
-    (when org-timer-mode-line-timer
-      (cancel-timer org-timer-mode-line-timer)
-      (setq org-timer-mode-line-timer nil))
-    (when (or (eq org-timer-display 'mode-line)
-             (eq org-timer-display 'both))
-      (setq global-mode-string
-           (delq 'org-timer-mode-line-string global-mode-string)))
-    (when (or (eq org-timer-display 'frame-title)
-             (eq org-timer-display 'both))
-      (setq frame-title-format
-           (delq 'org-timer-mode-line-string frame-title-format)))
-    (force-mode-line-update))
-   ((equal value 'pause)
-    (when org-timer-mode-line-timer
-      (cancel-timer org-timer-mode-line-timer)
-      (setq org-timer-mode-line-timer nil)))
-   ((equal value 'on)
-    (when (or (eq org-timer-display 'mode-line)
-             (eq org-timer-display 'both))
-      (or global-mode-string (setq global-mode-string '("")))
-      (or (memq 'org-timer-mode-line-string global-mode-string)
-         (setq global-mode-string
-               (append global-mode-string '(org-timer-mode-line-string)))))
-    (when (or (eq org-timer-display 'frame-title)
-             (eq org-timer-display 'both))
-      (or (memq 'org-timer-mode-line-string frame-title-format)
-         (setq frame-title-format
-               (append frame-title-format '(org-timer-mode-line-string)))))
-    (org-timer-update-mode-line)
-    (when org-timer-mode-line-timer
-      (cancel-timer org-timer-mode-line-timer)
-      (setq org-timer-mode-line-timer nil))
-    (when org-timer-display
-      (setq org-timer-mode-line-timer
-           (run-with-timer 1 1 'org-timer-update-mode-line))))))
+  (cl-case value
+    (off
+     (when org-timer-mode-line-timer
+       (cancel-timer org-timer-mode-line-timer)
+       (setq org-timer-mode-line-timer nil))
+     (when (or (eq org-timer-display 'mode-line)
+              (eq org-timer-display 'both))
+       (setq global-mode-string
+            (delq 'org-timer-mode-line-string global-mode-string)))
+     (when (or (eq org-timer-display 'frame-title)
+              (eq org-timer-display 'both))
+       (setq frame-title-format
+            (delq 'org-timer-mode-line-string frame-title-format)))
+     (force-mode-line-update))
+    (paused
+     (when org-timer-mode-line-timer
+       (cancel-timer org-timer-mode-line-timer)
+       (setq org-timer-mode-line-timer nil)))
+    (on
+     (when (or (eq org-timer-display 'mode-line)
+              (eq org-timer-display 'both))
+       (or global-mode-string (setq global-mode-string '("")))
+       (or (memq 'org-timer-mode-line-string global-mode-string)
+          (setq global-mode-string
+                (append global-mode-string '(org-timer-mode-line-string)))))
+     (when (or (eq org-timer-display 'frame-title)
+              (eq org-timer-display 'both))
+       (or (memq 'org-timer-mode-line-string frame-title-format)
+          (setq frame-title-format
+                (append frame-title-format '(org-timer-mode-line-string)))))
+     (org-timer-update-mode-line)
+     (when org-timer-mode-line-timer
+       (cancel-timer org-timer-mode-line-timer)
+       (setq org-timer-mode-line-timer nil))
+     (when org-timer-display
+       (setq org-timer-mode-line-timer
+            (run-with-timer 1 1 'org-timer-update-mode-line))))))
 
 (defun org-timer-update-mode-line ()
   "Update the timer time in the mode line."
@@ -349,102 +392,113 @@ VALUE can be `on', `off', or `pause'."
          (concat " <" (substring (org-timer-value-string) 0 -1) ">"))
     (force-mode-line-update)))
 
-(defun org-timer-cancel-timer ()
-  "Cancel the current timer."
-  (interactive)
-  (when (eval org-timer-current-timer)
-    (run-hooks 'org-timer-cancel-hook)
-    (cancel-timer org-timer-current-timer)
-    (setq org-timer-current-timer nil)
-    (setq org-timer-timer-is-countdown nil)
-    (org-timer-set-mode-line 'off))
-  (message "Last timer canceled"))
-
 (defun org-timer-show-remaining-time ()
   "Display the remaining time before the timer ends."
   (interactive)
   (require 'time)
-  (if (not org-timer-current-timer)
+  (if (not org-timer-countdown-timer)
       (message "No timer set")
     (let* ((rtime (decode-time
-                  (time-subtract (timer--time org-timer-current-timer)
+                  (time-subtract (timer--time org-timer-countdown-timer)
                                  (current-time))))
           (rsecs (nth 0 rtime))
           (rmins (nth 1 rtime)))
       (message "%d minute(s) %d seconds left before next time out"
               rmins rsecs))))
 
-(defvar org-clock-sound)
-
 ;;;###autoload
 (defun org-timer-set-timer (&optional opt)
-  "Prompt for a duration and set a timer.
+  "Prompt for a duration in minutes or hh:mm:ss and set a timer.
 
-If `org-timer-default-timer' is not zero, suggest this value as
+If `org-timer-default-timer' is not \"0\", suggest this value as
 the default duration for the timer.  If a timer is already set,
 prompt the user if she wants to replace it.
 
 Called with a numeric prefix argument, use this numeric value as
-the duration of the timer.
+the duration of the timer in minutes.
 
 Called with a `C-u' prefix arguments, use `org-timer-default-timer'
 without prompting the user for a duration.
 
 With two `C-u' prefix arguments, use `org-timer-default-timer'
 without prompting the user for a duration and automatically
-replace any running timer."
+replace any running timer.
+
+By default, the timer duration will be set to the number of
+minutes in the Effort property, if any.  You can ignore this by
+using three `C-u' prefix arguments."
   (interactive "P")
-  (let ((minutes (or (and (numberp opt) (number-to-string opt))
-                    (and (listp opt) (not (null opt))
-                         (number-to-string org-timer-default-timer))
-                    (read-from-minibuffer
-                     "How many minutes left? "
-                     (if (not (eq org-timer-default-timer 0))
-                         (number-to-string org-timer-default-timer))))))
+  (when (and org-timer-start-time
+            (not org-timer-countdown-timer))
+    (user-error "Relative timer is running.  Stop first"))
+  (let* ((default-timer
+          ;; `org-timer-default-timer' used to be a number, don't choke:
+          (if (numberp org-timer-default-timer)
+              (number-to-string org-timer-default-timer)
+            org-timer-default-timer))
+        (effort-minutes (ignore-errors (org-get-at-eol 'effort-minutes 1)))
+        (minutes (or (and (numberp opt) (number-to-string opt))
+                     (and (not (equal opt '(64)))
+                          effort-minutes
+                          (number-to-string effort-minutes))
+                     (and (consp opt) default-timer)
+                     (and (stringp opt) opt)
+                     (read-from-minibuffer
+                      "How much time left? (minutes or h:mm:ss) "
+                      (and (not (string-equal default-timer "0")) 
default-timer)))))
+    (when (string-match "\\`[0-9]+\\'" minutes)
+      (setq minutes (concat minutes ":00")))
     (if (not (string-match "[0-9]+" minutes))
        (org-timer-show-remaining-time)
-      (let* ((mins (string-to-number (match-string 0 minutes)))
-            (secs (* mins 60))
-            (hl (cond
-                 ((string-match "Org Agenda" (buffer-name))
-                  (let* ((marker (or (get-text-property (point) 'org-marker)
-                                     (org-agenda-error)))
-                         (hdmarker (or (get-text-property (point) 
'org-hd-marker)
-                                       marker))
-                         (pos (marker-position marker)))
-                    (with-current-buffer (marker-buffer marker)
-                      (widen)
-                      (goto-char pos)
-                      (org-show-entry)
-                      (or (ignore-errors (org-get-heading))
-                          (concat "File:" (file-name-nondirectory 
(buffer-file-name)))))))
-                 ((derived-mode-p 'org-mode)
-                  (or (ignore-errors (org-get-heading))
-                      (concat "File:" (file-name-nondirectory 
(buffer-file-name)))))
-                 (t (error "Not in an Org buffer"))))
-            timer-set)
-       (if (or (and org-timer-current-timer
-                    (or (equal opt '(16))
-                        (y-or-n-p "Replace current timer? ")))
-               (not org-timer-current-timer))
-           (progn
-             (require 'org-clock)
-             (when org-timer-current-timer
-               (cancel-timer org-timer-current-timer))
-             (setq org-timer-current-timer
-                   (run-with-timer
-                    secs nil `(lambda ()
-                                (setq org-timer-current-timer nil)
-                                (org-notify ,(format "%s: time out" hl) 
,org-clock-sound)
-                                (setq org-timer-timer-is-countdown nil)
-                                (org-timer-set-mode-line 'off)
-                                (run-hooks 'org-timer-done-hook))))
-             (run-hooks 'org-timer-set-hook)
-             (setq org-timer-timer-is-countdown t
-                   org-timer-start-time
-                   (time-add (current-time) (seconds-to-time (* mins 60))))
-             (org-timer-set-mode-line 'on))
-         (message "No timer set"))))))
+      (let ((secs (org-timer-hms-to-secs (org-timer-fix-incomplete minutes))))
+       (if (and org-timer-countdown-timer
+                (not (or (equal opt '(16))
+                         (y-or-n-p "Replace current timer? "))))
+           (message "No timer set")
+         (when (timerp org-timer-countdown-timer)
+           (cancel-timer org-timer-countdown-timer))
+         (setq org-timer-countdown-timer-title
+               (org-timer--get-timer-title))
+         (setq org-timer-countdown-timer
+               (org-timer--run-countdown-timer
+                secs org-timer-countdown-timer-title))
+         (run-hooks 'org-timer-set-hook)
+         (setq org-timer-start-time
+               (time-add (current-time) (seconds-to-time secs)))
+         (setq org-timer-pause-time nil)
+         (org-timer-set-mode-line 'on))))))
+
+(defun org-timer--run-countdown-timer (secs title)
+  "Start countdown timer that will last SECS.
+TITLE will be appended to the notification message displayed when
+time is up."
+  (let ((msg (format "%s: time out" title)))
+    (run-with-timer
+     secs nil `(lambda ()
+                (setq org-timer-countdown-timer nil
+                      org-timer-start-time nil)
+                (org-notify ,msg ,org-clock-sound)
+                (org-timer-set-mode-line 'off)
+                (run-hooks 'org-timer-done-hook)))))
+
+(defun org-timer--get-timer-title ()
+  "Construct timer title from heading or file name of Org buffer."
+  (cond
+   ((derived-mode-p 'org-agenda-mode)
+    (let* ((marker (or (get-text-property (point) 'org-marker)
+                      (org-agenda-error)))
+          (hdmarker (or (get-text-property (point) 'org-hd-marker)
+                        marker)))
+      (with-current-buffer (marker-buffer marker)
+       (org-with-wide-buffer
+        (goto-char hdmarker)
+        (org-show-entry)
+        (or (ignore-errors (org-get-heading))
+            (buffer-name (buffer-base-buffer)))))))
+   ((derived-mode-p 'org-mode)
+    (or (ignore-errors (org-get-heading))
+       (buffer-name (buffer-base-buffer))))
+   (t (error "Not in an Org buffer"))))
 
 (provide 'org-timer)
 
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index aae65cc..2db3eae 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -3,15 +3,15 @@
 ;;; Code:
 ;;;###autoload
 (defun org-release ()
-  "The release version of org-mode.
-  Inserted by installing org-mode or when a release is made."
-   (let ((org-release "8.2.10"))
+  "The release version of Org.
+Inserted by installing Org mode or when a release is made."
+   (let ((org-release "9.0.9"))
      org-release))
 ;;;###autoload
 (defun org-git-version ()
   "The Git version of org-mode.
-  Inserted by installing org-mode or when a release is made."
-   (let ((org-git-version "release_8.2.10"))
+Inserted by installing Org or when a release is made."
+   (let ((org-git-version "release_9.0.9"))
      org-git-version))
 
 (provide 'org-version)
diff --git a/lisp/org/org-w3m.el b/lisp/org/org-w3m.el
index 8360bd0..e9bbeff 100644
--- a/lisp/org/org-w3m.el
+++ b/lisp/org/org-w3m.el
@@ -1,4 +1,4 @@
-;;; org-w3m.el --- Support from copy and paste from w3m to Org-mode
+;;; org-w3m.el --- Support from Copy and Paste From w3m -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
 
@@ -25,9 +25,9 @@
 ;;; Commentary:
 
 ;; This file implements copying HTML content from a w3m buffer and
-;; transforming the text on the fly so that it can be pasted into
-;; an org-mode buffer with hot links.  It will also work for regions
-;; in gnus buffers that have been washed with w3m.
+;; transforming the text on the fly so that it can be pasted into an
+;; Org buffer with hot links.  It will also work for regions in gnus
+;; buffers that have been washed with w3m.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -35,7 +35,7 @@
 
 ;; Richard Riley <rileyrgdev at googlemail dot com>
 ;;
-;;      The idea of transforming the HTML content with org-mode style is
+;;      The idea of transforming the HTML content with Org syntax is
 ;;      proposed by Richard, I'm just coding it.
 ;;
 
@@ -46,7 +46,7 @@
 (defvar w3m-current-url)
 (defvar w3m-current-title)
 
-(add-hook 'org-store-link-functions 'org-w3m-store-link)
+(org-link-set-parameters "w3m" :store #'org-w3m-store-link)
 (defun org-w3m-store-link ()
   "Store a link to a w3m buffer."
   (when (eq major-mode 'w3m-mode)
@@ -60,7 +60,7 @@
   "Copy current buffer content or active region with `org-mode' style links.
 This will encode `link-title' and `link-location' with
 `org-make-link-string', and insert the transformed test into the kill ring,
-so that it can be yanked into an Org-mode buffer with links working correctly."
+so that it can be yanked into an Org  buffer with links working correctly."
   (interactive)
   (let* ((regionp (org-region-active-p))
          (transform-start (point-min))
@@ -107,7 +107,7 @@ so that it can be yanked into an Org-mode buffer with links 
working correctly."
                 (concat return-content
                         (buffer-substring (point) transform-end))))
       (org-kill-new return-content)
-      (message "Transforming links...done, use C-y to insert text into 
Org-mode file")
+      (message "Transforming links...done, use C-y to insert text into Org 
file")
       (message "Copy with link transformation complete."))))
 
 (defun org-w3m-get-anchor-start ()
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 02a7a0c..22b7dbf 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -1,4 +1,4 @@
-;;; org.el --- Outline-based notes management and organizer
+;;; org.el --- Outline-based notes management and organizer -*- 
lexical-binding: t; -*-
 
 ;; Carstens outline-mode for keeping track of everything.
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
@@ -25,23 +25,24 @@
 ;;
 ;;; Commentary:
 ;;
-;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing
+;; Org is a mode for keeping notes, maintaining ToDo lists, and doing
 ;; project planning with a fast and effective plain-text system.
 ;;
-;; Org-mode develops organizational tasks around NOTES files that contain
-;; information about projects as plain text.  Org-mode is implemented on
-;; top of outline-mode, which makes it possible to keep the content of
-;; large files well structured.  Visibility cycling and structure editing
-;; help to work with the tree.  Tables are easily created with a built-in
-;; table editor.  Org-mode supports ToDo items, deadlines, time stamps,
-;; and scheduling.  It dynamically compiles entries into an agenda that
-;; utilizes and smoothly integrates much of the Emacs calendar and diary.
-;; Plain text URL-like links connect to websites, emails, Usenet
-;; messages, BBDB entries, and any files related to the projects.  For
-;; printing and sharing of notes, an Org-mode file can be exported as a
-;; structured ASCII file, as HTML, or (todo and agenda items only) as an
-;; iCalendar file.  It can also serve as a publishing tool for a set of
-;; linked webpages.
+;; Org mode develops organizational tasks around NOTES files that
+;; contain information about projects as plain text.  Org mode is
+;; implemented on top of outline-mode, which makes it possible to keep
+;; the content of large files well structured.  Visibility cycling and
+;; structure editing help to work with the tree.  Tables are easily
+;; created with a built-in table editor.  Org mode supports ToDo
+;; items, deadlines, time stamps, and scheduling.  It dynamically
+;; compiles entries into an agenda that utilizes and smoothly
+;; integrates much of the Emacs calendar and diary.  Plain text
+;; URL-like links connect to websites, emails, Usenet messages, BBDB
+;; entries, and any files related to the projects.  For printing and
+;; sharing of notes, an Org file can be exported as a structured ASCII
+;; file, as HTML, or (todo and agenda items only) as an iCalendar
+;; file.  It can also serve as a publishing tool for a set of linked
+;; webpages.
 ;;
 ;; Installation and Activation
 ;; ---------------------------
@@ -51,11 +52,11 @@
 ;;
 ;; Documentation
 ;; -------------
-;; The documentation of Org-mode can be found in the TeXInfo file.  The
+;; The documentation of Org mode can be found in the TeXInfo file.  The
 ;; distribution also contains a PDF version of it.  At the homepage of
-;; Org-mode, you can read the same text online as HTML.  There is also an
+;; Org mode, you can read the same text online as HTML.  There is also an
 ;; excellent reference card made by Philip Rooke.  This card can be found
-;; in the etc/ directory of Emacs 22.
+;; in the doc/ directory.
 ;;
 ;; A list of recent changes can be found at
 ;; http://orgmode.org/Changes.html
@@ -63,21 +64,29 @@
 ;;; Code:
 
 (defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
-(defvar org-table-formula-constants-local nil
+(defvar-local org-table-formula-constants-local nil
   "Local version of `org-table-formula-constants'.")
-(make-variable-buffer-local 'org-table-formula-constants-local)
 
 ;;;; Require other packages
 
-(eval-when-compile
-  (require 'cl)
-  (require 'gnus-sum))
+(require 'cl-lib)
+
+(eval-when-compile (require 'gnus-sum))
 
 (require 'calendar)
 (require 'find-func)
 (require 'format-spec)
 
-(load "org-loaddefs.el" t t t)
+(or (eq this-command 'eval-buffer)
+    (condition-case nil
+       (load (concat (file-name-directory load-file-name)
+                     "org-loaddefs.el")
+             nil t t t)
+      (error
+       (message "WARNING: No org-loaddefs.el file could be found from where 
org.el is loaded.")
+       (sit-for 3)
+       (message "You need to run \"make\" or \"make autoloads\" from Org lisp 
directory")
+       (sit-for 3))))
 
 (require 'org-macs)
 (require 'org-compat)
@@ -101,75 +110,87 @@ sure that we are at the beginning of the line.")
   "Matches a headline, putting stars and text into groups.
 Stars are put in group 1 and the trimmed body in group 2.")
 
-;; Emacs 22 calendar compatibility:  Make sure the new variables are available
-(unless (boundp 'calendar-view-holidays-initially-flag)
-  (org-defvaralias 'calendar-view-holidays-initially-flag
-    'view-calendar-holidays-initially))
-(unless (boundp 'calendar-view-diary-initially-flag)
-  (org-defvaralias 'calendar-view-diary-initially-flag
-    'view-diary-entries-initially))
-(unless (boundp 'diary-fancy-buffer)
-  (org-defvaralias 'diary-fancy-buffer 'fancy-diary-buffer))
-
+(declare-function calendar-check-holidays "holidays" (date))
+(declare-function cdlatex-environment "ext:cdlatex" (environment item))
+(declare-function isearch-no-upper-case-p "isearch" (string regexp-flag))
 (declare-function org-add-archive-files "org-archive" (files))
-
-(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
-(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
-(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ())
-(declare-function org-pop-to-buffer-same-window "org-compat" (&optional 
buffer-or-name norecord label))
+(declare-function org-agenda-entry-get-agenda-timestamp "org-agenda" (pom))
+(declare-function org-agenda-list "org-agenda" (&optional arg start-day span 
with-hour))
+(declare-function org-agenda-redo "org-agenda" (&optional all))
+(declare-function org-babel-do-in-edit-buffer "ob-core" (&rest body) t)
+(declare-function org-babel-tangle-file "ob-tangle" (file &optional 
target-file lang))
+(declare-function org-beamer-mode "ox-beamer" (&optional prefix) t)
 (declare-function org-clock-get-last-clock-out-time "org-clock" ())
-(declare-function org-clock-timestamps-up "org-clock" (&optional n))
-(declare-function org-clock-timestamps-down "org-clock" (&optional n))
+(declare-function org-clock-out "org-clock" (&optional switch-to-state 
fail-quietly at-time))
 (declare-function org-clock-remove-overlays "org-clock" (&optional beg end 
noremove))
+(declare-function org-clock-sum "org-clock" (&optional tstart tend 
headline-filter propname))
 (declare-function org-clock-sum-current-item "org-clock" (&optional tstart))
+(declare-function org-clock-timestamps-down "org-clock" (&optional n))
+(declare-function org-clock-timestamps-up "org-clock" (&optional n))
 (declare-function org-clock-update-time-maybe "org-clock" ())
 (declare-function org-clocktable-shift "org-clock" (dir n))
-
-(declare-function orgtbl-mode "org-table" (&optional arg))
-(declare-function org-clock-out "org-clock" (&optional switch-to-state 
fail-quietly at-time))
-(declare-function org-beamer-mode "ox-beamer" (&optional prefix) t)
-(declare-function org-table-edit-field "org-table" (arg))
-(declare-function org-table-justify-field-maybe "org-table" (&optional new))
-(declare-function org-table-set-constants "org-table" ())
-(declare-function org-table-calc-current-TBLFM "org-table" (&optional arg))
-(declare-function org-id-get-create "org-id" (&optional force))
+(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-cache-refresh "org-element" (pos))
+(declare-function org-element-cache-reset "org-element" (&optional all))
+(declare-function org-element-contents "org-element" (element))
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-copy "org-element" (datum))
+(declare-function org-element-interpret-data "org-element" (data))
+(declare-function org-element-lineage "org-element" (blob &optional types 
with-self))
+(declare-function org-element-link-parser "org-element" ())
+(declare-function org-element-nested-p "org-element" (elem-a elem-b))
+(declare-function org-element-parse-buffer "org-element" (&optional 
granularity visible-only))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-put-property "org-element" (element property 
value))
+(declare-function org-element-swap-A-B "org-element" (elem-a elem-b))
+(declare-function org-element-type "org-element" (element))
+(declare-function org-element-update-syntax "org-element" ())
 (declare-function org-id-find-id-file "org-id" (id))
-(declare-function org-tags-view "org-agenda" (&optional todo-only match))
-(declare-function org-agenda-list "org-agenda"
-                  (&optional arg start-day span with-hour))
-(declare-function org-agenda-redo "org-agenda" (&optional all))
+(declare-function org-id-get-create "org-id" (&optional force))
+(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
+(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
+(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ())
+(declare-function org-plot/gnuplot "org-plot" (&optional params))
 (declare-function org-table-align "org-table" ())
 (declare-function org-table-begin "org-table" (&optional table-type))
+(declare-function org-table-beginning-of-field "org-table" (&optional n))
 (declare-function org-table-blank-field "org-table" ())
+(declare-function org-table-calc-current-TBLFM "org-table" (&optional arg))
+(declare-function org-table-copy-region "org-table" (beg end &optional cut))
+(declare-function org-table-cut-region "org-table" (beg end))
+(declare-function org-table-edit-field "org-table" (arg))
 (declare-function org-table-end "org-table" (&optional table-type))
+(declare-function org-table-end-of-field "org-table" (&optional n))
 (declare-function org-table-insert-row "org-table" (&optional arg))
-(declare-function org-table-paste-rectangle "org-table" ())
+(declare-function org-table-justify-field-maybe "org-table" (&optional new))
 (declare-function org-table-maybe-eval-formula "org-table" ())
 (declare-function org-table-maybe-recalculate-line "org-table" ())
+(declare-function org-table-next-row "org-table" ())
+(declare-function org-table-paste-rectangle "org-table" ())
+(declare-function org-table-recalculate "org-table" (&optional all noalign))
+(declare-function org-table-wrap-region "org-table" (arg))
+(declare-function org-tags-view "org-agenda" (&optional todo-only match))
+(declare-function orgtbl-ascii-plot "org-table" (&optional ask))
+(declare-function orgtbl-mode "org-table" (&optional arg))
+(declare-function org-export-get-backend "ox" (name))
+(declare-function org-export-get-environment "ox" (&optional backend subtreep 
ext-plist))
+(declare-function org-latex-make-preamble "ox-latex" (info &optional template 
snippet?))
 
-(declare-function org-element--parse-objects "org-element"
-                 (beg end acc restriction))
-(declare-function org-element-at-point "org-element" (&optional keep-trail))
-(declare-function org-element-contents "org-element" (element))
-(declare-function org-element-context "org-element" (&optional element))
-(declare-function org-element-interpret-data "org-element"
-                 (data &optional parent))
-(declare-function org-element-map "org-element"
-                  (data types fun &optional
-                        info first-match no-recursion with-affiliated))
-(declare-function org-element-nested-p "org-element" (elem-a elem-b))
-(declare-function org-element-parse-buffer "org-element"
-                 (&optional granularity visible-only))
-(declare-function org-element-property "org-element" (property element))
-(declare-function org-element-put-property "org-element"
-                 (element property value))
-(declare-function org-element-swap-A-B "org-element" (elem-a elem-b))
-(declare-function org-element--parse-objects "org-element"
-                 (beg end acc restriction))
-(declare-function org-element-parse-buffer "org-element"
-                 (&optional granularity visible-only))
-(declare-function org-element-restriction "org-element" (element))
-(declare-function org-element-type "org-element" (element))
+(defsubst org-uniquify (list)
+  "Non-destructively remove duplicate elements from LIST."
+  (let ((res (copy-sequence list))) (delete-dups res)))
+
+(defsubst org-get-at-bol (property)
+  "Get text property PROPERTY at the beginning of line."
+  (get-text-property (point-at-bol) property))
+
+(defsubst org-trim (s &optional keep-lead)
+  "Remove whitespace at the beginning and the end of string S.
+When optional argument KEEP-LEAD is non-nil, removing blank lines
+at the beginning of the string does not affect leading indentation."
+  (replace-regexp-in-string
+   (if keep-lead "\\`\\([ \t]*\n\\)+" "\\`[ \t\n\r]+") ""
+   (replace-regexp-in-string "[ \t\n\r]+\\'" "" s)))
 
 ;; load languages based on value of `org-babel-load-languages'
 (defvar org-babel-load-languages)
@@ -178,28 +199,24 @@ Stars are put in group 1 and the trimmed body in group 
2.")
 (defun org-babel-do-load-languages (sym value)
   "Load the languages defined in `org-babel-load-languages'."
   (set-default sym value)
-  (mapc (lambda (pair)
-         (let ((active (cdr pair)) (lang (symbol-name (car pair))))
-           (if active
-               (progn
-                 (require (intern (concat "ob-" lang))))
-             (progn
-               (funcall 'fmakunbound
-                        (intern (concat "org-babel-execute:" lang)))
-               (funcall 'fmakunbound
-                        (intern (concat "org-babel-expand-body:" lang)))))))
-       org-babel-load-languages))
+  (dolist (pair org-babel-load-languages)
+    (let ((active (cdr pair)) (lang (symbol-name (car pair))))
+      (if active
+         (require (intern (concat "ob-" lang)))
+       (funcall 'fmakunbound
+                (intern (concat "org-babel-execute:" lang)))
+       (funcall 'fmakunbound
+                (intern (concat "org-babel-expand-body:" lang)))))))
 
 (declare-function org-babel-tangle-file "ob-tangle" (file &optional 
target-file lang))
 ;;;###autoload
 (defun org-babel-load-file (file &optional compile)
-  "Load Emacs Lisp source code blocks in the Org-mode FILE.
+  "Load Emacs Lisp source code blocks in the Org FILE.
 This function exports the source code using `org-babel-tangle'
 and then loads the resulting file using `load-file'.  With prefix
 arg (noninteractively: 2nd arg) COMPILE the tangled Emacs Lisp
 file to byte-code before it is loaded."
   (interactive "fFile to load: \nP")
-  (require 'ob-core)
   (let* ((age (lambda (file)
                (float-time
                 (time-subtract (current-time)
@@ -207,11 +224,13 @@ file to byte-code before it is loaded."
                                           (file-attributes file)))))))
         (base-name (file-name-sans-extension file))
         (exported-file (concat base-name ".el")))
-    ;; tangle if the org-mode file is newer than the elisp file
+    ;; tangle if the Org file is newer than the elisp file
     (unless (and (file-exists-p exported-file)
                 (> (funcall age file) (funcall age exported-file)))
+      ;; Tangle-file traversal returns reversed list of tangled files
+      ;; and we want to evaluate the first target.
       (setq exported-file
-           (car (org-babel-tangle-file file exported-file "emacs-lisp"))))
+           (car (last (org-babel-tangle-file file exported-file 
"emacs-lisp")))))
     (message "%s %s"
             (if compile
                 (progn (byte-compile-file exported-file 'load)
@@ -220,7 +239,7 @@ file to byte-code before it is loaded."
             exported-file)))
 
 (defcustom org-babel-load-languages '((emacs-lisp . t))
-  "Languages which can be evaluated in Org-mode buffers.
+  "Languages which can be evaluated in Org buffers.
 This list can be used to load support for any of the languages
 below, note that each language will depend on a different set of
 system executables and/or Emacs modes.  When a language is
@@ -246,10 +265,12 @@ requirements) is loaded."
                 (const :tag "Ditaa" ditaa)
                 (const :tag "Dot" dot)
                 (const :tag "Emacs Lisp" emacs-lisp)
+                (const :tag "Forth" forth)
                 (const :tag "Fortran" fortran)
                 (const :tag "Gnuplot" gnuplot)
                 (const :tag "Haskell" haskell)
                 (const :tag "IO" io)
+                (const :tag "J" J)
                 (const :tag "Java" java)
                 (const :tag "Javascript" js)
                 (const :tag "LaTeX" latex)
@@ -272,10 +293,12 @@ requirements) is loaded."
                 (const :tag "Scala" scala)
                 (const :tag "Scheme" scheme)
                 (const :tag "Screen" screen)
-                (const :tag "Shell Script" sh)
+                (const :tag "Shell Script" shell)
                 (const :tag "Shen" shen)
                 (const :tag "Sql" sql)
-                (const :tag "Sqlite" sqlite))
+                (const :tag "Sqlite" sqlite)
+                (const :tag "Stan" stan)
+                (const :tag "ebnf2ps" ebnf2ps))
                :value-type (boolean :tag "Activate" :value t)))
 
 ;;;; Customization variables
@@ -293,41 +316,318 @@ identifier."
 
 ;;;###autoload
 (defun org-version (&optional here full message)
-  "Show the org-mode version in the echo area.
-With prefix argument HERE, insert it at point.
-When FULL is non-nil, use a verbose version string.
-When MESSAGE is non-nil, display a message with the version."
-  (interactive "P")
-  (let* ((org-dir         (ignore-errors (org-find-library-dir "org")))
-        (save-load-suffixes (when (boundp 'load-suffixes) load-suffixes))
-        (load-suffixes (list ".el"))
-        (org-install-dir (ignore-errors (org-find-library-dir "org-loaddefs")))
-        (org-trash       (or
-                          (and (fboundp 'org-release) (fboundp 
'org-git-version))
-                          (org-load-noerror-mustsuffix (concat org-dir 
"org-version"))))
-        (load-suffixes save-load-suffixes)
-        (org-version (org-release))
-        (git-version (org-git-version))
-        (version (format "Org-mode version %s (%s @ %s)"
-                         org-version
-                         git-version
-                         (if org-install-dir
-                             (if (string= org-dir org-install-dir)
-                                 org-install-dir
-                               (concat "mixed installation! " org-install-dir 
" and " org-dir))
-                           "org-loaddefs.el can not be found!")))
-        (version1 (if full version org-version)))
-    (if (org-called-interactively-p 'interactive)
-       (if here
-           (insert version)
-         (message version))
-      (if message (message version1))
+  "Show the Org version.
+Interactively, or when MESSAGE is non-nil, show it in echo area.
+With prefix argument, or when HERE is non-nil, insert it at point.
+In non-interactive uses, a reduced version string is output unless
+FULL is given."
+  (interactive (list current-prefix-arg t (not current-prefix-arg)))
+  (let ((org-dir (ignore-errors (org-find-library-dir "org")))
+       (save-load-suffixes (when (boundp 'load-suffixes) load-suffixes))
+       (load-suffixes (list ".el"))
+       (org-install-dir
+        (ignore-errors (org-find-library-dir "org-loaddefs"))))
+    (unless (and (fboundp 'org-release) (fboundp 'org-git-version))
+      (org-load-noerror-mustsuffix (concat org-dir "org-version")))
+    (let* ((load-suffixes save-load-suffixes)
+          (release (org-release))
+          (git-version (org-git-version))
+          (version (format "Org mode version %s (%s @ %s)"
+                           release
+                           git-version
+                           (if org-install-dir
+                               (if (string= org-dir org-install-dir)
+                                   org-install-dir
+                                 (concat "mixed installation! "
+                                         org-install-dir
+                                         " and "
+                                         org-dir))
+                             "org-loaddefs.el can not be found!")))
+          (version1 (if full version release)))
+      (when here (insert version1))
+      (when message (message "%s" version1))
       version1)))
 
 (defconst org-version (org-version))
 
-;;; Compatibility constants
+
+;;; Syntax Constants
+
+;;;; Block
+
+(defconst org-block-regexp
+  "^[ \t]*#\\+begin_?\\([^ 
\n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$"
+  "Regular expression for hiding blocks.")
+
+(defconst org-dblock-start-re
+  "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
+  "Matches the start line of a dynamic block, with parameters.")
+
+(defconst org-dblock-end-re "^[ \t]*#\\+\\(?:END\\|end\\)\\([: \t\r\n]\\|$\\)"
+  "Matches the end of a dynamic block.")
+
+;;;; Clock and Planning
+
+(defconst org-clock-string "CLOCK:"
+  "String used as prefix for timestamps clocking work hours on an item.")
+
+(defvar org-closed-string "CLOSED:"
+  "String used as the prefix for timestamps logging closing a TODO entry.")
+
+(defvar org-deadline-string "DEADLINE:"
+  "String to mark deadline entries.
+\\<org-mode-map>
+A deadline is this string, followed by a time stamp.  It must be
+a word, terminated by a colon.  You can insert a schedule keyword
+and a timestamp with `\\[org-deadline]'.")
+
+(defvar org-scheduled-string "SCHEDULED:"
+  "String to mark scheduled TODO entries.
+\\<org-mode-map>
+A schedule is this string, followed by a time stamp.  It must be
+a word, terminated by a colon.  You can insert a schedule keyword
+and a timestamp with `\\[org-schedule]'.")
+
+(defconst org-ds-keyword-length
+  (+ 2
+     (apply #'max
+           (mapcar #'length
+                   (list org-deadline-string org-scheduled-string
+                         org-clock-string org-closed-string))))
+  "Maximum length of the DEADLINE and SCHEDULED keywords.")
+
+(defconst org-planning-line-re
+  (concat "^[ \t]*"
+         (regexp-opt
+          (list org-closed-string org-deadline-string org-scheduled-string)
+          t))
+  "Matches a line with planning info.
+Matched keyword is in group 1.")
+
+(defconst org-clock-line-re
+  (concat "^[ \t]*" org-clock-string)
+  "Matches a line with clock info.")
+
+(defconst org-deadline-regexp (concat "\\<" org-deadline-string)
+  "Matches the DEADLINE keyword.")
+
+(defconst org-deadline-time-regexp
+  (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
+  "Matches the DEADLINE keyword together with a time stamp.")
+
+(defconst org-deadline-time-hour-regexp
+  (concat "\\<" org-deadline-string
+         " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>")
+  "Matches the DEADLINE keyword together with a time-and-hour stamp.")
+
+(defconst org-deadline-line-regexp
+  (concat "\\<\\(" org-deadline-string "\\).*")
+  "Matches the DEADLINE keyword and the rest of the line.")
+
+(defconst org-scheduled-regexp (concat "\\<" org-scheduled-string)
+  "Matches the SCHEDULED keyword.")
+
+(defconst org-scheduled-time-regexp
+  (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
+  "Matches the SCHEDULED keyword together with a time stamp.")
+
+(defconst org-scheduled-time-hour-regexp
+  (concat "\\<" org-scheduled-string
+         " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>")
+  "Matches the SCHEDULED keyword together with a time-and-hour stamp.")
+
+(defconst org-closed-time-regexp
+  (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
+  "Matches the CLOSED keyword together with a time stamp.")
+
+(defconst org-keyword-time-regexp
+  (concat "\\<"
+         (regexp-opt
+          (list org-scheduled-string org-deadline-string org-closed-string
+                org-clock-string)
+          t)
+         " *[[<]\\([^]>]+\\)[]>]")
+  "Matches any of the 4 keywords, together with the time stamp.")
+
+(defconst org-keyword-time-not-clock-regexp
+  (concat
+   "\\<"
+   (regexp-opt
+    (list org-scheduled-string org-deadline-string org-closed-string) t)
+   " *[[<]\\([^]>]+\\)[]>]")
+  "Matches any of the 3 keywords, together with the time stamp.")
+
+(defconst org-maybe-keyword-time-regexp
+  (concat "\\(\\<"
+         (regexp-opt
+          (list org-scheduled-string org-deadline-string org-closed-string
+                org-clock-string)
+          t)
+         "\\)?"
+         " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?[]>]"
+         "\\|"
+         "<%%([^\r\n>]*>\\)")
+  "Matches a timestamp, possibly preceded by a keyword.")
+
+(defconst org-all-time-keywords
+  (mapcar (lambda (w) (substring w 0 -1))
+         (list org-scheduled-string org-deadline-string
+               org-clock-string org-closed-string))
+  "List of time keywords.")
+
+;;;; Drawer
+
+(defconst org-drawer-regexp "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"
+  "Matches first or last line of a hidden block.
+Group 1 contains drawer's name or \"END\".")
+
+(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
+  "Regular expression matching the first line of a property drawer.")
+
+(defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
+  "Regular expression matching the last line of a property drawer.")
+
+(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$"
+  "Regular expression matching the first line of a clock drawer.")
+
+(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$"
+  "Regular expression matching the last line of a clock drawer.")
+
+(defconst org-property-drawer-re
+  (concat "^[ \t]*:PROPERTIES:[ \t]*\n"
+         "\\(?:[ \t]*:\\S-+:\\(?: .*\\)?[ \t]*\n\\)*?"
+         "[ \t]*:END:[ \t]*$")
+  "Matches an entire property drawer.")
+
+(defconst org-clock-drawer-re
+  (concat "\\(" org-clock-drawer-start-re "\\)[^\000]*?\\("
+         org-clock-drawer-end-re "\\)\n?")
+  "Matches an entire clock drawer.")
+
+;;;; Headline
+
+(defconst org-heading-keyword-regexp-format
+  "^\\(\\*+\\)\\(?: +%s\\)\\(?: +\\(.*?\\)\\)?[ \t]*$"
+  "Printf format for a regexp matching a headline with some keyword.
+This regexp will match the headline of any node which has the
+exact keyword that is put into the format.  The keyword isn't in
+any group by default, but the stars and the body are.")
+
+(defconst org-heading-keyword-maybe-regexp-format
+  "^\\(\\*+\\)\\(?: +%s\\)?\\(?: +\\(.*?\\)\\)?[ \t]*$"
+  "Printf format for a regexp matching a headline, possibly with some keyword.
+This regexp can match any headline with the specified keyword, or
+without a keyword.  The keyword isn't in any group by default,
+but the stars and the body are.")
+
+(defconst org-archive-tag "ARCHIVE"
+  "The tag that marks a subtree as archived.
+An archived subtree does not open during visibility cycling, and does
+not contribute to the agenda listings.")
+
+(defconst org-comment-string "COMMENT"
+  "Entries starting with this keyword will never be exported.
+\\<org-mode-map>
+An entry can be toggled between COMMENT and normal with
+`\\[org-toggle-comment]'.")
+
+
+;;;; LaTeX Environments and Fragments
+
+(defconst org-latex-regexps
+  '(("begin" "^[ 
\t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
+    ;; ("$" "\\([ \t(]\\|^\\)\\(\\(\\([$]\\)\\([^ 
\t\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \t\n,.$]\\)\\4\\)\\)\\([ \t.,?;:'\")]\\|$\\)" 
2 nil)
+    ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
+    ("$1" "\\([^$]\\|^\\)\\(\\$[^ 
\t\r\n,;.$]\\$\\)\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|\000\\|'\\|$\\)" 2 nil)
+    ("$"  "\\([^$]\\|^\\)\\(\\(\\$\\([^ 
\t\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ 
\t\n,.$]\\)\\$\\)\\)\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|\000\\|'\\|$\\)" 2 
nil)
+    ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
+    ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 nil)
+    ("$$" "\\$\\$[^\000]*?\\$\\$" 0 nil))
+  "Regular expressions for matching embedded LaTeX.")
+
+;;;; Node Property
+
+(defconst org-effort-property "Effort"
+  "The property that is being used to keep track of effort estimates.
+Effort estimates given in this property need to have the format H:MM.")
+
+;;;; Table
+
+(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
+  "Detect an org-type or table-type table.")
+
+(defconst org-table-line-regexp "^[ \t]*|"
+  "Detect an org-type table line.")
+
+(defconst org-table-dataline-regexp "^[ \t]*|[^-]"
+  "Detect an org-type table line.")
+
+(defconst org-table-hline-regexp "^[ \t]*|-"
+  "Detect an org-type table hline.")
+
+(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
+  "Detect a table-type table hline.")
+
+(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
+  "Detect the first line outside a table when searching from within it.
+This works for both table types.")
+
+(defconst org-TBLFM-regexp "^[ \t]*#\\+TBLFM: "
+  "Detect a #+TBLFM line.")
+
+;;;; Timestamp
+
+(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^\r\n>]*?\\)>"
+  "Regular expression for fast time stamp matching.")
+
+(defconst org-ts-regexp-inactive
+  "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]"
+  "Regular expression for fast inactive time stamp matching.")
+
+(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^]\r\n>]*?\\)[]>]"
+  "Regular expression for fast time stamp matching.")
+
+(defconst org-ts-regexp0
+  "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\( 
+[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
+  "Regular expression matching time strings for analysis.
+This one does not require the space after the date, so it can be used
+on a string that terminates immediately after the date.")
+
+(defconst org-ts-regexp1 
"\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]+0-9>\r\n 
-]*\\)\\( \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
+  "Regular expression matching time strings for analysis.")
+
+(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>")
+  "Regular expression matching time stamps, with groups.")
+
+(defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]")
+  "Regular expression matching time stamps (also [..]), with groups.")
+
+(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
+  "Regular expression matching a time stamp range.")
+
+(defconst org-tr-regexp-both
+  (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
+  "Regular expression matching a time stamp range.")
+
+(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
+                                org-ts-regexp "\\)?")
+  "Regular expression matching a time stamp or time stamp range.")
+
+(defconst org-tsr-regexp-both
+  (concat org-ts-regexp-both "\\(--?-?"
+         org-ts-regexp-both "\\)?")
+  "Regular expression matching a time stamp or time stamp range.
+The time stamps may be either active or inactive.")
 
+(defconst org-repeat-re
+  "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] 
[^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)"
+  "Regular expression for specifying repeated events.
+After a match, group 1 contains the repeat expression.")
+
+(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
+  "Formats for `format-time-string' which are used for time stamps.")
+
+
 ;;; The custom variables
 
 (defgroup org nil
@@ -337,7 +637,7 @@ When MESSAGE is non-nil, display a message with the 
version."
   :group 'calendar)
 
 (defcustom org-mode-hook nil
-  "Mode hook for Org-mode, run after the mode was turned on."
+  "Mode hook for Org mode, run after the mode was turned on."
   :group 'org
   :type 'hook)
 
@@ -359,17 +659,17 @@ When MESSAGE is non-nil, display a message with the 
version."
 (defun org-load-modules-maybe (&optional force)
   "Load all extensions listed in `org-modules'."
   (when (or force (not org-modules-loaded))
-    (mapc (lambda (ext)
-           (condition-case nil (require ext)
-             (error (message "Problems while trying to load feature `%s'" 
ext))))
-         org-modules)
+    (dolist (ext org-modules)
+      (condition-case nil (require ext)
+       (error (message "Problems while trying to load feature `%s'" ext))))
     (setq org-modules-loaded t)))
 
 (defun org-set-modules (var value)
   "Set VAR to VALUE and call `org-load-modules-maybe' with the force flag."
   (set var value)
   (when (featurep 'org)
-    (org-load-modules-maybe 'force)))
+    (org-load-modules-maybe 'force)
+    (org-element-cache-reset 'all)))
 
 (defcustom org-modules '(org-w3m org-bbdb org-bibtex org-docview org-gnus 
org-info org-irc org-mhe org-rmail)
   "Modules that should always be loaded together with org.el.
@@ -397,6 +697,7 @@ For export specific modules, see also 
`org-export-backends'."
        (const :tag "   crypt:             Encryption of subtrees" org-crypt)
        (const :tag "   ctags:             Access to Emacs tags with links" 
org-ctags)
        (const :tag "   docview:           Links to doc-view buffers" 
org-docview)
+       (const :tag "   eww:               Store link to url of eww" org-eww)
        (const :tag "   gnus:              Links to GNUS folders/messages" 
org-gnus)
        (const :tag "   habit:             Track your consistency with habits" 
org-habit)
        (const :tag "   id:                Global IDs for identifying entries" 
org-id)
@@ -407,52 +708,50 @@ For export specific modules, see also 
`org-export-backends'."
        (const :tag "   mouse:             Additional mouse support" org-mouse)
        (const :tag "   protocol:          Intercept calls from emacsclient" 
org-protocol)
        (const :tag "   rmail:             Links to RMAIL folders/messages" 
org-rmail)
-       (const :tag "   w3m:               Special cut/paste from w3m to 
Org-mode." org-w3m)
+       (const :tag "   w3m:               Special cut/paste from w3m to Org 
mode." org-w3m)
 
        (const :tag "C  annotate-file:     Annotate a file with org syntax" 
org-annotate-file)
-       (const :tag "C  bookmark:          Org-mode links to bookmarks" 
org-bookmark)
+       (const :tag "C  bookmark:          Org links to bookmarks" org-bookmark)
        (const :tag "C  bullets:           Add overlays to headlines stars" 
org-bullets)
        (const :tag "C  checklist:         Extra functions for checklists in 
repeated tasks" org-checklist)
        (const :tag "C  choose:            Use TODO keywords to mark decisions 
states" org-choose)
        (const :tag "C  collector:         Collect properties into tables" 
org-collector)
-       (const :tag "C  depend:            TODO dependencies for 
Org-mode\n\t\t\t(PARTIALLY OBSOLETE, see built-in dependency support))" 
org-depend)
-       (const :tag "C  drill:             Flashcards and spaced repetition for 
Org-mode" org-drill)
-       (const :tag "C  elisp-symbol:      Org-mode links to emacs-lisp 
symbols" org-elisp-symbol)
+       (const :tag "C  depend:            TODO dependencies for Org 
mode\n\t\t\t(PARTIALLY OBSOLETE, see built-in dependency support))" org-depend)
+       (const :tag "C  drill:             Flashcards and spaced repetition for 
Org mode" org-drill)
+       (const :tag "C  elisp-symbol:      Org links to emacs-lisp symbols" 
org-elisp-symbol)
        (const :tag "C  eshell             Support for links to working 
directories in eshell" org-eshell)
        (const :tag "C  eval-light:        Evaluate inbuffer-code on demand" 
org-eval-light)
        (const :tag "C  eval:              Include command output as text" 
org-eval)
-       (const :tag "C  expiry:            Expiry mechanism for Org-mode 
entries" org-expiry)
+       (const :tag "C  expiry:            Expiry mechanism for Org entries" 
org-expiry)
        (const :tag "C  favtable:          Lookup table of favorite references 
and links" org-favtable)
        (const :tag "C  git-link:          Provide org links to specific file 
version" org-git-link)
        (const :tag "C  interactive-query: Interactive modification of tags 
query\n\t\t\t(PARTIALLY OBSOLETE, see secondary filtering)" 
org-interactive-query)
-        (const :tag "C  invoice:           Help manage client invoices in 
Org-mode" org-invoice)
-       (const :tag "C  jira:              Add a jira:ticket protocol to 
Org-mode" org-jira)
+        (const :tag "C  invoice:           Help manage client invoices in Org 
mode" org-invoice)
        (const :tag "C  learn:             SuperMemo's incremental learning 
algorithm" org-learn)
        (const :tag "C  mac-iCal           Imports events from iCal.app to the 
Emacs diary" org-mac-iCal)
        (const :tag "C  mac-link:          Grab links and url from various mac 
Applications" org-mac-link)
-       (const :tag "C  mairix:            Hook mairix search into Org-mode for 
different MUAs" org-mairix)
-       (const :tag "C  man:               Support for links to manpages in 
Org-mode" org-man)
+       (const :tag "C  mairix:            Hook mairix search into Org for 
different MUAs" org-mairix)
+       (const :tag "C  man:               Support for links to manpages in Org 
mode" org-man)
        (const :tag "C  mew:               Links to Mew folders/messages" 
org-mew)
        (const :tag "C  mtags:             Support for muse-like tags" 
org-mtags)
        (const :tag "C  notmuch:           Provide org links to notmuch 
searches or messages" org-notmuch)
        (const :tag "C  panel:             Simple routines for us with bad 
memory" org-panel)
-       (const :tag "C  registry:          A registry for Org-mode links" 
org-registry)
-       (const :tag "C  screen:            Visit screen sessions through 
Org-mode links" org-screen)
+       (const :tag "C  registry:          A registry for Org links" 
org-registry)
+       (const :tag "C  screen:            Visit screen sessions through Org 
links" org-screen)
        (const :tag "C  secretary:         Team management with org-mode" 
org-secretary)
-       (const :tag "C  sqlinsert:         Convert Org-mode tables to SQL 
insertions" orgtbl-sqlinsert)
-       (const :tag "C  toc:               Table of contents for Org-mode 
buffer" org-toc)
-       (const :tag "C  track:             Keep up with Org-mode development" 
org-track)
+       (const :tag "C  sqlinsert:         Convert Org tables to SQL 
insertions" orgtbl-sqlinsert)
+       (const :tag "C  toc:               Table of contents for Org buffer" 
org-toc)
+       (const :tag "C  track:             Keep up with Org mode development" 
org-track)
        (const :tag "C  velocity           Something like Notational Velocity 
for Org" org-velocity)
        (const :tag "C  vm:                Links to VM folders/messages" org-vm)
        (const :tag "C  wikinodes:         CamelCase wiki-like links" 
org-wikinodes)
        (const :tag "C  wl:                Links to Wanderlust 
folders/messages" org-wl)
        (repeat :tag "External packages" :inline t (symbol :tag "Package"))))
 
-(defvar org-export--registered-backends) ; From ox.el.
+(defvar org-export-registered-backends) ; From ox.el.
 (declare-function org-export-derived-backend-p "ox" (backend &rest backends))
 (declare-function org-export-backend-name "ox" (backend) t)
-(declare-function org-export-backend-options "ox" (cl-x) t)
-(defcustom org-export-backends '(ascii html icalendar latex)
+(defcustom org-export-backends '(ascii html icalendar latex odt)
   "List of export back-ends that should be always available.
 
 If a description starts with <C>, the file is not part of Emacs
@@ -469,8 +768,8 @@ interface or run the following code, where VAL stands for 
the new
 value of the variable, after updating it:
 
   (progn
-    (setq org-export--registered-backends
-          (org-remove-if-not
+    (setq org-export-registered-backends
+          (cl-remove-if-not
            (lambda (backend)
              (let ((name (org-export-backend-name backend)))
                (or (memq name val)
@@ -478,9 +777,9 @@ value of the variable, after updating it:
                      (dolist (b val)
                        (and (org-export-derived-backend-p b name)
                             (throw \\='parentp t)))))))
-           org-export--registered-backends))
-    (let ((new-list (mapcar \\='org-export-backend-name
-                            org-export--registered-backends)))
+           org-export-registered-backends))
+    (let ((new-list (mapcar #\\='org-export-backend-name
+                            org-export-registered-backends)))
       (dolist (backend val)
         (cond
          ((not (load (format \"ox-%s\" backend) t t))
@@ -493,16 +792,16 @@ Adding a back-end to this list will also pull the 
back-end it
 depends on, if any."
   :group 'org
   :group 'org-export
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "9.0")
   :initialize 'custom-initialize-set
   :set (lambda (var val)
         (if (not (featurep 'ox)) (set-default var val)
           ;; Any back-end not required anymore (not present in VAL and not
           ;; a parent of any back-end in the new value) is removed from the
           ;; list of registered back-ends.
-          (setq org-export--registered-backends
-                (org-remove-if-not
+          (setq org-export-registered-backends
+                (cl-remove-if-not
                  (lambda (backend)
                    (let ((name (org-export-backend-name backend)))
                      (or (memq name val)
@@ -510,11 +809,11 @@ depends on, if any."
                            (dolist (b val)
                              (and (org-export-derived-backend-p b name)
                                   (throw 'parentp t)))))))
-                 org-export--registered-backends))
+                 org-export-registered-backends))
           ;; Now build NEW-LIST of both new back-ends and required
           ;; parents.
-          (let ((new-list (mapcar 'org-export-backend-name
-                                  org-export--registered-backends)))
+          (let ((new-list (mapcar #'org-export-backend-name
+                                  org-export-registered-backends)))
             (dolist (backend val)
               (cond
                ((not (load (format "ox-%s" backend) t t))
@@ -544,19 +843,18 @@ depends on, if any."
              (const :tag "C  taskjuggler Export buffer to TaskJuggler format" 
taskjuggler)))
 
 (eval-after-load 'ox
-  '(mapc
-    (lambda (backend)
-      (condition-case nil (require (intern (format "ox-%s" backend)))
-       (error (message "Problems while trying to load export back-end `%s'"
-                       backend))))
-    org-export-backends))
+  '(dolist (backend org-export-backends)
+     (condition-case nil (require (intern (format "ox-%s" backend)))
+       (error (message "Problems while trying to load export back-end `%s'"
+                      backend)))))
 
 (defcustom org-support-shift-select nil
   "Non-nil means make shift-cursor commands select text when possible.
+\\<org-mode-map>\
 
 In Emacs 23, when `shift-select-mode' is on, shifted cursor keys
 start selecting a region, or enlarge regions started in this way.
-In Org-mode, in special contexts, these same keys are used for
+In Org mode, in special contexts, these same keys are used for
 other purposes, important enough to compete with shift selection.
 Org tries to balance these needs by supporting `shift-select-mode'
 outside these special contexts, under control of this variable.
@@ -571,7 +869,7 @@ cursor keys will then execute Org commands in the following 
contexts:
 Outside these contexts, the commands will throw an error.
 
 When this variable is t and the cursor is not in a special
-context, Org-mode will support shift-selection for making and
+context, Org mode will support shift-selection for making and
 enlarging regions.  To make this more effective, the bullet
 cycling will no longer happen anywhere in an item line, but only
 if the cursor is exactly on the bullet.
@@ -579,16 +877,16 @@ if the cursor is exactly on the bullet.
 If you set this variable to the symbol `always', then the keys
 will not be special in headlines, property lines, and item lines,
 to make shift selection work there as well.  If this is what you
-want, you can use the following alternative commands: `C-c C-t'
-and `C-c ,' to change TODO state and priority, `C-u C-u C-c C-t'
-can be used to switch TODO sets, `C-c -' to cycle item bullet
-types, and properties can be edited by hand or in column view.
+want, you can use the following alternative commands:
+`\\[org-todo]' and `\\[org-priority]' \
+to change TODO state and priority,
+`\\[universal-argument] \\[universal-argument] \\[org-todo]' \
+can be used to switch TODO sets,
+`\\[org-ctrl-c-minus]' to cycle item bullet types,
+and properties can be edited by hand or in column view.
 
 However, when the cursor is on a timestamp, shift-cursor commands
-will still edit the time stamp - this is just too good to give up.
-
-XEmacs user should have this variable set to nil, because
-`shift-select-mode' is in Emacs 23 or later only."
+will still edit the time stamp - this is just too good to give up."
   :group 'org
   :type '(choice
          (const :tag "Never" nil)
@@ -622,12 +920,13 @@ already archived entries."
   :group 'org-archive)
 
 (defgroup org-startup nil
-  "Options concerning startup of Org-mode."
+  "Options concerning startup of Org mode."
   :tag "Org Startup"
   :group 'org)
 
 (defcustom org-startup-folded t
-  "Non-nil means entering Org-mode will switch to OVERVIEW.
+  "Non-nil means entering Org mode will switch to OVERVIEW.
+
 This can also be configured on a per-file basis by adding one of
 the following lines anywhere in the buffer:
 
@@ -636,9 +935,9 @@ the following lines anywhere in the buffer:
    #+STARTUP: content
    #+STARTUP: showeverything
 
-By default, this option is ignored when Org opens agenda files
-for the first time.  If you want the agenda to honor the startup
-option, set `org-agenda-inhibit-startup' to nil."
+Set `org-agenda-inhibit-startup' to a non-nil value if you want
+to ignore this option when Org opens agenda files for the first
+time."
   :group 'org-startup
   :type '(choice
          (const :tag "nofold: show all" nil)
@@ -647,9 +946,18 @@ option, set `org-agenda-inhibit-startup' to nil."
          (const :tag "show everything, even drawers" showeverything)))
 
 (defcustom org-startup-truncated t
-  "Non-nil means entering Org-mode will set `truncate-lines'.
+  "Non-nil means entering Org mode will set `truncate-lines'.
 This is useful since some lines containing links can be very long and
-uninteresting.  Also tables look terrible when wrapped."
+uninteresting.  Also tables look terrible when wrapped.
+
+The variable `org-startup-truncated' allows to configure
+truncation for Org mode different to the other modes that use the
+variable `truncate-lines' and as a shortcut instead of putting
+the variable `truncate-lines' into the `org-mode-hook'.  If one
+wants to configure truncation for Org mode not statically but
+dynamically e. g. in a hook like `ediff-prepare-buffer-hook' then
+the variable `truncate-lines' has to be used because in such a
+case it is too late to set the variable `org-startup-truncated'."
   :group 'org-startup
   :type 'boolean)
 
@@ -742,26 +1050,26 @@ the following lines anywhere in the buffer:
   :type 'boolean)
 
 (defcustom org-insert-mode-line-in-empty-file nil
-  "Non-nil means insert the first line setting Org-mode in empty files.
+  "Non-nil means insert the first line setting Org mode in empty files.
 When the function `org-mode' is called interactively in an empty file, this
-normally means that the file name does not automatically trigger Org-mode.
-To ensure that the file will always be in Org-mode in the future, a
-line enforcing Org-mode will be inserted into the buffer, if this option
+normally means that the file name does not automatically trigger Org mode.
+To ensure that the file will always be in Org mode in the future, a
+line enforcing Org mode will be inserted into the buffer, if this option
 has been set."
   :group 'org-startup
   :type 'boolean)
 
 (defcustom org-replace-disputed-keys nil
   "Non-nil means use alternative key bindings for some keys.
-Org-mode uses S-<cursor> keys for changing timestamps and priorities.
+Org mode uses S-<cursor> keys for changing timestamps and priorities.
 These keys are also used by other packages like shift-selection-mode'
 \(built into Emacs 23), `CUA-mode' or `windmove.el'.
-If you want to use Org-mode together with one of these other modes,
-or more generally if you would like to move some Org-mode commands to
+If you want to use Org mode together with one of these other modes,
+or more generally if you would like to move some Org mode commands to
 other keys, set this variable and configure the keys with the variable
 `org-disputed-keys'.
 
-This option is only relevant at load-time of Org-mode, and must be set
+This option is only relevant at load-time of Org mode, and must be set
 *before* org.el is loaded.  Changing it requires a restart of Emacs to
 become effective."
   :group 'org-startup
@@ -769,18 +1077,13 @@ become effective."
 
 (defcustom org-use-extra-keys nil
   "Non-nil means use extra key sequence definitions for certain commands.
-This happens automatically if you run XEmacs or if `window-system'
-is nil.  This variable lets you do the same manually.  You must
-set it before loading org.
-
-Example: on Carbon Emacs 22 running graphically, with an external
-keyboard on a Powerbook, the default way of setting M-left might
-not work for either Alt or ESC.  Setting this variable will make
-it work for ESC."
+This happens automatically if `window-system' is nil.  This
+variable lets you do the same manually.  You must set it before
+loading Org."
   :group 'org-startup
   :type 'boolean)
 
-(org-defvaralias 'org-CUA-compatible 'org-replace-disputed-keys)
+(defvaralias 'org-CUA-compatible 'org-replace-disputed-keys)
 
 (defcustom org-disputed-keys
   '(([(shift up)]              . [(meta p)])
@@ -789,90 +1092,52 @@ it work for ESC."
     ([(shift right)]           . [(meta +)])
     ([(control shift right)]   . [(meta shift +)])
     ([(control shift left)]    . [(meta shift -)]))
-  "Keys for which Org-mode and other modes compete.
+  "Keys for which Org mode and other modes compete.
 This is an alist, cars are the default keys, second element specifies
 the alternative to use when `org-replace-disputed-keys' is t.
 
 Keys can be specified in any syntax supported by `define-key'.
-The value of this option takes effect only at Org-mode's startup,
+The value of this option takes effect only at Org mode startup,
 therefore you'll have to restart Emacs to apply it after changing."
   :group 'org-startup
   :type 'alist)
 
 (defun org-key (key)
   "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'.
-Or return the original if not disputed.
-Also apply the translations defined in `org-xemacs-key-equivalents'."
+Or return the original if not disputed."
   (when org-replace-disputed-keys
     (let* ((nkey (key-description key))
-          (x (org-find-if (lambda (x)
-                            (equal (key-description (car x)) nkey))
-                          org-disputed-keys)))
+          (x (cl-find-if (lambda (x) (equal (key-description (car x)) nkey))
+                         org-disputed-keys)))
       (setq key (if x (cdr x) key))))
-  (when (featurep 'xemacs)
-    (setq key (or (cdr (assoc key org-xemacs-key-equivalents)) key)))
   key)
 
-(defun org-find-if (predicate seq)
-  (catch 'exit
-    (while seq
-      (if (funcall predicate (car seq))
-         (throw 'exit (car seq))
-       (pop seq)))))
-
 (defun org-defkey (keymap key def)
   "Define a key, possibly translated, as returned by `org-key'."
   (define-key keymap (org-key key) def))
 
 (defcustom org-ellipsis nil
-  "The ellipsis to use in the Org-mode outline.
+  "The ellipsis to use in the Org mode outline.
+
 When nil, just use the standard three dots.
 When a string, use that string instead.
-When a face, use the standard 3 dots, but with the specified face.
-The change affects only Org-mode (which will then use its own display table).
+
+The change affects only Org mode (which will then use its own display table).
 Changing this requires executing `\\[org-mode]' in a buffer to become
 effective."
   :group 'org-startup
   :type '(choice (const :tag "Default" nil)
-                (face :tag "Face" :value org-warning)
-                (string :tag "String" :value "...#")))
+                (string :tag "String" :value "...#"))
+  :safe #'string-or-null-p)
 
 (defvar org-display-table nil
   "The display table for org-mode, in case `org-ellipsis' is non-nil.")
 
 (defgroup org-keywords nil
-  "Keywords in Org-mode."
+  "Keywords in Org mode."
   :tag "Org Keywords"
   :group 'org)
 
-(defcustom org-deadline-string "DEADLINE:"
-  "String to mark deadline entries.
-A deadline is this string, followed by a time stamp.  Should be a word,
-terminated by a colon.  You can insert a schedule keyword and
-a timestamp with \\[org-deadline].
-Changes become only effective after restarting Emacs."
-  :group 'org-keywords
-  :type 'string)
-
-(defcustom org-scheduled-string "SCHEDULED:"
-  "String to mark scheduled TODO entries.
-A schedule is this string, followed by a time stamp.  Should be a word,
-terminated by a colon.  You can insert a schedule keyword and
-a timestamp with \\[org-schedule].
-Changes become only effective after restarting Emacs."
-  :group 'org-keywords
-  :type 'string)
-
-(defcustom org-closed-string "CLOSED:"
-  "String used as the prefix for timestamps logging closing a TODO entry."
-  :group 'org-keywords
-  :type 'string)
-
-(defcustom org-clock-string "CLOCK:"
-  "String used as prefix for timestamps clocking work hours on an item."
-  :group 'org-keywords
-  :type 'string)
-
 (defcustom org-closed-keep-when-no-todo nil
   "Remove CLOSED: time-stamp when switching back to a non-todo state?"
   :group 'org-todo
@@ -881,37 +1146,8 @@ Changes become only effective after restarting Emacs."
   :package-version '(Org . "8.0")
   :type 'boolean)
 
-(defconst org-planning-or-clock-line-re (concat "^[ \t]*\\("
-                                               org-scheduled-string "\\|"
-                                               org-deadline-string "\\|"
-                                               org-closed-string "\\|"
-                                               org-clock-string "\\)")
-  "Matches a line with planning or clock info.")
-
-(defcustom org-comment-string "COMMENT"
-  "Entries starting with this keyword will never be exported.
-An entry can be toggled between COMMENT and normal with
-\\[org-toggle-comment].
-Changes become only effective after restarting Emacs."
-  :group 'org-keywords
-  :type 'string)
-
-(defcustom org-quote-string "QUOTE"
-  "Entries starting with this keyword will be exported in fixed-width font.
-Quoting applies only to the text in the entry following the headline, and does
-not extend beyond the next headline, even if that is lower level.
-An entry can be toggled between QUOTE and normal with
-\\[org-toggle-fixed-width-section]."
-  :group 'org-keywords
-  :type 'string)
-
-(defconst org-repeat-re
-  "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] 
[^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)"
-  "Regular expression for specifying repeated events.
-After a match, group 1 contains the repeat expression.")
-
 (defgroup org-structure nil
-  "Options concerning the general structure of Org-mode files."
+  "Options concerning the general structure of Org files."
   :tag "Org Structure"
   :group 'org)
 
@@ -920,92 +1156,88 @@ After a match, group 1 contains the repeat expression.")
   :tag "Org Reveal Location"
   :group 'org-structure)
 
-(defconst org-context-choice
-  '(choice
-    (const :tag "Always" t)
-    (const :tag "Never" nil)
-    (repeat :greedy t :tag "Individual contexts"
-           (cons
-            (choice :tag "Context"
-                    (const agenda)
-                    (const org-goto)
-                    (const occur-tree)
-                    (const tags-tree)
-                    (const link-search)
-                    (const mark-goto)
-                    (const bookmark-jump)
-                    (const isearch)
-                    (const default))
-            (boolean))))
-  "Contexts for the reveal options.")
-
-(defcustom org-show-hierarchy-above '((default . t))
-  "Non-nil means show full hierarchy when revealing a location.
-Org-mode often shows locations in an org-mode file which might have
-been invisible before.  When this is set, the hierarchy of headings
-above the exposed location is shown.
-Turning this off for example for sparse trees makes them very compact.
-Instead of t, this can also be an alist specifying this option for different
-contexts.  Valid contexts are
+(defcustom org-show-context-detail '((agenda . local)
+                                    (bookmark-jump . lineage)
+                                    (isearch . lineage)
+                                    (default . ancestors))
+  "Alist between context and visibility span when revealing a location.
+
+\\<org-mode-map>Some actions may move point into invisible
+locations.  As a consequence, Org always expose a neighborhood
+around point.  How much is shown depends on the initial action,
+or context.  Valid contexts are
+
   agenda         when exposing an entry from the agenda
-  org-goto       when using the command `org-goto' on key C-c C-j
-  occur-tree     when using the command `org-occur' on key C-c /
+  org-goto       when using the command `org-goto' (`\\[org-goto]')
+  occur-tree     when using the command `org-occur' (`\\[org-sparse-tree] /')
   tags-tree      when constructing a sparse tree based on tags matches
   link-search    when exposing search matches associated with a link
   mark-goto      when exposing the jump goal of a mark
   bookmark-jump  when exposing a bookmark location
   isearch        when exiting from an incremental search
-  default        default for all contexts not set explicitly"
-  :group 'org-reveal-location
-  :type org-context-choice)
-
-(defcustom org-show-following-heading '((default . nil))
-  "Non-nil means show following heading when revealing a location.
-Org-mode often shows locations in an org-mode file which might have
-been invisible before.  When this is set, the heading following the
-match is shown.
-Turning this off for example for sparse trees makes them very compact,
-but makes it harder to edit the location of the match.  In such a case,
-use the command \\[org-reveal] to show more context.
-Instead of t, this can also be an alist specifying this option for different
-contexts.  See `org-show-hierarchy-above' for valid contexts."
-  :group 'org-reveal-location
-  :type org-context-choice)
-
-(defcustom org-show-siblings '((default . nil) (isearch t) (bookmark-jump t))
-  "Non-nil means show all sibling heading when revealing a location.
-Org-mode often shows locations in an org-mode file which might have
-been invisible before.  When this is set, the sibling of the current entry
-heading are all made visible.  If `org-show-hierarchy-above' is t,
-the same happens on each level of the hierarchy above the current entry.
-
-By default this is on for the isearch context, off for all other contexts.
-Turning this off for example for sparse trees makes them very compact,
-but makes it harder to edit the location of the match.  In such a case,
-use the command \\[org-reveal] to show more context.
-Instead of t, this can also be an alist specifying this option for different
-contexts.  See `org-show-hierarchy-above' for valid contexts."
-  :group 'org-reveal-location
-  :type org-context-choice
-  :version "24.4"
-  :package-version '(Org . "8.0"))
+  default        default for all contexts not set explicitly
+
+Allowed visibility spans are
+
+  minimal        show current headline; if point is not on headline,
+                 also show entry
 
-(defcustom org-show-entry-below '((default . nil))
-  "Non-nil means show the entry below a headline when revealing a location.
-Org-mode often shows locations in an org-mode file which might have
-been invisible before.  When this is set, the text below the headline that is
-exposed is also shown.
+  local          show current headline, entry and next headline
 
-By default this is off for all contexts.
-Instead of t, this can also be an alist specifying this option for different
-contexts.  See `org-show-hierarchy-above' for valid contexts."
+  ancestors      show current headline and its direct ancestors; if
+                 point is not on headline, also show entry
+
+  lineage        show current headline, its direct ancestors and all
+                 their children; if point is not on headline, also show
+                 entry and first child
+
+  tree           show current headline, its direct ancestors and all
+                 their children; if point is not on headline, also show
+                 entry and all children
+
+  canonical      show current headline, its direct ancestors along with
+                 their entries and children; if point is not located on
+                 the headline, also show current entry and all children
+
+As special cases, a nil or t value means show all contexts in
+`minimal' or `canonical' view, respectively.
+
+Some views can make displayed information very compact, but also
+make it harder to edit the location of the match.  In such
+a case, use the command `org-reveal' (`\\[org-reveal]') to show
+more context."
   :group 'org-reveal-location
-  :type org-context-choice)
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type '(choice
+         (const :tag "Canonical" t)
+         (const :tag "Minimal" nil)
+         (repeat :greedy t :tag "Individual contexts"
+                 (cons
+                  (choice :tag "Context"
+                          (const agenda)
+                          (const org-goto)
+                          (const occur-tree)
+                          (const tags-tree)
+                          (const link-search)
+                          (const mark-goto)
+                          (const bookmark-jump)
+                          (const isearch)
+                          (const default))
+                  (choice :tag "Detail level"
+                          (const minimal)
+                          (const local)
+                          (const ancestors)
+                          (const lineage)
+                          (const tree)
+                          (const canonical))))))
 
 (defcustom org-indirect-buffer-display 'other-window
   "How should indirect tree buffers be displayed?
+
 This applies to indirect buffers created with the commands
-\\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer].
+`org-tree-to-indirect-buffer' and `org-agenda-tree-to-indirect-buffer'.
+
 Valid values are:
 current-window   Display in the current window
 other-window     Just display in another window.
@@ -1024,7 +1256,13 @@ new-frame        Make a new frame each time.  Note that 
in this case
 (defcustom org-use-speed-commands nil
   "Non-nil means activate single letter commands at beginning of a headline.
 This may also be a function to test for appropriate locations where speed
-commands should be active."
+commands should be active.
+
+For example, to activate speed commands when the point is on any
+star at the beginning of the headline, you can do this:
+
+  (setq org-use-speed-commands
+      (lambda () (and (looking-at org-outline-regexp) (looking-back 
\"^\\**\"))))"
   :group 'org-structure
   :type '(choice
          (const :tag "Never" nil)
@@ -1054,10 +1292,10 @@ commands in the Help buffer using the `?' speed 
command."
                                (sexp))))))
 
 (defcustom org-bookmark-names-plist
-   '(:last-capture "org-capture-last-stored"
-     :last-refile "org-refile-last-stored"
-     :last-capture-marker "org-capture-last-stored-marker")
-   "Names for bookmarks automatically set by some Org commands.
+  '(:last-capture "org-capture-last-stored"
+                 :last-refile "org-refile-last-stored"
+                 :last-capture-marker "org-capture-last-stored-marker")
+  "Names for bookmarks automatically set by some Org commands.
 This can provide strings as names for a number of bookmarks Org sets
 automatically.  The following keys are currently implemented:
   :last-capture
@@ -1065,11 +1303,11 @@ automatically.  The following keys are currently 
implemented:
   :last-refile
 When a key does not show up in the property list, the corresponding bookmark
 is not set."
-   :group 'org-structure
-   :type 'plist)
+  :group 'org-structure
+  :type 'plist)
 
 (defgroup org-cycle nil
-  "Options concerning visibility cycling in Org-mode."
+  "Options concerning visibility cycling in Org mode."
   :tag "Org Cycle"
   :group 'org-structure)
 
@@ -1093,25 +1331,8 @@ than its value."
          (const :tag "No limit" nil)
          (integer :tag "Maximum level")))
 
-(defcustom org-drawers '("PROPERTIES" "CLOCK" "LOGBOOK" "RESULTS")
-  "Names of drawers.  Drawers are not opened by cycling on the headline above.
-Drawers only open with a TAB on the drawer line itself.  A drawer looks like
-this:
-   :DRAWERNAME:
-   .....
-   :END:
-The drawer \"PROPERTIES\" is special for capturing properties through
-the property API.
-
-Drawers can be defined on the per-file basis with a line like:
-
-#+DRAWERS: HIDDEN STATE PROPERTIES"
-  :group 'org-structure
-  :group 'org-cycle
-  :type '(repeat (string :tag "Drawer Name")))
-
 (defcustom org-hide-block-startup nil
-  "Non-nil means entering Org-mode will fold all blocks.
+  "Non-nil means entering Org mode will fold all blocks.
 This can also be set in on a per-file basis with
 
 #+STARTUP: hideblocks
@@ -1122,12 +1343,17 @@ This can also be set in on a per-file basis with
 
 (defcustom org-cycle-global-at-bob nil
   "Cycle globally if cursor is at beginning of buffer and not at a headline.
-This makes it possible to do global cycling without having to use S-TAB or
-\\[universal-argument] TAB.  For this special case to work, the first line
-of the buffer must not be a headline -- it may be empty or some other text.
+
+This makes it possible to do global cycling without having to use `S-TAB'
+or `\\[universal-argument] TAB'.  For this special case to work, the first \
+line of the buffer
+must not be a headline -- it may be empty or some other text.
+
 When used in this way, `org-cycle-hook' is disabled temporarily to make
-sure the cursor stays at the beginning of the buffer.  When this option is
-nil, don't do anything special at the beginning of the buffer."
+sure the cursor stays at the beginning of the buffer.
+
+When this option is nil, don't do anything special at the beginning of
+the buffer."
   :group 'org-cycle
   :type 'boolean)
 
@@ -1166,7 +1392,7 @@ visibility is cycled."
   "Number of empty lines needed to keep an empty line between collapsed trees.
 If you leave an empty line between the end of a subtree and the following
 headline, this empty line is hidden when the subtree is folded.
-Org-mode will leave (exactly) one empty line visible if the number of
+Org mode will leave (exactly) one empty line visible if the number of
 empty lines is equal or larger to the number given in this variable.
 So the default 2 means at least 2 empty lines after the end of a subtree
 are needed to produce free space between a collapsed subtree and the
@@ -1192,7 +1418,6 @@ the values `folded', `children', or `subtree'."
 
 (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
                            org-cycle-hide-drawers
-                           org-cycle-hide-inline-tasks
                            org-cycle-show-empty-lines
                            org-optimize-window-after-visibility-change)
   "Hook that is run after `org-cycle' has changed the buffer visibility.
@@ -1202,10 +1427,12 @@ argument is a symbol.  After a global state change, it 
can have the values
 `overview', `contents', or `all'.  After a local state change, it can have
 the values `folded', `children', or `subtree'."
   :group 'org-cycle
-  :type 'hook)
+  :type 'hook
+  :version "26.1"
+  :package-version '(Org . "8.3"))
 
 (defgroup org-edit-structure nil
-  "Options concerning structure editing in Org-mode."
+  "Options concerning structure editing in Org mode."
   :tag "Org Edit Structure"
   :group 'org-structure)
 
@@ -1229,23 +1456,25 @@ lines to the buffer:
   "Non-nil means adapt indentation to outline node level.
 
 When this variable is set, Org assumes that you write outlines by
-indenting text in each node to align with the headline (after the stars).
-The following issues are influenced by this variable:
+indenting text in each node to align with the headline (after the
+stars).  The following issues are influenced by this variable:
 
-- When this is set and the *entire* text in an entry is indented, the
-  indentation is increased by one space in a demotion command, and
-  decreased by one in a promotion command.  If any line in the entry
-  body starts with text at column 0, indentation is not changed at all.
+- The indentation is increased by one space in a demotion
+  command, and decreased by one in a promotion command.  However,
+  in the latter case, if shifting some line in the entry body
+  would alter document structure (e.g., insert a new headline),
+  indentation is not changed at all.
 
-- Property drawers and planning information is inserted indented when
-  this variable s set.  When nil, they will not be indented.
+- Property drawers and planning information is inserted indented
+  when this variable is set.  When nil, they will not be indented.
 
-- TAB indents a line relative to context.  The lines below a headline
-  will be indented when this variable is set.
+- TAB indents a line relative to current level.  The lines below
+  a headline will be indented when this variable is set.
 
-Note that this is all about true indentation, by adding and removing
-space characters.  See also `org-indent.el' which does level-dependent
-indentation in a virtual way, i.e. at display time in Emacs."
+Note that this is all about true indentation, by adding and
+removing space characters.  See also `org-indent.el' which does
+level-dependent indentation in a virtual way, i.e. at display
+time in Emacs."
   :group 'org-edit-structure
   :type 'boolean)
 
@@ -1286,7 +1515,7 @@ This may also be a cons cell where the behavior for `C-a' 
and
                        (const :tag "off" nil)
                        (const :tag "on: before tags first" t)
                        (const :tag "reversed: after tags first" reversed)))))
-(org-defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e)
+(defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e)
 
 (defcustom org-special-ctrl-k nil
   "Non-nil means `C-k' will behave specially in headlines.
@@ -1386,9 +1615,11 @@ default   the value to be used for all contexts not 
explicitly
 
 (defcustom org-insert-heading-respect-content nil
   "Non-nil means insert new headings after the current subtree.
+\\<org-mode-map>
 When nil, the new heading is created directly after the current line.
-The commands \\[org-insert-heading-respect-content] and 
\\[org-insert-todo-heading-respect-content] turn
-this variable on for the duration of the command."
+The commands `\\[org-insert-heading-respect-content]' and \
+`\\[org-insert-todo-heading-respect-content]' turn this variable on
+for the duration of the command."
   :group 'org-structure
   :type 'boolean)
 
@@ -1398,11 +1629,7 @@ this variable on for the duration of the command."
 The value is an alist, with `heading' and `plain-list-item' as CAR,
 and a boolean flag as CDR.  The cdr may also be the symbol `auto', in
 which case Org will look at the surrounding headings/items and try to
-make an intelligent decision whether to insert a blank line or not.
-
-For plain lists, if `org-list-empty-line-terminates-plain-lists' is set,
-the setting here is ignored and no empty line is inserted to avoid breaking
-the list structure."
+make an intelligent decision whether to insert a blank line or not."
   :group 'org-edit-structure
   :type '(list
          (cons (const heading)
@@ -1422,8 +1649,7 @@ the list structure."
 (defcustom org-enable-fixed-width-editor t
   "Non-nil means lines starting with \":\" are treated as fixed-width.
 This currently only means they are never auto-wrapped.
-When nil, such lines will be treated like ordinary lines.
-See also the QUOTE keyword."
+When nil, such lines will be treated like ordinary lines."
   :group 'org-edit-structure
   :type 'boolean)
 
@@ -1441,7 +1667,7 @@ When nil, you can use these keybindings to navigate the 
buffer:
   :type 'boolean)
 
 (defgroup org-sparse-trees nil
-  "Options concerning sparse trees in Org-mode."
+  "Options concerning sparse trees in Org mode."
   :tag "Org Sparse Trees"
   :group 'org-structure)
 
@@ -1454,14 +1680,26 @@ changed by an edit command."
 
 (defcustom org-remove-highlights-with-change t
   "Non-nil means any change to the buffer will remove temporary highlights.
+\\<org-mode-map>\
 Such highlights are created by `org-occur' and `org-clock-display'.
-When nil, `C-c C-c' needs to be used to get rid of the highlights.
-The highlights created by `org-preview-latex-fragment' always need
-`C-c C-c' to be removed."
+When nil, `\\[org-ctrl-c-ctrl-c]' needs to be used \
+to get rid of the highlights.
+The highlights created by `org-toggle-latex-fragment' always need
+`\\[org-toggle-latex-fragment]' to be removed."
   :group 'org-sparse-trees
   :group 'org-time
   :type 'boolean)
 
+(defcustom org-occur-case-fold-search t
+  "Non-nil means `org-occur' should be case-insensitive.
+If set to `smart' the search will be case-insensitive only if it
+doesn't specify any upper case character."
+  :group 'org-sparse-trees
+  :version "26.1"
+  :type '(choice
+         (const :tag "Case-sensitive" nil)
+         (const :tag "Case-insensitive" t)
+         (const :tag "Case-insensitive for lower case searches only" 'smart)))
 
 (defcustom org-occur-hook '(org-first-headline-recenter)
   "Hook that is run after `org-occur' has constructed a sparse tree.
@@ -1471,18 +1709,18 @@ as possible."
   :type 'hook)
 
 (defgroup org-imenu-and-speedbar nil
-  "Options concerning imenu and speedbar in Org-mode."
+  "Options concerning imenu and speedbar in Org mode."
   :tag "Org Imenu and Speedbar"
   :group 'org-structure)
 
 (defcustom org-imenu-depth 2
-  "The maximum level for Imenu access to Org-mode headlines.
+  "The maximum level for Imenu access to Org headlines.
 This also applied for speedbar access."
   :group 'org-imenu-and-speedbar
   :type 'integer)
 
 (defgroup org-table nil
-  "Options concerning tables in Org-mode."
+  "Options concerning tables in Org mode."
   :tag "Org Table"
   :group 'org)
 
@@ -1499,12 +1737,12 @@ do the following:
   TAB or RET are pressed to move to another field.  With optimization this
   happens only if changes to a field might have changed the column width.
 Optimization requires replacing the functions `self-insert-command',
-`delete-char', and `backward-delete-char' in Org-mode buffers, with a
-slight (in fact: unnoticeable) speed impact for normal typing.  Org-mode is
-very good at guessing when a re-align will be necessary, but you can always
-force one with \\[org-ctrl-c-ctrl-c].
+`delete-char', and `backward-delete-char' in Org buffers, with a
+slight (in fact: unnoticeable) speed impact for normal typing.  Org is very
+good at guessing when a re-align will be necessary, but you can always
+force one with `\\[org-ctrl-c-ctrl-c]'.
 
-If you would like to use the optimized version in Org-mode, but the
+If you would like to use the optimized version in Org mode, but the
 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
 
 This variable can be used to turn on and off the table editor during a session,
@@ -1517,8 +1755,7 @@ See also the variable `org-table-auto-blank-field'."
          (const :tag "on" t)
          (const :tag "on, optimized" optimized)))
 
-(defcustom org-self-insert-cluster-for-undo (or (featurep 'xemacs)
-                                               (version<= emacs-version 
"24.1"))
+(defcustom org-self-insert-cluster-for-undo nil
   "Non-nil means cluster self-insert commands for undo when possible.
 If this is set, then, like in the Emacs command loop, 20 consecutive
 characters will be undone together.
@@ -1534,24 +1771,95 @@ calls `table-recognize-table'."
   :type 'boolean)
 
 (defgroup org-link nil
-  "Options concerning links in Org-mode."
+  "Options concerning links in Org mode."
   :tag "Org Link"
   :group 'org)
 
-(defvar org-link-abbrev-alist-local nil
+(defvar-local org-link-abbrev-alist-local nil
   "Buffer-local version of `org-link-abbrev-alist', which see.
 The value of this is taken from the #+LINK lines.")
-(make-variable-buffer-local 'org-link-abbrev-alist-local)
+
+(defcustom org-link-parameters
+  '(("doi" :follow org--open-doi-link)
+    ("elisp" :follow org--open-elisp-link)
+    ("file" :complete org-file-complete-link)
+    ("ftp" :follow (lambda (path) (browse-url (concat "ftp:" path))))
+    ("help" :follow org--open-help-link)
+    ("http" :follow (lambda (path) (browse-url (concat "http:" path))))
+    ("https" :follow (lambda (path) (browse-url (concat "https:" path))))
+    ("mailto" :follow (lambda (path) (browse-url (concat "mailto:"; path))))
+    ("message" :follow (lambda (path) (browse-url (concat "message:" path))))
+    ("news" :follow (lambda (path) (browse-url (concat "news:"; path))))
+    ("shell" :follow org--open-shell-link))
+  "An alist of properties that defines all the links in Org mode.
+The key in each association is a string of the link type.
+Subsequent optional elements make up a p-list of link properties.
+
+:follow - A function that takes the link path as an argument.
+
+:export - A function that takes the link path, description and
+export-backend as arguments.
+
+:store - A function responsible for storing the link.  See the
+function `org-store-link-functions'.
+
+:complete - A function that inserts a link with completion.  The
+function takes one optional prefix arg.
+
+:face - A face for the link, or a function that returns a face.
+The function takes one argument which is the link path.  The
+default face is `org-link'.
+
+:mouse-face - The mouse-face. The default is `highlight'.
+
+:display - `full' will not fold the link in descriptive
+display.  Default is `org-link'.
+
+:help-echo - A string or function that takes (window object position)
+as arguments and returns a string.
+
+:keymap - A keymap that is active on the link.  The default is
+`org-mouse-map'.
+
+:htmlize-link - A function for the htmlize-link.  Defaults
+to (list :uri \"type:path\")
+
+:activate-func - A function to run at the end of font-lock
+activation.  The function must accept (link-start link-end path bracketp)
+as arguments."
+  :group 'org-link
+  :type '(alist :tag "Link display parameters"
+               :value-type plist))
+
+(defun org-link-get-parameter (type key)
+  "Get TYPE link property for KEY.
+TYPE is a string and KEY is a plist keyword."
+  (plist-get
+   (cdr (assoc type org-link-parameters))
+   key))
+
+(defun org-link-set-parameters (type &rest parameters)
+  "Set link TYPE properties to PARAMETERS.
+  PARAMETERS should be :key val pairs."
+  (let ((data (assoc type org-link-parameters)))
+    (if data (setcdr data (org-combine-plists (cdr data) parameters))
+      (push (cons type parameters) org-link-parameters)
+      (org-make-link-regexps)
+      (org-element-update-syntax))))
+
+(defun org-link-types ()
+  "Return a list of known link types."
+  (mapcar #'car org-link-parameters))
 
 (defcustom org-link-abbrev-alist nil
   "Alist of link abbreviations.
 The car of each element is a string, to be replaced at the start of a link.
 The cdrs are replacement values, like (\"linkkey\" . REPLACE).  Abbreviated
-links in Org-mode buffers can have an optional tag after a double colon, e.g.
+links in Org buffers can have an optional tag after a double colon, e.g.,
 
      [[linkkey:tag][description]]
 
-The `linkkey' must be a word word, starting with a letter, followed
+The `linkkey' must be a single word, starting with a letter, followed
 by letters, numbers, `-' or `_'.
 
 If REPLACE is a string, the tag will simply be appended to create the link.
@@ -1603,11 +1911,18 @@ adaptive  Use relative path for files in the current 
directory and sub-
          (const noabbrev)
          (const adaptive)))
 
-(defcustom org-activate-links '(bracket angle plain radio tag date footnote)
-  "Types of links that should be activated in Org-mode files.
-This is a list of symbols, each leading to the activation of a certain link
-type.  In principle, it does not hurt to turn on most link types - there may
-be a small gain when turning off unused link types.  The types are:
+(defvaralias 'org-activate-links 'org-highlight-links)
+(defcustom org-highlight-links '(bracket angle plain radio tag date footnote)
+  "Types of links that should be highlighted in Org files.
+
+This is a list of symbols, each one of them leading to the
+highlighting of a certain link type.
+
+You can still open links that are not highlighted.
+
+In principle, it does not hurt to turn on highlighting for all
+link types.  There may be a small gain when turning off unused
+link types.  The types are:
 
 bracket   The recommended [[link][description]] or [[link]] links with hiding.
 angle     Links in angular brackets that may contain whitespace like
@@ -1618,8 +1933,10 @@ tag       Tag settings in a headline (link to tag 
search).
 date      Time stamps (link to calendar).
 footnote  Footnote labels.
 
-Changing this variable requires a restart of Emacs to become effective."
+If you set this variable during an Emacs session, use `org-mode-restart'
+in the Org buffer so that the change takes effect."
   :group 'org-link
+  :group 'org-appearance
   :type '(set :greedy t
              (const :tag "Double bracket links" bracket)
              (const :tag "Angular bracket links" angle)
@@ -1639,7 +1956,7 @@ return the description to use."
   :type '(choice (const nil) (function)))
 
 (defgroup org-link-store nil
-  "Options concerning storing links in Org-mode."
+  "Options concerning storing links in Org mode."
   :tag "Org Store Link"
   :group 'org-link)
 
@@ -1684,32 +2001,36 @@ It should match if the message is from the user 
him/herself."
 
 (defcustom org-context-in-file-links t
   "Non-nil means file links from `org-store-link' contain context.
-A search string will be added to the file name with :: as separator and
-used to find the context when the link is activated by the command
+\\<org-mode-map>
+A search string will be added to the file name with :: as separator
+and used to find the context when the link is activated by the command
 `org-open-at-point'.  When this option is t, the entire active region
 will be placed in the search string of the file link.  If set to a
 positive integer, only the first n lines of context will be stored.
 
-Using a prefix arg to the command \\[org-store-link] (`org-store-link')
+Using a prefix arg to the command `org-store-link' (`\\[universal-argument] \
+\\[org-store-link]')
 negates this setting for the duration of the command."
   :group 'org-link-store
   :type '(choice boolean integer))
 
 (defcustom org-keep-stored-link-after-insertion nil
   "Non-nil means keep link in list for entire session.
-
+\\<org-mode-map>
 The command `org-store-link' adds a link pointing to the current
 location to an internal list.  These links accumulate during a session.
 The command `org-insert-link' can be used to insert links into any
-Org-mode file (offering completion for all stored links).  When this
-option is nil, every link which has been inserted once using 
\\[org-insert-link]
-will be removed from the list, to make completing the unused links
-more efficient."
+Org file (offering completion for all stored links).
+
+When this option is nil, every link which has been inserted once using
+`\\[org-insert-link]' will be removed from the list, to make completing the \
+unused
+links more efficient."
   :group 'org-link-store
   :type 'boolean)
 
 (defgroup org-link-follow nil
-  "Options concerning following links in Org-mode."
+  "Options concerning following links in Org mode."
   :tag "Org Follow Link"
   :group 'org-link)
 
@@ -1749,8 +2070,8 @@ In tables, the special behavior of RET has precedence."
 (defcustom org-mouse-1-follows-link
   (if (boundp 'mouse-1-click-follows-link) mouse-1-click-follows-link t)
   "Non-nil means mouse-1 on a link will follow the link.
-A longer mouse click will still set point.  Does not work on XEmacs.
-Needs to be set before org.el is loaded."
+A longer mouse click will still set point.  Needs to be set
+before org.el is loaded."
   :group 'org-link-follow
   :version "24.4"
   :package-version '(Org . "8.3")
@@ -1766,16 +2087,22 @@ Changing this requires a restart of Emacs to work 
correctly."
   :type 'integer)
 
 (defcustom org-link-search-must-match-exact-headline 'query-to-create
-  "Non-nil means internal links in Org files must exactly match a headline.
-When nil, the link search tries to match a phrase with all words
-in the search text."
+  "Non-nil means internal fuzzy links can only match headlines.
+
+When nil, the a fuzzy link may point to a target or a named
+construct in the document.  When set to the special value
+`query-to-create', offer to create a new headline when none
+matched.
+
+Spaces and statistics cookies are ignored during heading searches."
   :group 'org-link-follow
   :version "24.1"
   :type '(choice
          (const :tag "Use fuzzy text search" nil)
          (const :tag "Match only exact headline" t)
          (const :tag "Match exact headline or query to create it"
-                query-to-create)))
+                query-to-create))
+  :safe #'symbolp)
 
 (defcustom org-link-frame-setup
   '((vm . vm-visit-folder-other-frame)
@@ -1836,7 +2163,7 @@ another window."
   "Non-nil means use indirect buffer to display infile links.
 Activating internal links (from one location in a file to another location
 in the same file) normally just jumps to the location.  When the link is
-activated with a \\[universal-argument] prefix (or with mouse-3), the link \
+activated with a `\\[universal-argument]' prefix (or with mouse-3), the link \
 is displayed in
 another window.  When this option is set, the other window actually displays
 an indirect buffer clone of the current buffer, to avoid any visibility
@@ -1860,26 +2187,13 @@ window on that directory."
   :group 'org-link-follow
   :type 'boolean)
 
-(defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s";)
-  "Function and arguments to call for following mailto links.
-This is a list with the first element being a Lisp function, and the
-remaining elements being arguments to the function.  In string arguments,
-%a will be replaced by the address, and %s will be replaced by the subject
-if one was given like in <mailto:address@hidden::this subject>."
-  :group 'org-link-follow
-  :type '(choice
-         (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s";))
-         (const :tag "compose-mail" (compose-mail "%a" "%s"))
-         (const :tag "message-mail" (message-mail "%a" "%s"))
-         (cons :tag "other" (function) (repeat :tag "argument" sexp))))
-
 (defcustom org-confirm-shell-link-function 'yes-or-no-p
   "Non-nil means ask for confirmation before executing shell links.
 Shell links can be dangerous: just think about a link
 
      [[shell:rm -rf ~/*][Google Search]]
 
-This link would show up in your Org-mode document as \"Google Search\",
+This link would show up in your Org document as \"Google Search\",
 but really it would remove your entire home directory.
 Therefore we advise against setting this variable to nil.
 Just change it to `y-or-n-p' if you want to confirm with a
@@ -1891,7 +2205,7 @@ single keystroke rather than having to type \"yes\"."
          (const :tag "no confirmation (dangerous)" nil)))
 (put 'org-confirm-shell-link-function
      'safe-local-variable
-     #'(lambda (x) (member x '(yes-or-no-p y-or-n-p))))
+     (lambda (x) (member x '(yes-or-no-p y-or-n-p))))
 
 (defcustom org-confirm-shell-link-not-regexp ""
   "A regexp to skip confirmation for shell links."
@@ -1905,7 +2219,7 @@ Elisp links can be dangerous: just think about a link
 
      [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
 
-This link would show up in your Org-mode document as \"Google Search\",
+This link would show up in your Org document as \"Google Search\",
 but really it would remove your entire home directory.
 Therefore we advise against setting this variable to nil.
 Just change it to `y-or-n-p' if you want to confirm with a
@@ -1917,7 +2231,7 @@ single keystroke rather than having to type \"yes\"."
          (const :tag "no confirmation (dangerous)" nil)))
 (put 'org-confirm-shell-link-function
      'safe-local-variable
-     #'(lambda (x) (member x '(yes-or-no-p y-or-n-p))))
+     (lambda (x) (member x '(yes-or-no-p y-or-n-p))))
 
 (defcustom org-confirm-elisp-link-not-regexp ""
   "A regexp to skip confirmation for Elisp links."
@@ -1934,30 +2248,23 @@ See `org-file-apps'.")
 
 (defconst org-file-apps-defaults-macosx
   '((remote . emacs)
-    (t . "open %s")
     (system . "open %s")
     ("ps.gz"  . "gv %s")
     ("eps.gz" . "gv %s")
     ("dvi"    . "xdvi %s")
-    ("fig"    . "xfig %s"))
+    ("fig"    . "xfig %s")
+    (t . "open %s"))
   "Default file applications on a macOS system.
 The system \"open\" is known as a default, but we use X11 applications
 for some files for which the OS does not have a good default.
 See `org-file-apps'.")
 
 (defconst org-file-apps-defaults-windowsnt
-  (list
-   '(remote . emacs)
-   (cons t
-        (list (if (featurep 'xemacs)
-                  'mswindows-shell-execute
-                'w32-shell-execute)
-              "open" 'file))
-   (cons 'system
-        (list (if (featurep 'xemacs)
-                  'mswindows-shell-execute
-                'w32-shell-execute)
-              "open" 'file)))
+  (list '(remote . emacs)
+       (cons 'system (lambda (file _path)
+                       (with-no-warnings (w32-shell-execute "open" file))))
+       (cons t (lambda (file _path)
+                 (with-no-warnings (w32-shell-execute "open" file)))))
   "Default file applications on a Windows NT system.
 The system \"open\" is used for most files.
 See `org-file-apps'.")
@@ -1968,11 +2275,15 @@ See `org-file-apps'.")
     ("\\.x?html?\\'" . default)
     ("\\.pdf\\'" . default))
   "External applications for opening `file:path' items in a document.
-Org-mode uses system defaults for different file types, but
+\\<org-mode-map>\
+
+Org mode uses system defaults for different file types, but
 you can use this variable to set the application for a given file
 extension.  The entries in this list are cons cells where the car identifies
-files and the cdr the corresponding command.  Possible values for the
-file identifier are
+files and the cdr the corresponding command.
+
+Possible values for the file identifier are:
+
  \"string\"    A string as a file identifier can be interpreted in different
                ways, depending on its contents:
 
@@ -1985,8 +2296,8 @@ file identifier are
                  filename matches the regexp.  If you want to
                  use groups here, use shy groups.
 
-                 Example: (\"\\.x?html\\\\='\" . \"firefox %s\")
-                          (\"\\(?:xhtml\\|html\\)\" . \"firefox %s\")
+                 Example: (\"\\\\.x?html\\\\\\='\" . \"firefox %s\")
+                          (\"\\\\(?:xhtml\\\\|html\\\\)\\\\\\='\" . \"firefox 
%s\")
                           to open *.html and *.xhtml with firefox.
 
                - Regular expression which contains (non-shy) groups:
@@ -1998,10 +2309,11 @@ file identifier are
                  that does not use any of the group matches, this case is
                  handled identically to the second one (i.e. match against
                  file name only).
-                 In a custom lisp form, you can access the group matches with
+                 In a custom function, you can access the group matches with
                  (match-string n link).
 
-                 Example: (\"\\.pdf::\\(\\d+\\)\\\\='\" . \"evince -p %1 %s\")
+                 Example: (\"\\\\.pdf::\\\\(\\\\d+\\\\)\\\\\\='\" . \
+\"evince -p %1 %s\")
                      to open [[file:document.pdf::5]] with evince at page 5.
 
  `directory'   Matches a directory
@@ -2013,28 +2325,32 @@ file identifier are
                command `emacs' will open most files in Emacs.  Beware that this
                will also open html files inside Emacs, unless you add
                (\"html\" . default) to the list as well.
- t             Default for files not matched by any of the other options.
  `system'      The system command to open files, like `open' on Windows
                and macOS, and mailcap under GNU/Linux.  This is the command
-               that will be selected if you call `C-c C-o' with a double
-               \\[universal-argument] \\[universal-argument] prefix.
+               that will be selected if you call `org-open-at-point' with a
+               double prefix argument (`\\[universal-argument] \
+\\[universal-argument] \\[org-open-at-point]').
+ t             Default for files not matched by any of the other options.
 
 Possible values for the command are:
+
  `emacs'       The file will be visited by the current Emacs process.
  `default'     Use the default application for this file type, which is the
                association for t in the list, most likely in the 
system-specific
-               part.
-               This can be used to overrule an unwanted setting in the
+               part.  This can be used to overrule an unwanted setting in the
                system-specific variable.
  `system'      Use the system command for opening files, like \"open\".
                This command is specified by the entry whose car is `system'.
                Most likely, the system-specific version of this variable
                does define this command, but you can overrule/replace it
                here.
+`mailcap'      Use command specified in the mailcaps.
  string        A command to be executed by a shell; %s will be replaced
                by the path to the file.
- sexp          A Lisp form which will be evaluated.  The file path will
-               be available in the Lisp variable `file'.
+ function      A Lisp function, which will be called with two arguments:
+               the file path and the original link string, without the
+               \"file:\" prefix.
+
 For more examples, see the system specific constants
 `org-file-apps-defaults-macosx'
 `org-file-apps-defaults-windowsnt'
@@ -2054,7 +2370,7 @@ For more examples, see the system specific constants
                        (const :tag "Use default" default)
                        (const :tag "Use the system command" system)
                        (string :tag "Command")
-                       (sexp :tag "Lisp form")))))
+                       (function :tag "Function")))))
 
 (defcustom org-doi-server-url "http://dx.doi.org/";
   "The URL of the DOI server."
@@ -2063,22 +2379,22 @@ For more examples, see the system specific constants
   :group 'org-link-follow)
 
 (defgroup org-refile nil
-  "Options concerning refiling entries in Org-mode."
+  "Options concerning refiling entries in Org mode."
   :tag "Org Refile"
   :group 'org)
 
 (defcustom org-directory "~/org"
-  "Directory with org files.
+  "Directory with Org files.
 This is just a default location to look for Org files.  There is no need
-at all to put your files into this directory.  It is only used in the
+at all to put your files into this directory.  It is used in the
 following situations:
 
 1. When a capture template specifies a target file that is not an
    absolute path.  The path will then be interpreted relative to
    `org-directory'
-2. When a capture note is filed away in an interactive way (when exiting the
-   note buffer with `C-1 C-c C-c'.  The user is prompted for an org file,
-   with `org-directory' as the default path."
+2. When the value of variable `org-agenda-files' is a single file, any
+   relative paths in this file will be taken as relative to
+   `org-directory'."
   :group 'org-refile
   :group 'org-capture
   :type 'directory)
@@ -2089,9 +2405,7 @@ Used as a fall back file for org-capture.el, for 
templates that
 do not specify a target file."
   :group 'org-refile
   :group 'org-capture
-  :type '(choice
-         (const :tag "Default from remember-data-file" nil)
-         file))
+  :type 'file)
 
 (defcustom org-goto-interface 'outline
   "The default interface to be used for `org-goto'.
@@ -2154,7 +2468,7 @@ will temporarily be changed to `time'."
          (const :tag "Record timestamp with note." note)))
 
 (defcustom org-refile-targets nil
-  "Targets for refiling entries with \\[org-refile].
+  "Targets for refiling entries with `\\[org-refile]'.
 This is a list of cons cells.  Each cell contains:
 - a specification of the files to be considered, either a list of files,
   or a symbol whose function or variable value will be used to retrieve
@@ -2218,12 +2532,15 @@ of the subtree."
 
 (defcustom org-refile-use-cache nil
   "Non-nil means cache refile targets to speed up the process.
+\\<org-mode-map>\
 The cache for a particular file will be updated automatically when
 the buffer has been killed, or when any of the marker used for flagging
 refile targets no longer points at a live buffer.
 If you have added new entries to a buffer that might themselves be targets,
-you need to clear the cache manually by pressing `C-0 C-c C-w' or, if you
-find that easier, `C-u C-u C-u C-c C-w'."
+you need to clear the cache manually by pressing `C-0 \\[org-refile]' or,
+if you find that easier, \
+`\\[universal-argument] \\[universal-argument] \\[universal-argument] \
+\\[org-refile]'."
   :group 'org-refile
   :version "24.1"
   :type 'boolean)
@@ -2246,13 +2563,13 @@ When `full-file-path', include the full file path."
 
 (defcustom org-outline-path-complete-in-steps t
   "Non-nil means complete the outline path in hierarchical steps.
-When Org-mode uses the refile interface to select an outline path
-\(see variable `org-refile-use-outline-path'), the completion of
-the path can be done is a single go, or if can be done in steps down
-the headline hierarchy.  Going in steps is probably the best if you
-do not use a special completion package like `ido' or `icicles'.
-However, when using these packages, going in one step can be very
-fast, while still showing the whole path to the entry."
+When Org uses the refile interface to select an outline path (see
+`org-refile-use-outline-path'), the completion of the path can be
+done in a single go, or it can be done in steps down the headline
+hierarchy.  Going in steps is probably the best if you do not use
+a special completion package like `ido' or `icicles'.  However,
+when using these packages, going in one step can be very fast,
+while still showing the whole path to the entry."
   :group 'org-refile
   :type 'boolean)
 
@@ -2285,12 +2602,12 @@ converted to a headline before refiling."
   :type 'boolean)
 
 (defgroup org-todo nil
-  "Options concerning TODO items in Org-mode."
+  "Options concerning TODO items in Org mode."
   :tag "Org TODO"
   :group 'org)
 
 (defgroup org-progress nil
-  "Options concerning Progress logging in Org-mode."
+  "Options concerning Progress logging in Org mode."
   :tag "Org Progress"
   :group 'org-time)
 
@@ -2308,12 +2625,12 @@ Each sequence starts with a symbol, either `sequence' 
or `type',
 indicating if the keywords should be interpreted as a sequence of
 action steps, or as different types of TODO items.  The first
 keywords are states requiring action - these states will select a headline
-for inclusion into the global TODO list Org-mode produces.  If one of
-the \"keywords\" is the vertical bar, \"|\", the remaining keywords
+for inclusion into the global TODO list Org produces.  If one of the
+\"keywords\" is the vertical bar, \"|\", the remaining keywords
 signify that no further action is necessary.  If \"|\" is not found,
 the last keyword is treated as the only DONE state of the sequence.
 
-The command \\[org-todo] cycles an entry through these states, and one
+The command `\\[org-todo]' cycles an entry through these states, and one
 additional state where no keyword is present.  For details about this
 cycling, see the manual.
 
@@ -2356,44 +2673,37 @@ taken from the (otherwise obsolete) variable 
`org-todo-interpretation'."
                    (lambda (widget)
                      (widget-put widget
                                  :args (mapcar
-                                        #'(lambda (x)
-                                            (widget-convert
-                                             (cons 'const x)))
+                                        (lambda (x)
+                                          (widget-convert
+                                           (cons 'const x)))
                                         org-todo-interpretation-widgets))
                      widget))
                   (repeat
                    (string :tag "Keyword"))))))
 
-(defvar org-todo-keywords-1 nil
+(defvar-local org-todo-keywords-1 nil
   "All TODO and DONE keywords active in a buffer.")
-(make-variable-buffer-local 'org-todo-keywords-1)
 (defvar org-todo-keywords-for-agenda nil)
 (defvar org-done-keywords-for-agenda nil)
-(defvar org-drawers-for-agenda nil)
 (defvar org-todo-keyword-alist-for-agenda nil)
 (defvar org-tag-alist-for-agenda nil
   "Alist of all tags from all agenda files.")
 (defvar org-tag-groups-alist-for-agenda nil
   "Alist of all groups tags from all current agenda files.")
-(defvar org-tag-groups-alist nil)
-(make-variable-buffer-local 'org-tag-groups-alist)
+(defvar-local org-tag-groups-alist nil)
 (defvar org-agenda-contributing-files nil)
-(defvar org-not-done-keywords nil)
-(make-variable-buffer-local 'org-not-done-keywords)
-(defvar org-done-keywords nil)
-(make-variable-buffer-local 'org-done-keywords)
-(defvar org-todo-heads nil)
-(make-variable-buffer-local 'org-todo-heads)
-(defvar org-todo-sets nil)
-(make-variable-buffer-local 'org-todo-sets)
-(defvar org-todo-log-states nil)
-(make-variable-buffer-local 'org-todo-log-states)
-(defvar org-todo-kwd-alist nil)
-(make-variable-buffer-local 'org-todo-kwd-alist)
-(defvar org-todo-key-alist nil)
-(make-variable-buffer-local 'org-todo-key-alist)
-(defvar org-todo-key-trigger nil)
-(make-variable-buffer-local 'org-todo-key-trigger)
+(defvar-local org-current-tag-alist nil
+  "Alist of all tag groups in current buffer.
+This variable takes into consideration `org-tag-alist',
+`org-tag-persistent-alist' and TAGS keywords in the buffer.")
+(defvar-local org-not-done-keywords nil)
+(defvar-local org-done-keywords nil)
+(defvar-local org-todo-heads nil)
+(defvar-local org-todo-sets nil)
+(defvar-local org-todo-log-states nil)
+(defvar-local org-todo-kwd-alist nil)
+(defvar-local org-todo-key-alist nil)
+(defvar-local org-todo-key-trigger nil)
 
 (defcustom org-todo-interpretation 'sequence
   "Controls how TODO keywords are interpreted.
@@ -2407,7 +2717,8 @@ more information."
                 (const type)))
 
 (defcustom org-use-fast-todo-selection t
-  "Non-nil means use the fast todo selection scheme with C-c C-t.
+  "\\<org-mode-map>\
+Non-nil means use the fast todo selection scheme with `\\[org-todo]'.
 This variable describes if and under what circumstances the cycling
 mechanism for TODO keywords will be replaced by a single-key, direct
 selection scheme.
@@ -2415,8 +2726,9 @@ selection scheme.
 When nil, fast selection is never used.
 
 When the symbol `prefix', it will be used when `org-todo' is called
-with a prefix argument,  i.e. `C-u C-c C-t' in an Org-mode buffer, and
-`C-u t' in an agenda buffer.
+with a prefix argument,  i.e. `\\[universal-argument] \\[org-todo]' \
+in an Org buffer, and
+`\\[universal-argument] t' in an agenda buffer.
 
 When t, fast selection is used by default.  In this case, the prefix
 argument forces cycling instead.
@@ -2436,6 +2748,9 @@ ALL-HEADLINES means update todo statistics by including 
headlines
 with no TODO keyword as well, counting them as not done.
 A list of TODO keywords means the same, but skip keywords that are
 not in this list.
+When set to a list of two lists, the first list contains keywords
+to consider as TODO keywords, the second list contains keywords
+to consider as DONE keywords.
 
 When this is set, todo statistics is updated in the parent of the
 current entry each time a todo state is changed."
@@ -2445,6 +2760,9 @@ current entry each time a todo state is changed."
          (const :tag "Yes, including all entries" all-headlines)
          (repeat :tag "Yes, for TODOs in this list"
                  (string :tag "TODO keyword"))
+         (list :tag "Yes, for TODOs and DONEs in these lists"
+               (repeat (string :tag "TODO keyword"))
+               (repeat (string :tag "DONE keyword")))
          (other :tag "No TODO statistics" nil)))
 
 (defcustom org-hierarchical-todo-statistics t
@@ -2529,7 +2847,7 @@ to change is while Emacs is running is through the 
customize interface."
 
 (defcustom org-treat-insert-todo-heading-as-state-change nil
   "Non-nil means inserting a TODO heading is treated as state change.
-So when the command \\[org-insert-todo-heading] is used, state change
+So when the command `\\[org-insert-todo-heading]' is used, state change
 logging will apply if appropriate.  When nil, the new TODO item will
 be inserted directly, and no logging will take place."
   :group 'org-todo
@@ -2667,20 +2985,23 @@ When nil, only the date will be recorded."
     (refile . "Refiled on %t")
     (clock-out . ""))
   "Headings for notes added to entries.
-The value is an alist, with the car being a symbol indicating the note
-context, and the cdr is the heading to be used.  The heading may also be the
-empty string.
-%t in the heading will be replaced by a time stamp.
-%T will be an active time stamp instead the default inactive one
-%d will be replaced by a short-format time stamp.
-%D will be replaced by an active short-format time stamp.
-%s will be replaced by the new TODO state, in double quotes.
-%S will be replaced by the old TODO state, in double quotes.
-%u will be replaced by the user name.
-%U will be replaced by the full user name.
-
-In fact, it is not a good idea to change the `state' entry, because
-agenda log mode depends on the format of these entries."
+
+The value is an alist, with the car being a symbol indicating the
+note context, and the cdr is the heading to be used.  The heading
+may also be the empty string.  The following placeholders can be
+used:
+
+  %t  a time stamp.
+  %T  an active time stamp instead the default inactive one
+  %d  a short-format time stamp.
+  %D  an active short-format time stamp.
+  %s  the new TODO state or time stamp (inactive), in double quotes.
+  %S  the old TODO state or time stamp (inactive), in double quotes.
+  %u  the user name.
+  %U  full user name.
+
+In fact, it is not a good idea to change the `state' entry,
+because Agenda Log mode depends on the format of these entries."
   :group  'org-todo
   :group  'org-progress
   :type '(list :greedy t
@@ -2719,7 +3040,10 @@ If this variable is set, 
`org-log-state-notes-insert-after-drawers'
 will be ignored.
 
 You can set the property LOG_INTO_DRAWER to overrule this setting for
-a subtree."
+a subtree.
+
+Do not check directly this variable in a Lisp program.  Call
+function `org-log-into-drawer' instead."
   :group 'org-todo
   :group 'org-progress
   :type '(choice
@@ -2727,18 +3051,20 @@ a subtree."
          (const :tag "LOGBOOK" t)
          (string :tag "Other")))
 
-(org-defvaralias 'org-log-state-notes-into-drawer 'org-log-into-drawer)
+(defvaralias 'org-log-state-notes-into-drawer 'org-log-into-drawer)
 
 (defun org-log-into-drawer ()
-  "Return the value of `org-log-into-drawer', but let properties overrule.
-If the current entry has or inherits a LOG_INTO_DRAWER property, it will be
-used instead of the default value."
+  "Name of the log drawer, as a string, or nil.
+This is the value of `org-log-into-drawer'.  However, if the
+current entry has or inherits a LOG_INTO_DRAWER property, it will
+be used instead of the default value."
   (let ((p (org-entry-get nil "LOG_INTO_DRAWER" 'inherit t)))
-    (cond
-     ((not p) org-log-into-drawer)
-     ((equal p "nil") nil)
-     ((equal p "t") "LOGBOOK")
-     (t p))))
+    (cond ((equal p "nil") nil)
+         ((equal p "t") "LOGBOOK")
+         ((stringp p) p)
+         (p "LOGBOOK")
+         ((stringp org-log-into-drawer) org-log-into-drawer)
+         (org-log-into-drawer "LOGBOOK"))))
 
 (defcustom org-log-state-notes-insert-after-drawers nil
   "Non-nil means insert state change notes after any drawers in entry.
@@ -2804,7 +3130,7 @@ property to one or more of these keywords."
 
 
 (defgroup org-priorities nil
-  "Priorities in Org-mode."
+  "Priorities in Org mode."
   :tag "Org Priorities"
   :group 'org-todo)
 
@@ -2862,24 +3188,13 @@ as an argument and return the numeric priority."
          (function)))
 
 (defgroup org-time nil
-  "Options concerning time stamps and deadlines in Org-mode."
+  "Options concerning time stamps and deadlines in Org mode."
   :tag "Org Time"
   :group 'org)
 
-(defcustom org-insert-labeled-timestamps-at-point nil
-  "Non-nil means SCHEDULED and DEADLINE timestamps are inserted at point.
-When nil, these labeled time stamps are forces into the second line of an
-entry, just after the headline.  When scheduling from the global TODO list,
-the time stamp will always be forced into the second line."
-  :group 'org-time
-  :type 'boolean)
-
-(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
-  "Formats for `format-time-string' which are used for time stamps.
-It is not recommended to change this constant.")
-
 (defcustom org-time-stamp-rounding-minutes '(0 5)
   "Number of minutes to round time stamps to.
+\\<org-mode-map>\
 These are two values, the first applies when first creating a time stamp.
 The second applies when changing it with the commands `S-up' and `S-down'.
 When changing the time stamp, this means that it will change in steps
@@ -2889,14 +3204,15 @@ When a setting is 0 or 1, insert the time unmodified.  
Useful rounding
 numbers should be factors of 60, so for example 5, 10, 15.
 
 When this is larger than 1, you can still force an exact time stamp by using
-a double prefix argument to a time stamp command like `C-c .' or `C-c !',
+a double prefix argument to a time stamp command like \
+`\\[org-time-stamp]' or `\\[org-time-stamp-inactive],
 and by using a prefix arg to `S-up/down' to specify the exact number
 of minutes to shift."
   :group 'org-time
-  :get #'(lambda (var) ; Make sure both elements are there
-          (if (integerp (default-value var))
-              (list (default-value var) 5)
-            (default-value var)))
+  :get (lambda (var) ; Make sure both elements are there
+        (if (integerp (default-value var))
+            (list (default-value var) 5)
+          (default-value var)))
   :type '(list
          (integer :tag "when inserting times")
          (integer :tag "when modifying times")))
@@ -3013,7 +3329,7 @@ in minutes (even for durations longer than an hour)."
                             (const t)))))
 
 (defcustom org-time-clocksum-use-fractional nil
-  "When non-nil, \\[org-clock-display] uses fractional times.
+  "When non-nil, `\\[org-clock-display]' uses fractional times.
 See `org-time-clocksum-format' for more on time clock formats."
   :group 'org-time
   :group 'org-clock
@@ -3021,7 +3337,7 @@ See `org-time-clocksum-format' for more on time clock 
formats."
   :type 'boolean)
 
 (defcustom org-time-clocksum-use-effort-durations nil
-  "When non-nil, \\[org-clock-display] uses effort durations.
+  "When non-nil, `\\[org-clock-display]' uses effort durations.
 E.g. by default, one day is considered to be a 8 hours effort,
 so a task that has been clocked for 16 hours will be displayed
 as during 2 days in the clock display or in the clocktable.
@@ -3052,9 +3368,9 @@ is used."
   :group 'org-time
   :type '(choice (string :tag "Format string")
                 (set (group :inline t (const :tag "Years" :years)
-                           (string :tag "Format string"))
+                            (string :tag "Format string"))
                      (group :inline t (const :tag "Months" :months)
-                           (string :tag "Format string"))
+                            (string :tag "Format string"))
                      (group :inline t (const :tag "Weeks" :weeks)
                             (string :tag "Format string"))
                      (group :inline t (const :tag "Days" :days)
@@ -3097,8 +3413,8 @@ This affects the following situations:
    For example, if it is April and you enter \"feb 2\", this will be read
    as Feb 2, *next* year.  \"May 5\", however, will be this year.
 2. The user gives a day, but no month.
-   For example, if today is the 15th, and you enter \"3\", Org-mode will
-   read this as the third of *next* month.  However, if you enter \"17\",
+   For example, if today is the 15th, and you enter \"3\", Org will read
+   this as the third of *next* month.  However, if you enter \"17\",
    it will be considered as *this* month.
 
 If you set this variable to the symbol `time', then also the following
@@ -3176,22 +3492,9 @@ In the calendar, the date can be selected with mouse-1.  
However, the
 minibuffer will also be active, and you can simply enter the date as well.
 When nil, only the minibuffer will be available."
   :group 'org-time
-  :type 'boolean)
-(org-defvaralias 'org-popup-calendar-for-date-prompt
-  'org-read-date-popup-calendar)
-
-(make-obsolete-variable
- 'org-read-date-minibuffer-setup-hook
- "Set `org-read-date-minibuffer-local-map' instead." "24.4")
-(defcustom org-read-date-minibuffer-setup-hook nil
-  "Hook to be used to set up keys for the date/time interface.
-Add key definitions to `minibuffer-local-map', which will be a
-temporary copy.
-
-WARNING: This option is obsolete, you should use
-`org-read-date-minibuffer-local-map' to set up keys."
-  :group 'org-time
-  :type 'hook)
+  :type 'boolean)
+(defvaralias 'org-popup-calendar-for-date-prompt
+  'org-read-date-popup-calendar)
 
 (defcustom org-extend-today-until 0
   "The hour when your day really ends.  Must be an integer.
@@ -3240,52 +3543,76 @@ moved to the new date."
   :type 'boolean)
 
 (defgroup org-tags nil
-  "Options concerning tags in Org-mode."
+  "Options concerning tags in Org mode."
   :tag "Org Tags"
   :group 'org)
 
 (defcustom org-tag-alist nil
-  "List of tags allowed in Org-mode files.
-When this list is nil, Org-mode will base TAG input on what is already in the
-buffer.
-The value of this variable is an alist, the car of each entry must be a
-keyword as a string, the cdr may be a character that is used to select
-that tag through the fast-tag-selection interface.
-See the manual for details."
+  "Default tags available in Org files.
+
+The value of this variable is an alist.  Associations either:
+
+  (TAG)
+  (TAG . SELECT)
+  (SPECIAL)
+
+where TAG is a tag as a string, SELECT is character, used to
+select that tag through the fast tag selection interface, and
+SPECIAL is one of the following keywords: `:startgroup',
+`:startgrouptag', `:grouptags', `:engroup', `:endgrouptag' or
+`:newline'.  These keywords are used to define a hierarchy of
+tags.  See manual for details.
+
+When this variable is nil, Org mode bases tag input on what is
+already in the buffer.  The value can be overridden locally by
+using a TAGS keyword, e.g.,
+
+  #+TAGS: tag1 tag2
+
+See also `org-tag-persistent-alist' to sidestep this behavior."
   :group 'org-tags
   :type '(repeat
          (choice
           (cons   (string    :tag "Tag name")
                   (character :tag "Access char"))
-          (list :tag "Start radio group"
-                (const :startgroup)
-                (option (string :tag "Group description")))
-          (list :tag "Group tags delimiter"
-                (const :grouptags))
-          (list :tag "End radio group"
-                (const :endgroup)
-                (option (string :tag "Group description")))
+          (const :tag "Start radio group" (:startgroup))
+          (const :tag "Start tag group, non distinct" (:startgrouptag))
+          (const :tag "Group tags delimiter" (:grouptags))
+          (const :tag "End radio group" (:endgroup))
+          (const :tag "End tag group, non distinct" (:endgrouptag))
           (const :tag "New line" (:newline)))))
 
 (defcustom org-tag-persistent-alist nil
-  "List of tags that will always appear in all Org-mode files.
-This is in addition to any in buffer settings or customizations
-of `org-tag-alist'.
-When this list is nil, Org-mode will base TAG input on `org-tag-alist'.
-The value of this variable is an alist, the car of each entry must be a
-keyword as a string, the cdr may be a character that is used to select
-that tag through the fast-tag-selection interface.
-See the manual for details.
-To disable these tags on a per-file basis, insert anywhere in the file:
-   #+STARTUP: noptag"
+  "Tags always available in Org files.
+
+The value of this variable is an alist.  Associations either:
+
+  (TAG)
+  (TAG . SELECT)
+  (SPECIAL)
+
+where TAG is a tag as a string, SELECT is a character, used to
+select that tag through the fast tag selection interface, and
+SPECIAL is one of the following keywords: `:startgroup',
+`:startgrouptag', `:grouptags', `:engroup', `:endgrouptag' or
+`:newline'.  These keywords are used to define a hierarchy of
+tags.  See manual for details.
+
+Unlike to `org-tag-alist', tags defined in this variable do not
+depend on a local TAGS keyword.  Instead, to disable these tags
+on a per-file basis, insert anywhere in the file:
+
+  #+STARTUP: noptag"
   :group 'org-tags
   :type '(repeat
          (choice
-          (cons   (string    :tag "Tag name")
-                  (character :tag "Access char"))
+          (cons (string    :tag "Tag name")
+                (character :tag "Access char"))
           (const :tag "Start radio group" (:startgroup))
+          (const :tag "Start tag group, non distinct" (:startgrouptag))
           (const :tag "Group tags delimiter" (:grouptags))
           (const :tag "End radio group" (:endgroup))
+          (const :tag "End tag group, non distinct" (:endgrouptag))
           (const :tag "New line" (:newline)))))
 
 (defcustom org-complete-tags-always-offer-all-agenda-tags nil
@@ -3296,9 +3623,7 @@ tags in that file can be created dynamically (there are 
none).
 
   (add-hook \\='org-capture-mode-hook
             (lambda ()
-              (set (make-local-variable
-                    \\='org-complete-tags-always-offer-all-agenda-tags)
-                   t)))"
+              (setq-local org-complete-tags-always-offer-all-agenda-tags t)))"
   :group 'org-tags
   :version "24.1"
   :type 'boolean)
@@ -3340,7 +3665,7 @@ displaying the tags menu is not even shown, until you 
press C-c again."
   "Non-nil means fast tags selection interface will also offer TODO states.
 This is an undocumented feature, you should not rely on it.")
 
-(defcustom org-tags-column (if (featurep 'xemacs) -76 -77)
+(defcustom org-tags-column -77
   "The column to which tags should be indented in a headline.
 If this number is positive, it specifies the column.  If it is negative,
 it means that the tags should be flushright to that column.  For example,
@@ -3437,7 +3762,7 @@ is better to limit inheritance to certain tags using the 
variables
   "Hook that is run after the tags in a line have changed.")
 
 (defgroup org-properties nil
-  "Options concerning properties in Org-mode."
+  "Options concerning properties in Org mode."
   :tag "Org Properties"
   :group 'org)
 
@@ -3504,14 +3829,14 @@ in this variable)."
          (regexp :tag "Properties matched by regexp")))
 
 (defun org-property-inherit-p (property)
-  "Check if PROPERTY is one that should be inherited."
+  "Return a non-nil value if PROPERTY should be inherited."
   (cond
    ((eq org-use-property-inheritance t) t)
    ((not org-use-property-inheritance) nil)
    ((stringp org-use-property-inheritance)
     (string-match org-use-property-inheritance property))
    ((listp org-use-property-inheritance)
-    (member property org-use-property-inheritance))
+    (member-ignore-case property org-use-property-inheritance))
    (t (error "Invalid setting of `org-use-property-inheritance'"))))
 
 (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS"
@@ -3532,26 +3857,6 @@ ellipses string, only part of the ellipses string will 
be shown."
   :group 'org-properties
   :type 'string)
 
-(defcustom org-columns-modify-value-for-display-function nil
-  "Function that modifies values for display in column view.
-For example, it can be used to cut out a certain part from a time stamp.
-The function must take 2 arguments:
-
-column-title    The title of the column (*not* the property name)
-value           The value that should be modified.
-
-The function should return the value that should be displayed,
-or nil if the normal value should be used."
-  :group 'org-properties
-  :type '(choice (const nil) (function)))
-
-(defcustom org-effort-property "Effort"
-  "The property that is being used to keep track of effort estimates.
-Effort estimates given in this property need to have the format H:MM."
-  :group 'org-properties
-  :group 'org-progress
-  :type '(string :tag "Property"))
-
 (defconst org-global-properties-fixed
   '(("VISIBILITY_ALL" . "folded children content all")
     ("CLOCK_MODELINE_TOTAL_ALL" . "current today repeat all auto"))
@@ -3582,18 +3887,17 @@ You can set buffer-local values for the same purpose in 
the variable
          (cons (string :tag "Property")
                (string :tag "Value"))))
 
-(defvar org-file-properties nil
+(defvar-local org-file-properties nil
   "List of property/value pairs that can be inherited by any entry.
 Valid for the current buffer.
 This variable is populated from #+PROPERTY lines.")
-(make-variable-buffer-local 'org-file-properties)
 
 (defgroup org-agenda nil
-  "Options concerning agenda views in Org-mode."
+  "Options concerning agenda views in Org mode."
   :tag "Org Agenda"
   :group 'org)
 
-(defvar org-category nil
+(defvar-local org-category nil
   "Variable used by org files to set a category for agenda display.
 Such files should use a file variable to set it, for example
 
@@ -3605,22 +3909,22 @@ or contain a special line
 
 If the file does not specify a category, then file's base name
 is used instead.")
-(make-variable-buffer-local 'org-category)
-(put 'org-category 'safe-local-variable #'(lambda (x) (or (symbolp x) (stringp 
x))))
+(put 'org-category 'safe-local-variable (lambda (x) (or (symbolp x) (stringp 
x))))
 
 (defcustom org-agenda-files nil
   "The files to be used for agenda display.
-Entries may be added to this list with \\[org-agenda-file-to-front] and 
removed with
-\\[org-remove-file].  You can also use customize to edit the list.
 
-If an entry is a directory, all files in that directory that are matched by
-`org-agenda-file-regexp' will be part of the file list.
+If an entry is a directory, all files in that directory that are matched
+by `org-agenda-file-regexp' will be part of the file list.
 
 If the value of the variable is not a list but a single file name, then
-the list of agenda files is actually stored and maintained in that file, one
-agenda file per line.  In this file paths can be given relative to
+the list of agenda files is actually stored and maintained in that file,
+one agenda file per line.  In this file paths can be given relative to
 `org-directory'.  Tilde expansion and environment variable substitution
-are also made."
+are also made.
+
+Entries may be added to this list with `\\[org-agenda-file-to-front]'
+and removed with `\\[org-remove-file]'."
   :group 'org-agenda
   :type '(choice
          (repeat :tag "List of files and directories" file)
@@ -3637,7 +3941,8 @@ regular expression will be included."
 (defcustom org-agenda-text-search-extra-files nil
   "List of extra files to be searched by text search commands.
 These files will be searched in addition to the agenda files by the
-commands `org-search-view' (`C-c a s') and `org-occur-in-agenda-files'.
+commands `org-search-view' (`\\[org-agenda] s') \
+and `org-occur-in-agenda-files'.
 Note that these files will only be searched for text search commands,
 not for the other agenda views like todo lists, tag searches or the weekly
 agenda.  This variable is intended to list notes and possibly archive files
@@ -3650,7 +3955,7 @@ scope."
              (const :tag "Agenda Archives" agenda-archives)
              (repeat :inline t (file))))
 
-(org-defvaralias 'org-agenda-multi-occur-extra-files
+(defvaralias 'org-agenda-multi-occur-extra-files
   'org-agenda-text-search-extra-files)
 
 (defcustom org-agenda-skip-unavailable-files nil
@@ -3670,7 +3975,7 @@ forth between agenda and calendar."
 (defcustom org-calendar-insert-diary-entry-key [?i]
   "The key to be installed in `calendar-mode-map' for adding diary entries.
 This option is irrelevant until `org-agenda-diary-file' has been configured
-to point to an Org-mode file.  When that is the case, the command
+to point to an Org file.  When that is the case, the command
 `org-agenda-diary-entry' will be bound to the key given here, by default
 `i'.  In the calendar, `i' normally adds entries to `diary-file'.  So
 if you want to continue doing this, you need to change this to a different
@@ -3700,7 +4005,7 @@ points to a file, `org-agenda-diary-entry' will be used 
instead."
                     'org-agenda-diary-entry))))))
 
 (defgroup org-latex nil
-  "Options for embedding LaTeX code into Org-mode."
+  "Options for embedding LaTeX code into Org mode."
   :tag "Org LaTeX"
   :group 'org)
 
@@ -3755,39 +4060,131 @@ Replace format-specifiers in the command as noted 
below and use
 `shell-command' to convert LaTeX to MathML.
 %j:     Executable file in fully expanded form as specified by
         `org-latex-to-mathml-jar-file'.
-%I:     Input LaTeX file in fully expanded form
-%o:     Output MathML file
+%I:     Input LaTeX file in fully expanded form.
+%i:     The latex fragment to be converted.
+%o:     Output MathML file.
+
 This command is used by `org-create-math-formula'.
 
-When using MathToWeb as the converter, set this to
-\"java -jar %j -unicode -force -df %o %I\"."
+When using MathToWeb as the converter, set this option to
+\"java -jar %j -unicode -force -df %o %I\".
+
+When using LaTeXML set this option to
+\"latexmlmath \"%i\" --presentationmathml=%o\"."
   :group 'org-latex
   :version "24.1"
   :type '(choice
          (const :tag "None" nil)
          (string :tag "\nShell command")))
 
-(defcustom org-latex-create-formula-image-program 'dvipng
-  "Program to convert LaTeX fragments with.
-
-dvipng          Process the LaTeX fragments to dvi file, then convert
-                dvi files to png files using dvipng.
-                This will also include processing of non-math environments.
-imagemagick     Convert the LaTeX fragments to pdf files and use imagemagick
-                to convert pdf files to png files"
+(defcustom org-preview-latex-default-process 'dvipng
+  "The default process to convert LaTeX fragments to image files.
+All available processes and theirs documents can be found in
+`org-preview-latex-process-alist', which see."
   :group 'org-latex
-  :version "24.1"
-  :type '(choice
-         (const :tag "dvipng" dvipng)
-         (const :tag "imagemagick" imagemagick)))
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type 'symbol)
+
+(defcustom org-preview-latex-process-alist
+  '((dvipng
+     :programs ("latex" "dvipng")
+     :description "dvi > png"
+     :message "you need to install the programs: latex and dvipng."
+     :image-input-type "dvi"
+     :image-output-type "png"
+     :image-size-adjust (1.0 . 1.0)
+     :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
+     :image-converter ("dvipng -fg %F -bg %B -D %D -T tight -o %O %f"))
+    (dvisvgm
+     :programs ("latex" "dvisvgm")
+     :description "dvi > svg"
+     :message "you need to install the programs: latex and dvisvgm."
+     :use-xcolor t
+     :image-input-type "dvi"
+     :image-output-type "svg"
+     :image-size-adjust (1.7 . 1.5)
+     :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
+     :image-converter ("dvisvgm %f -n -b min -c %S -o %O"))
+    (imagemagick
+     :programs ("latex" "convert")
+     :description "pdf > png"
+     :message "you need to install the programs: latex and imagemagick."
+     :use-xcolor t
+     :image-input-type "pdf"
+     :image-output-type "png"
+     :image-size-adjust (1.0 . 1.0)
+     :latex-compiler ("pdflatex -interaction nonstopmode -output-directory %o 
%f")
+     :image-converter
+     ("convert -density %D -trim -antialias %f -quality 100 %O")))
+  "Definitions of external processes for LaTeX previewing.
+Org mode can use some external commands to generate TeX snippet's images for
+previewing or inserting into HTML files, e.g., \"dvipng\".  This variable tells
+`org-create-formula-image' how to call them.
+
+The value is an alist with the pattern (NAME . PROPERTIES).  NAME is a symbol.
+PROPERTIES accepts the following attributes:
+
+  :programs           list of strings, required programs.
+  :description        string, describe the process.
+  :message            string, message it when required programs cannot be 
found.
+  :image-input-type   string, input file type of image converter (e.g., 
\"dvi\").
+  :image-output-type  string, output file type of image converter (e.g., 
\"png\").
+  :use-xcolor         boolean, when non-nil, LaTeX \"xcolor\" macro is used to
+                      deal with background and foreground color of image.
+                      Otherwise, dvipng style background and foregroud color
+                      format are generated.  You may then refer to them in
+                      command options with \"%F\" and \"%B\".
+  :image-size-adjust  cons of numbers, the car element is used to adjust LaTeX
+                      image size showed in buffer and the cdr element is for
+                      HTML file.  This option is only useful for process
+                      developers, users should use variable
+                      `org-format-latex-options' instead.
+  :post-clean         list of strings, files matched are to be cleaned up once
+                      the image is generated.  When nil, the files with 
\".dvi\",
+                      \".xdv\", \".pdf\", \".tex\", \".aux\", \".log\", 
\".svg\",
+                      \".png\", \".jpg\", \".jpeg\" or \".out\" extension will
+                      be cleaned up.
+  :latex-header       list of strings, the LaTeX header of the snippet file.
+                      When nil, the fallback value is used instead, which is
+                      controlled by `org-format-latex-header',
+                      `org-latex-default-packages-alist' and
+                      `org-latex-packages-alist', which see.
+  :latex-compiler     list of LaTeX commands, as strings.  Each of them is 
given
+                      to the shell.  Place-holders \"%t\", \"%b\" and \"%o\" 
are
+                      replaced with values defined below.
+  :image-converter    list of image converter commands strings.  Each of them 
is
+                      given to the shell and supports any of the following
+                      place-holders defined below.
+
+Place-holders used by `:image-converter' and `:latex-compiler':
+
+  %f    input file name
+  %b    base name of input file
+  %o    base directory of input file
+  %O    absolute output file name
+
+Place-holders only used by `:image-converter':
+
+  %F    foreground of image
+  %B    background of image
+  %D    dpi, which is used to adjust image size by some processing commands.
+  %S    the image size scale ratio, which is used to adjust image size by some
+        processing commands."
+  :group 'org-latex
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type '(alist :tag "LaTeX to image backends"
+               :value-type (plist)))
 
-(defcustom org-latex-preview-ltxpng-directory "ltxpng/"
+(defcustom org-preview-latex-image-directory "ltximg/"
   "Path to store latex preview images.
 A relative path here creates many directories relative to the
 processed org files paths.  An absolute path puts all preview
 images at the same place."
   :group 'org-latex
-  :version "24.3"
+  :version "26.1"
+  :package-version '(Org . "9.0")
   :type 'string)
 
 (defun org-format-latex-mathml-available-p ()
@@ -3805,8 +4202,8 @@ images at the same place."
 
 (defcustom org-format-latex-header "\\documentclass{article}
 \\usepackage[usenames]{color}
-[PACKAGES]
-[DEFAULT-PACKAGES]
+\[PACKAGES]
+\[DEFAULT-PACKAGES]
 \\pagestyle{empty}             % do not remove
 % The settings below are copied from fullpage.sty
 \\setlength{\\textwidth}{\\paperwidth}
@@ -3847,22 +4244,19 @@ header, or they will be appended."
          (default-value var)))
 
 (defcustom org-latex-default-packages-alist
-  '(("AUTO" "inputenc"  t)
-    ("T1"   "fontenc"   t)
-    (""     "fixltx2e"  nil)
+  '(("AUTO" "inputenc"  t ("pdflatex"))
+    ("T1"   "fontenc"   t ("pdflatex"))
     (""     "graphicx"  t)
+    (""     "grffile"   t)
     (""     "longtable" nil)
-    (""     "float"     nil)
     (""     "wrapfig"   nil)
     (""     "rotating"  nil)
     ("normalem" "ulem"  t)
     (""     "amsmath"   t)
     (""     "textcomp"  t)
-    (""     "marvosym"  t)
-    (""     "wasysym"   t)
     (""     "amssymb"   t)
-    (""     "hyperref"  nil)
-    "\\tolerance=1000")
+    (""     "capt-of"   nil)
+    (""     "hyperref"  nil))
   "Alist of default packages to be inserted in the header.
 
 Change this only if one of the packages here causes an
@@ -3872,16 +4266,17 @@ The packages in this list are needed by one part or 
another of
 Org mode to function properly:
 
 - inputenc, fontenc:  for basic font and character selection
-- fixltx2e: Important patches of LaTeX itself
 - graphicx: for including images
+- grffile: allow periods and spaces in graphics file names
 - longtable: For multipage tables
-- float, wrapfig: for figure placement
+- wrapfig: for figure placement
 - rotating: for sideways figures and tables
 - ulem: for underline and strike-through
 - amsmath: for subscript and superscript and math environments
-- textcomp, marvosymb, wasysym, amssymb: for various symbols used
+- textcomp, amssymb: for various symbols used
   for interpreting the entities in `org-entities'.  You can skip
   some of these packages if you don't use any of their symbols.
+- capt-of: for captions outside of floats
 - hyperref: for cross references
 
 Therefore you should not modify this variable unless you know
@@ -3890,20 +4285,24 @@ you might be loading some other package that conflicts 
with one
 of the default packages.  Each element is either a cell or
 a string.
 
-A cell is of the format:
+A cell is of the format
 
-  ( \"options\" \"package\" SNIPPET-FLAG).
+  (\"options\" \"package\" SNIPPET-FLAG COMPILERS)
 
 If SNIPPET-FLAG is non-nil, the package also needs to be included
 when compiling LaTeX snippets into images for inclusion into
-non-LaTeX output.
+non-LaTeX output.  COMPILERS is a list of compilers that should
+include the package, see `org-latex-compiler'.  If the document
+compiler is not in the list, and the list is non-nil, the package
+will not be inserted in the final document.
 
 A string will be inserted as-is in the header of the document."
   :group 'org-latex
   :group 'org-export-latex
   :set 'org-set-packages-alist
   :get 'org-get-packages-alist
-  :version "24.1"
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(repeat
          (choice
           (list :tag "options/package pair"
@@ -3947,7 +4346,7 @@ Make sure that you only list packages here which:
           (string :tag "A line of LaTeX"))))
 
 (defgroup org-appearance nil
-  "Settings for Org-mode appearance."
+  "Settings for Org mode appearance."
   :tag "Org Appearance"
   :group 'org)
 
@@ -4038,6 +4437,11 @@ following symbols:
   :group 'org-appearance
   :type 'boolean)
 
+(defcustom org-hide-macro-markers nil
+  "Non-nil mean font-lock should hide the brackets marking macro calls."
+  :group 'org-appearance
+  :type 'boolean)
+
 (defcustom org-pretty-entities nil
   "Non-nil means show entities as UTF8 characters.
 When nil, the \\name form remains in the buffer."
@@ -4124,7 +4528,7 @@ After a match, the match groups contain these elements:
 ;; set this option proved cumbersome.  See this message/thread:
 ;; http://article.gmane.org/gmane.emacs.orgmode/68681
 (defvar org-emphasis-regexp-components
-  '(" \t('\"{" "- \t.,:!?;'\")}\\" " \t\r\n,\"'" "." 1)
+  '(" \t('\"{" "- \t.,:!?;'\")}\\[" " \t\r\n" "." 1)
   "Components used to build the regular expression for emphasis.
 This is a list with five entries.  Terminology:  In an emphasis string
 like \" *strong word* \", we call the initial space PREMATCH, the final
@@ -4142,17 +4546,17 @@ newline      The maximum number of newlines allowed in 
an emphasis exp.
 You need to reload Org or to restart Emacs after customizing this.")
 
 (defcustom org-emphasis-alist
-  `(("*" bold)
+  '(("*" bold)
     ("/" italic)
     ("_" underline)
     ("=" org-verbatim verbatim)
     ("~" org-code verbatim)
-    ("+" ,(if (featurep 'xemacs) 'org-table '(:strike-through t))))
+    ("+" (:strike-through t)))
   "Alist of characters and faces to emphasize text.
 Text starting and ending with a special character will be emphasized,
 for example *bold*, _underlined_ and /italic/.  This variable sets the
 marker characters and the face to be used by font-lock for highlighting
-in Org-mode Emacs buffers.
+in Org buffers.
 
 You need to reload Org or to restart Emacs after customizing this."
   :group 'org-appearance
@@ -4167,122 +4571,68 @@ You need to reload Org or to restart Emacs after 
customizing this."
            (plist :tag "Face property list"))
           (option (const verbatim)))))
 
-(defvar org-protecting-blocks
-  '("src" "example" "latex" "ascii" "html" "ditaa" "dot" "r" "R")
+(defvar org-protecting-blocks '("src" "example" "export")
   "Blocks that contain text that is quoted, i.e. not processed as Org syntax.
 This is needed for font-lock setup.")
 
-;;; Miscellaneous options
-
-(defgroup org-completion nil
-  "Completion in Org-mode."
-  :tag "Org Completion"
-  :group 'org)
-
-(defcustom org-completion-use-ido nil
-  "Non-nil means use ido completion wherever possible.
-Note that `ido-mode' must be active for this variable to be relevant.
-If you decide to turn this variable on, you might well want to turn off
-`org-outline-path-complete-in-steps'.
-See also `org-completion-use-iswitchb'."
-  :group 'org-completion
-  :type 'boolean)
-
-(defcustom org-completion-use-iswitchb nil
-  "Non-nil means use iswitchb completion wherever possible.
-Note that `iswitchb-mode' must be active for this variable to be relevant.
-If you decide to turn this variable on, you might well want to turn off
-`org-outline-path-complete-in-steps'.
-Note that this variable has only an effect if `org-completion-use-ido' is nil."
-  :group 'org-completion
-  :type 'boolean)
-
-(defcustom org-completion-fallback-command 'hippie-expand
-  "The expansion command called by \\[pcomplete] in normal context.
-Normal means, no org-mode-specific context."
-  :group 'org-completion
-  :type 'function)
-
 ;;; Functions and variables from their packages
 ;;  Declared here to avoid compiler warnings
-
-;; XEmacs only
-(defvar outline-mode-menu-heading)
-(defvar outline-mode-menu-show)
-(defvar outline-mode-menu-hide)
-(defvar zmacs-regions) ; XEmacs regions
-
-;; Emacs only
 (defvar mark-active)
 
 ;; Various packages
-(declare-function calendar-iso-to-absolute      "cal-iso"    (date))
-(declare-function calendar-forward-day          "cal-move"   (arg))
-(declare-function calendar-goto-date            "cal-move"   (date))
-(declare-function calendar-goto-today           "cal-move"   ())
-(declare-function calendar-iso-from-absolute    "cal-iso"    (date))
-(defvar calc-embedded-close-formula)
-(defvar calc-embedded-open-formula)
-(declare-function cdlatex-tab "ext:cdlatex" ())
+(declare-function calc-eval "calc" (str &optional separator &rest args))
+(declare-function calendar-forward-day "cal-move" (arg))
+(declare-function calendar-goto-date "cal-move" (date))
+(declare-function calendar-goto-today "cal-move" ())
+(declare-function calendar-iso-from-absolute "cal-iso" (date))
+(declare-function calendar-iso-to-absolute "cal-iso" (date))
 (declare-function cdlatex-compute-tables "ext:cdlatex" ())
-(declare-function dired-get-filename "dired" (&optional localp 
no-error-if-not-filep))
-(defvar font-lock-unfontify-region-function)
-(declare-function iswitchb-read-buffer "iswitchb"
-                  (prompt &optional
-                          default require-match _predicate start matches-set))
-(defvar iswitchb-temp-buflist)
-(declare-function org-gnus-follow-link "org-gnus" (&optional group article))
-(defvar org-agenda-tags-todo-honor-ignore-options)
-(declare-function org-agenda-skip "org-agenda" ())
-(declare-function
- org-agenda-format-item "org-agenda"
- (extra txt &optional level category tags dotime remove-re habitp))
-(declare-function org-agenda-new-marker "org-agenda" (&optional pos))
-(declare-function org-agenda-change-all-lines "org-agenda"
+(declare-function cdlatex-tab "ext:cdlatex" ())
+(declare-function dired-get-filename
+                 "dired"
+                 (&optional localp no-error-if-not-filep))
+(declare-function iswitchb-read-buffer
+                 "iswitchb"
+                 (prompt &optional
+                         default require-match _predicate start matches-set))
+(declare-function org-agenda-change-all-lines
+                 "org-agenda"
                  (newhead hdmarker &optional fixface just-this))
-(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional 
type))
+(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
+                 "org-agenda"
+                 (&optional end))
+(declare-function org-agenda-copy-local-variable "org-agenda" (var))
+(declare-function org-agenda-format-item
+                 "org-agenda"
+                 (extra txt &optional level category tags dotime
+                        remove-re habitp))
 (declare-function org-agenda-maybe-redo "org-agenda" ())
-(declare-function org-agenda-save-markers-for-cut-and-paste "org-agenda"
+(declare-function org-agenda-new-marker "org-agenda" (&optional pos))
+(declare-function org-agenda-save-markers-for-cut-and-paste
+                 "org-agenda"
                  (beg end))
-(declare-function org-agenda-copy-local-variable "org-agenda" (var))
-(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
-                 "org-agenda" (&optional end))
-(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
-(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
+(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional 
type))
+(declare-function org-agenda-skip "org-agenda" ())
+(declare-function org-attach-reveal "org-attach" (&optional if-exists))
+(declare-function org-gnus-follow-link "org-gnus" (&optional group article))
+(declare-function org-indent-mode "org-indent" (&optional arg))
 (declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
 (declare-function org-inlinetask-goto-end "org-inlinetask" ())
-(declare-function org-indent-mode "org-indent" (&optional arg))
-(declare-function parse-time-string "parse-time" (string))
-(declare-function org-attach-reveal "org-attach" (&optional if-exists))
+(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
+(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
 (declare-function orgtbl-send-table "org-table" (&optional maybe))
-(defvar remember-data-file)
-(defvar texmathp-why)
+(declare-function parse-time-string "parse-time" (string))
 (declare-function speedbar-line-directory "speedbar" (&optional depth))
-(declare-function table--at-cell-p "table" (position &optional object 
at-column))
-
-(defvar org-latex-regexps)
-
-;;; Autoload and prepare some org modules
-
-;; Some table stuff that needs to be defined here, because it is used
-;; by the functions setting up org-mode or checking for table context.
-
-(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
-  "Detect an org-type or table-type table.")
-(defconst org-table-line-regexp "^[ \t]*|"
-  "Detect an org-type table line.")
-(defconst org-table-dataline-regexp "^[ \t]*|[^-]"
-  "Detect an org-type table line.")
-(defconst org-table-hline-regexp "^[ \t]*|-"
-  "Detect an org-type table hline.")
-(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
-  "Detect a table-type table hline.")
-(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
-  "Detect the first line outside a table when searching from within it.
-This works for both table types.")
 
-(defconst org-TBLFM-regexp "^[ \t]*#\\+TBLFM: "
-  "Detect a #+TBLFM line.")
+(defvar align-mode-rules-list)
+(defvar calc-embedded-close-formula)
+(defvar calc-embedded-open-formula)
+(defvar calc-embedded-open-mode)
+(defvar font-lock-unfontify-region-function)
+(defvar iswitchb-temp-buflist)
+(defvar org-agenda-tags-todo-honor-ignore-options)
+(defvar remember-data-file)
+(defvar texmathp-why)
 
 ;;;###autoload
 (defun turn-on-orgtbl ()
@@ -4291,75 +4641,50 @@ This works for both table types.")
   (orgtbl-mode 1))
 
 (defun org-at-table-p (&optional table-type)
-  "Return t if the cursor is inside an org-type table.
-If TABLE-TYPE is non-nil, also check for table.el-type tables."
-  (if org-enable-table-editor
-      (save-excursion
-       (beginning-of-line 1)
-       (looking-at (if table-type org-table-any-line-regexp
-                     org-table-line-regexp)))
-    nil))
-(defsubst org-table-p () (org-at-table-p))
+  "Non-nil if the cursor is inside an Org table.
+If TABLE-TYPE is non-nil, also check for table.el-type tables.
+If `org-enable-table-editor' is nil, return nil unconditionally."
+  (and
+   org-enable-table-editor
+   (save-excursion
+     (beginning-of-line)
+     (looking-at-p (if table-type "[ \t]*[|+]" "[ \t]*|")))
+   (or (not (derived-mode-p 'org-mode))
+       (let ((e (org-element-lineage (org-element-at-point) '(table) t)))
+        (and e (or table-type (eq (org-element-property :type e) 'org)))))))
 
 (defun org-at-table.el-p ()
-  "Return t if and only if we are at a table.el table."
-  (and (org-at-table-p 'any)
-       (save-excursion
-        (goto-char (org-table-begin 'any))
-        (looking-at org-table1-hline-regexp))))
-
-(defun org-table-recognize-table.el ()
-  "If there is a table.el table nearby, recognize it and move into it."
-  (if org-table-tab-recognizes-table.el
-      (if (org-at-table.el-p)
-         (progn
-           (beginning-of-line 1)
-           (if (looking-at org-table-dataline-regexp)
-               nil
-             (if (looking-at org-table1-hline-regexp)
-                 (progn
-                   (beginning-of-line 2)
-                   (if (looking-at org-table-any-border-regexp)
-                       (beginning-of-line -1)))))
-           (if (re-search-forward "|" (org-table-end t) t)
-               (progn
-                 (require 'table)
-                 (if (table--at-cell-p (point))
-                     t
-                   (message "recognizing table.el table...")
-                   (table-recognize-table)
-                   (message "recognizing table.el table...done")))
-             (error "This should not happen"))
-           t)
-       nil)
-    nil))
+  "Non-nil when point is at a table.el table."
+  (and (save-excursion (beginning-of-line) (looking-at "[ \t]*[|+]"))
+       (let ((element (org-element-at-point)))
+        (and (eq (org-element-type element) 'table)
+             (eq (org-element-property :type element) 'table.el)))))
 
 (defun org-at-table-hline-p ()
-  "Return t if the cursor is inside a hline in a table."
-  (if org-enable-table-editor
-      (save-excursion
-       (beginning-of-line 1)
-       (looking-at org-table-hline-regexp))
-    nil))
+  "Non-nil when point is inside a hline in a table.
+Assume point is already in a table.  If `org-enable-table-editor'
+is nil, return nil unconditionally."
+  (and org-enable-table-editor
+       (save-excursion
+        (beginning-of-line)
+        (looking-at org-table-hline-regexp))))
 
 (defun org-table-map-tables (function &optional quietly)
   "Apply FUNCTION to the start of all tables in the buffer."
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (while (re-search-forward org-table-any-line-regexp nil t)
-       (unless quietly
-         (message "Mapping tables: %d%%"
-                  (floor (* 100.0 (point)) (buffer-size))))
-       (beginning-of-line 1)
-       (when (and (looking-at org-table-line-regexp)
-                  ;; Exclude tables in src/example/verbatim/clocktable blocks
-                  (not (org-in-block-p '("src" "example" "verbatim" 
"clocktable"))))
-         (save-excursion (funcall function))
-         (or (looking-at org-table-line-regexp)
-             (forward-char 1)))
-       (re-search-forward org-table-any-border-regexp nil 1))))
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (while (re-search-forward org-table-any-line-regexp nil t)
+     (unless quietly
+       (message "Mapping tables: %d%%"
+               (floor (* 100.0 (point)) (buffer-size))))
+     (beginning-of-line 1)
+     (when (and (looking-at org-table-line-regexp)
+               ;; Exclude tables in src/example/verbatim/clocktable blocks
+               (not (org-in-block-p '("src" "example" "verbatim" 
"clocktable"))))
+       (save-excursion (funcall function))
+       (or (looking-at org-table-line-regexp)
+          (forward-char 1)))
+     (re-search-forward org-table-any-border-regexp nil 1)))
   (unless quietly (message "Mapping tables: done")))
 
 (declare-function org-clock-save-markers-for-cut-and-paste "org-clock" (beg 
end))
@@ -4368,12 +4693,12 @@ If TABLE-TYPE is non-nil, also check for table.el-type 
tables."
                  (&optional also-non-dangling-p prompt last-valid))
 
 (defun org-at-TBLFM-p (&optional pos)
-  "Return t when point (or POS) is in #+TBLFM line."
+  "Non-nil when point (or POS) is in #+TBLFM line."
   (save-excursion
-    (let ((pos pos)))
     (goto-char (or pos (point)))
-    (beginning-of-line 1)
-    (looking-at org-TBLFM-regexp)))
+    (beginning-of-line)
+    (and (let ((case-fold-search t)) (looking-at org-TBLFM-regexp))
+        (eq (org-element-type (org-element-at-point)) 'table))))
 
 (defvar org-clock-start-time)
 (defvar org-clock-marker (make-marker)
@@ -4410,7 +4735,7 @@ If yes, offer to stop it and to save the buffer with the 
changes."
   (add-hook 'kill-emacs-hook 'org-clock-save))
 
 (defgroup org-archive nil
-  "Options concerning archiving in Org-mode."
+  "Options concerning archiving in Org mode."
   :tag "Org Archive"
   :group 'org-structure)
 
@@ -4425,7 +4750,7 @@ When the filename is omitted, archiving happens in the 
same file.
 %s in the filename will be replaced by the current file
 name (without the directory part).  Archiving to a different file
 is useful to keep archived entries from contributing to the
-Org-mode Agenda.
+Org Agenda.
 
 The archived entries will be filed as subtrees of the specified
 headline.  When the headline is omitted, the subtrees are simply
@@ -4473,16 +4798,6 @@ the hierarchy, it will be used."
   :group 'org-archive
   :type 'string)
 
-(defcustom org-archive-tag "ARCHIVE"
-  "The tag that marks a subtree as archived.
-An archived subtree does not open during visibility cycling, and does
-not contribute to the agenda listings.
-After changing this, font-lock must be restarted in the relevant buffers to
-get the proper fontification."
-  :group 'org-archive
-  :group 'org-keywords
-  :type 'string)
-
 (defcustom org-agenda-skip-archived-trees t
   "Non-nil means the agenda will skip any items located in archived trees.
 An archived tree is a tree marked with the tag ARCHIVE.  The use of this
@@ -4515,24 +4830,25 @@ collapsed state."
   :group 'org-sparse-trees
   :type 'boolean)
 
-(defcustom org-sparse-tree-default-date-type 'scheduled-or-deadline
+(defcustom org-sparse-tree-default-date-type nil
   "The default date type when building a sparse tree.
 When this is nil, a date is a scheduled or a deadline timestamp.
 Otherwise, these types are allowed:
 
         all: all timestamps
      active: only active timestamps (<...>)
-   inactive: only inactive timestamps (<...)
+   inactive: only inactive timestamps ([...])
   scheduled: only scheduled timestamps
    deadline: only deadline timestamps"
-  :type '(choice (const :tag "Scheduled or deadline" scheduled-or-deadline)
+  :type '(choice (const :tag "Scheduled or deadline" nil)
                 (const :tag "All timestamps" all)
                 (const :tag "Only active timestamps" active)
                 (const :tag "Only inactive timestamps" inactive)
                 (const :tag "Only scheduled timestamps" scheduled)
                 (const :tag "Only deadline timestamps" deadline)
                 (const :tag "Only closed timestamps" closed))
-  :version "24.3"
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :group 'org-sparse-trees)
 
 (defun org-cycle-hide-archived-subtrees (state)
@@ -4545,9 +4861,10 @@ Otherwise, these types are allowed:
              (end (if globalp (point-max) (org-end-of-subtree t))))
        (org-hide-archived-subtrees beg end)
        (goto-char beg)
-       (if (looking-at (concat ".*:" org-archive-tag ":"))
-           (message "%s" (substitute-command-keys
-                          "Subtree is archived and stays closed.  Use 
\\[org-force-cycle-archived] to cycle it anyway.")))))))
+       (when (looking-at-p (concat ".*:" org-archive-tag ":"))
+         (message "%s" (substitute-command-keys
+                        "Subtree is archived and stays closed.  Use \
+`\\[org-force-cycle-archived]' to cycle it anyway.")))))))
 
 (defun org-force-cycle-archived ()
   "Cycle subtree even if it is archived."
@@ -4558,13 +4875,16 @@ Otherwise, these types are allowed:
 
 (defun org-hide-archived-subtrees (beg end)
   "Re-hide all archived subtrees after a visibility state change."
-  (save-excursion
-    (let* ((re (concat ":" org-archive-tag ":")))
-      (goto-char beg)
-      (while (re-search-forward re end t)
-       (when (org-at-heading-p)
-         (org-flag-subtree t)
-         (org-end-of-subtree t))))))
+  (org-with-wide-buffer
+   (let ((case-fold-search nil)
+        (re (concat org-outline-regexp-bol ".*:" org-archive-tag ":")))
+     (goto-char beg)
+     ;; Include headline point is currently on.
+     (beginning-of-line)
+     (while (and (< (point) end) (re-search-forward re end t))
+       (when (member org-archive-tag (org-get-tags))
+        (org-flag-subtree t)
+        (org-end-of-subtree t))))))
 
 (declare-function outline-end-of-heading "outline" ())
 (declare-function outline-flag-region "outline" (from to flag))
@@ -4580,7 +4900,6 @@ Otherwise, these types are allowed:
 
 ;; Declare Column View Code
 
-(declare-function org-columns-number-to-string "org-colview" (n fmt &optional 
printf))
 (declare-function org-columns-get-format-and-top-level "org-colview" ())
 (declare-function org-columns-compute "org-colview" (property))
 
@@ -4593,79 +4912,47 @@ Otherwise, these types are allowed:
 
 ;;; Variables for pre-computed regular expressions, all buffer local
 
-(defvar org-drawer-regexp "^[ \t]*:PROPERTIES:[ \t]*$"
-  "Matches first line of a hidden block.")
-(make-variable-buffer-local 'org-drawer-regexp)
-(defvar org-todo-regexp nil
-  "Matches any of the TODO state keywords.")
-(make-variable-buffer-local 'org-todo-regexp)
-(defvar org-not-done-regexp nil
-  "Matches any of the TODO state keywords except the last one.")
-(make-variable-buffer-local 'org-not-done-regexp)
-(defvar org-not-done-heading-regexp nil
-  "Matches a TODO headline that is not done.")
-(make-variable-buffer-local 'org-not-done-regexp)
-(defvar org-todo-line-regexp nil
-  "Matches a headline and puts TODO state into group 2 if present.")
-(make-variable-buffer-local 'org-todo-line-regexp)
-(defvar org-complex-heading-regexp nil
+(defvar-local org-todo-regexp nil
+  "Matches any of the TODO state keywords.
+Since TODO keywords are case-sensitive, `case-fold-search' is
+expected to be bound to nil when matching against this regexp.")
+
+(defvar-local org-not-done-regexp nil
+  "Matches any of the TODO state keywords except the last one.
+Since TODO keywords are case-sensitive, `case-fold-search' is
+expected to be bound to nil when matching against this regexp.")
+
+(defvar-local org-not-done-heading-regexp nil
+  "Matches a TODO headline that is not done.
+Since TODO keywords are case-sensitive, `case-fold-search' is
+expected to be bound to nil when matching against this regexp.")
+
+(defvar-local org-todo-line-regexp nil
+  "Matches a headline and puts TODO state into group 2 if present.
+Since TODO keywords are case-sensitive, `case-fold-search' is
+expected to be bound to nil when matching against this regexp.")
+
+(defvar-local org-complex-heading-regexp nil
   "Matches a headline and puts everything into groups:
-group 1: the stars
-group 2: The todo keyword, maybe
+
+group 1: Stars
+group 2: The TODO keyword, maybe
 group 3: Priority cookie
 group 4: True headline
-group 5: Tags")
-(make-variable-buffer-local 'org-complex-heading-regexp)
-(defvar org-complex-heading-regexp-format nil
+group 5: Tags
+
+Since TODO keywords are case-sensitive, `case-fold-search' is
+expected to be bound to nil when matching against this regexp.")
+
+(defvar-local org-complex-heading-regexp-format nil
   "Printf format to make regexp to match an exact headline.
 This regexp will match the headline of any node which has the
 exact headline text that is put into the format, but may have any
 TODO state, priority and tags.")
-(make-variable-buffer-local 'org-complex-heading-regexp-format)
-(defvar org-todo-line-tags-regexp nil
+
+(defvar-local org-todo-line-tags-regexp nil
   "Matches a headline and puts TODO state into group 2 if present.
 Also put tags into group 4 if tags are present.")
-(make-variable-buffer-local 'org-todo-line-tags-regexp)
-(defvar org-ds-keyword-length 12
-  "Maximum length of the DEADLINE and SCHEDULED keywords.")
-(make-variable-buffer-local 'org-ds-keyword-length)
-(defvar org-deadline-regexp nil
-  "Matches the DEADLINE keyword.")
-(make-variable-buffer-local 'org-deadline-regexp)
-(defvar org-deadline-time-regexp nil
-  "Matches the DEADLINE keyword together with a time stamp.")
-(make-variable-buffer-local 'org-deadline-time-regexp)
-(defvar org-deadline-time-hour-regexp nil
-  "Matches the DEADLINE keyword together with a time-and-hour stamp.")
-(make-variable-buffer-local 'org-deadline-time-hour-regexp)
-(defvar org-deadline-line-regexp nil
-  "Matches the DEADLINE keyword and the rest of the line.")
-(make-variable-buffer-local 'org-deadline-line-regexp)
-(defvar org-scheduled-regexp nil
-  "Matches the SCHEDULED keyword.")
-(make-variable-buffer-local 'org-scheduled-regexp)
-(defvar org-scheduled-time-regexp nil
-  "Matches the SCHEDULED keyword together with a time stamp.")
-(make-variable-buffer-local 'org-scheduled-time-regexp)
-(defvar org-scheduled-time-hour-regexp nil
-  "Matches the SCHEDULED keyword together with a time-and-hour stamp.")
-(make-variable-buffer-local 'org-scheduled-time-hour-regexp)
-(defvar org-closed-time-regexp nil
-  "Matches the CLOSED keyword together with a time stamp.")
-(make-variable-buffer-local 'org-closed-time-regexp)
-
-(defvar org-keyword-time-regexp nil
-  "Matches any of the 4 keywords, together with the time stamp.")
-(make-variable-buffer-local 'org-keyword-time-regexp)
-(defvar org-keyword-time-not-clock-regexp nil
-  "Matches any of the 3 keywords, together with the time stamp.")
-(make-variable-buffer-local 'org-keyword-time-not-clock-regexp)
-(defvar org-maybe-keyword-time-regexp nil
-  "Matches a timestamp, possibly preceded by a keyword.")
-(make-variable-buffer-local 'org-maybe-keyword-time-regexp)
-(defvar org-all-time-keywords nil
-  "List of time keywords.")
-(make-variable-buffer-local 'org-all-time-keywords)
 
 (defconst org-plain-time-of-day-regexp
   (concat
@@ -4771,32 +5058,6 @@ in the #+STARTUP line), the corresponding variable, and 
the value to set
 this variable to if the option is found.  An optional forth element PUSH
 means to push this value onto the list in the variable.")
 
-(defun org-update-property-plist (key val props)
-  "Update PROPS with KEY and VAL."
-  (let* ((appending (string= "+" (substring key (- (length key) 1))))
-        (key (if appending (substring key 0 (- (length key) 1)) key))
-        (remainder (org-remove-if (lambda (p) (string= (car p) key)) props))
-        (previous (cdr (assoc key props))))
-    (if appending
-       (cons (cons key (if previous (concat previous " " val) val)) remainder)
-      (cons (cons key val) remainder))))
-
-(defconst org-block-regexp
-  "^[ \t]*#\\+begin_?\\([^ 
\n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$"
-  "Regular expression for hiding blocks.")
-(defconst org-heading-keyword-regexp-format
-  "^\\(\\*+\\)\\(?: +%s\\)\\(?: +\\(.*?\\)\\)?[ \t]*$"
-  "Printf format for a regexp matching a headline with some keyword.
-This regexp will match the headline of any node which has the
-exact keyword that is put into the format.  The keyword isn't in
-any group by default, but the stars and the body are.")
-(defconst org-heading-keyword-maybe-regexp-format
-  "^\\(\\*+\\)\\(?: +%s\\)?\\(?: +\\(.*?\\)\\)?[ \t]*$"
-  "Printf format for a regexp matching a headline, possibly with some keyword.
-This regexp can match any headline with the specified keyword, or
-without a keyword.  The keyword isn't in any group by default,
-but the stars and the body are.")
-
 (defcustom org-group-tags t
   "When non-nil (the default), use group tags.
 This can be turned on/off through `org-toggle-tags-groups'."
@@ -4820,386 +5081,378 @@ Support for group tags is controlled by the option
   (message "Groups tags support has been turned %s"
           (if org-group-tags "on" "off")))
 
-(defun org-set-regexps-and-options-for-tags ()
-  "Precompute variables used for tags."
-  (when (derived-mode-p 'org-mode)
-    (org-set-local 'org-file-tags nil)
-    (let ((re (org-make-options-regexp '("FILETAGS" "TAGS")))
-         (splitre "[ \t]+")
-         (start 0)
-         tags ftags key value)
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (while (re-search-forward re nil t)
-           (setq key (upcase (org-match-string-no-properties 1))
-                 value (org-match-string-no-properties 2))
-           (if (stringp value) (setq value (org-trim value)))
-           (cond
-            ((equal key "TAGS")
-             (setq tags (append tags (if tags '("\\n") nil)
-                                (org-split-string value splitre))))
-            ((equal key "FILETAGS")
-             (when (string-match "\\S-" value)
-               (setq ftags
-                     (append
-                      ftags
-                      (apply 'append
-                             (mapcar (lambda (x) (org-split-string x ":"))
-                                     (org-split-string value)))))))))))
-      ;; Process the file tags.
-      (and ftags (org-set-local 'org-file-tags
-                               (mapcar 'org-add-prop-inherited ftags)))
-      (org-set-local 'org-tag-groups-alist nil)
-      ;; Process the tags.
-      (when (and (not tags) org-tag-alist)
-       (setq tags
-             (mapcar
-              (lambda (tg) (cond ((eq (car tg) :startgroup) "{")
-                                 ((eq (car tg) :endgroup) "}")
-                                 ((eq (car tg) :grouptags) ":")
-                                 ((eq (car tg) :newline) "\n")
-                                 (t (concat (car tg)
-                                            (if (characterp (cdr tg))
-                                                (format "(%s)" (char-to-string 
(cdr tg))) "")))))
-              org-tag-alist)))
-      (let (tgs g)
-       (dolist (e tags)
-         (cond
-          ((equal e "{")
-           (progn (push '(:startgroup) tgs)
-                  (when (equal (nth 1 tags) ":")
-                    (push (list (replace-regexp-in-string
-                                 "(.+)$" "" (nth 0 tags)))
-                          org-tag-groups-alist)
-                    (setq g 0))))
-          ((equal e ":") (push '(:grouptags) tgs))
-          ((equal e "}") (push '(:endgroup) tgs) (if g (setq g nil)))
-          ((equal e "\\n") (push '(:newline) tgs))
-          ((string-match (org-re "^\\([[:alnum:address@hidden)(\\(.\\))$") e)
-           (push (cons (match-string 1 e)
-                       (string-to-char (match-string 2 e)))
-                  tgs)
-           (if (and g (> g 0))
-               (setcar org-tag-groups-alist
-                       (append (car org-tag-groups-alist)
-                               (list (match-string 1 e)))))
-           (if g (setq g (1+ g))))
-          (t (push (list e) tgs)
-             (if (and g (> g 0))
-                 (setcar org-tag-groups-alist
-                         (append (car org-tag-groups-alist) (list e))))
-             (if g (setq g (1+ g))))))
-       (org-set-local 'org-tag-alist nil)
-       (dolist (e tgs)
-         (or (and (stringp (car e))
-                  (assoc (car e) org-tag-alist))
-             (push e org-tag-alist)))
-       ;; Return a list with tag variables
-       (list org-file-tags org-tag-alist org-tag-groups-alist)))))
-
-(defvar org-ota nil)
-(defun org-set-regexps-and-options ()
-  "Precompute regular expressions used in the current buffer."
+(defun org-set-regexps-and-options (&optional tags-only)
+  "Precompute regular expressions used in the current buffer.
+When optional argument TAGS-ONLY is non-nil, only compute tags
+related expressions."
   (when (derived-mode-p 'org-mode)
-    (org-set-local 'org-todo-kwd-alist nil)
-    (org-set-local 'org-todo-key-alist nil)
-    (org-set-local 'org-todo-key-trigger nil)
-    (org-set-local 'org-todo-keywords-1 nil)
-    (org-set-local 'org-done-keywords nil)
-    (org-set-local 'org-todo-heads nil)
-    (org-set-local 'org-todo-sets nil)
-    (org-set-local 'org-todo-log-states nil)
-    (org-set-local 'org-file-properties nil)
-    (let ((re (org-make-options-regexp
-              '("CATEGORY" "TODO" "COLUMNS" "STARTUP" "ARCHIVE"
-                "LINK" "PRIORITIES" "CONSTANTS" "PROPERTY" "DRAWERS"
-                "SETUPFILE" "OPTIONS")
-              "\\(?:[a-zA-Z][0-9a-zA-Z_]*_TODO\\)"))
-         (splitre "[ \t]+")
-         (scripts org-use-sub-superscripts)
-         kwds kws0 kwsa key log value cat arch const links hw dws
-         tail sep kws1 prio props drawers ext-setup-or-nil setup-contents
-         (start 0))
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (while
-             (or (and
-                  ext-setup-or-nil
-                  (not org-ota)
-                  (let (ret)
-                    (with-temp-buffer
-                      (insert ext-setup-or-nil)
-                      (let ((major-mode 'org-mode) org-ota)
-                        (setq ret (save-match-data
-                                    (org-set-regexps-and-options-for-tags)))))
-                    ;; Append setupfile tags to existing tags
-                    (setq org-ota t)
-                    (setq org-file-tags
-                          (delq nil (append org-file-tags (nth 0 ret)))
-                          org-tag-alist
-                          (delq nil (append org-tag-alist (nth 1 ret)))
-                          org-tag-groups-alist
-                          (delq nil (append org-tag-groups-alist (nth 2 
ret))))))
-                 (and ext-setup-or-nil
-                      (string-match re ext-setup-or-nil start)
-                      (setq start (match-end 0)))
-                 (and (setq ext-setup-or-nil nil start 0)
-                      (re-search-forward re nil t)))
-           (setq key (upcase (match-string 1 ext-setup-or-nil))
-                 value (org-match-string-no-properties 2 ext-setup-or-nil))
-           (if (stringp value) (setq value (org-trim value)))
-           (cond
-            ((equal key "CATEGORY")
-             (setq cat value))
-            ((member key '("SEQ_TODO" "TODO"))
-             (push (cons 'sequence (org-split-string value splitre)) kwds))
-            ((equal key "TYP_TODO")
-             (push (cons 'type (org-split-string value splitre)) kwds))
-            ((string-match "\\`\\([a-zA-Z][0-9a-zA-Z_]*\\)_TODO\\'" key)
-             ;; general TODO-like setup
-             (push (cons (intern (downcase (match-string 1 key)))
-                         (org-split-string value splitre))
-                    kwds))
-            ((equal key "COLUMNS")
-             (org-set-local 'org-columns-default-format value))
-            ((equal key "LINK")
-             (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
-               (push (cons (match-string 1 value)
-                           (org-trim (match-string 2 value)))
-                     links)))
-            ((equal key "PRIORITIES")
-             (setq prio (org-split-string value " +")))
-            ((equal key "PROPERTY")
-             (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value)
-               (setq props (org-update-property-plist (match-string 1 value)
-                                                      (match-string 2 value)
-                                                      props))))
-            ((equal key "DRAWERS")
-             (setq drawers (delete-dups (append org-drawers (org-split-string 
value splitre)))))
-            ((equal key "CONSTANTS")
-             (org-table-set-constants))
-            ((equal key "STARTUP")
-             (let ((opts (org-split-string value splitre))
-                   var val)
-               (dolist (l opts)
-                 (when (setq l (assoc l org-startup-options))
-                   (setq var (nth 1 l) val (nth 2 l))
-                   (if (not (nth 3 l))
-                       (set (make-local-variable var) val)
-                     (if (not (listp (symbol-value var)))
-                         (set (make-local-variable var) nil))
-                     (set (make-local-variable var) (symbol-value var))
-                     (add-to-list var val))))))
-            ((equal key "ARCHIVE")
-             (setq arch value)
-             (remove-text-properties 0 (length arch)
-                                     '(face t fontified t) arch))
-            ((equal key "OPTIONS")
-             (if (string-match "\\([ \t]\\|\\`\\)\\^:\\(t\\|nil\\|{}\\)" value)
-                 (setq scripts (read (match-string 2 value)))))
-            ((and (equal key "SETUPFILE")
-                  ;; Prevent checking in Gnus messages
-                  (not buffer-read-only))
-             (setq setup-contents (org-file-contents
-                                   (expand-file-name
-                                    (org-remove-double-quotes value))
-                                   'noerror))
-             (if (not ext-setup-or-nil)
-                 (setq ext-setup-or-nil setup-contents start 0)
-               (setq ext-setup-or-nil
-                     (concat (substring ext-setup-or-nil 0 start)
-                             "\n" setup-contents "\n"
-                             (substring ext-setup-or-nil start)))))))
-         ;; search for property blocks
-         (goto-char (point-min))
-         (while (re-search-forward org-block-regexp nil t)
-           (when (equal "PROPERTY" (upcase (match-string 1)))
-             (setq value (replace-regexp-in-string
-                          "[\n\r]" " " (match-string 4)))
-             (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value)
-               (setq props (org-update-property-plist (match-string 1 value)
-                                                      (match-string 2 value)
-                                                      props)))))))
-      (org-set-local 'org-use-sub-superscripts scripts)
-      (when cat
-       (org-set-local 'org-category (intern cat))
-       (push (cons "CATEGORY" cat) props))
-      (when prio
-       (if (< (length prio) 3) (setq prio '("A" "C" "B")))
-       (setq prio (mapcar 'string-to-char prio))
-       (org-set-local 'org-highest-priority (nth 0 prio))
-       (org-set-local 'org-lowest-priority  (nth 1 prio))
-       (org-set-local 'org-default-priority (nth 2 prio)))
-      (and props (org-set-local 'org-file-properties (nreverse props)))
-      (and drawers (org-set-local 'org-drawers drawers))
-      (and arch (org-set-local 'org-archive-location arch))
-      (and links (setq org-link-abbrev-alist-local (nreverse links)))
-      ;; Process the TODO keywords
-      (unless kwds
-       ;; Use the global values as if they had been given locally.
-       (setq kwds (default-value 'org-todo-keywords))
-       (if (stringp (car kwds))
-           (setq kwds (list (cons org-todo-interpretation
-                                  (default-value 'org-todo-keywords)))))
-       (setq kwds (reverse kwds)))
-      (setq kwds (nreverse kwds))
-      (let (inter kw)
-       (dolist (kws kwds)
-         (let ((kws (or
-                     (run-hook-with-args-until-success
-                      'org-todo-setup-filter-hook kws)
-                     kws)))
-           (setq inter (pop kws) sep (member "|" kws)
-                 kws0 (delete "|" (copy-sequence kws))
-                 kwsa nil
-                 kws1 (mapcar
-                       (lambda (x)
-                         ;;                     1              2
-                         (if (string-match 
"^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x)
-                             (progn
-                               (setq kw (match-string 1 x)
-                                     key (and (match-end 2) (match-string 2 x))
-                                     log (org-extract-log-state-settings x))
-                               (push (cons kw (and key (string-to-char key))) 
kwsa)
-                               (and log (push log org-todo-log-states))
-                               kw)
-                           (error "Invalid TODO keyword %s" x)))
-                       kws0)
-                 kwsa (if kwsa (append '((:startgroup))
-                                       (nreverse kwsa)
-                                       '((:endgroup))))
-                 hw (car kws1)
-                 dws (if sep (org-remove-keyword-keys (cdr sep)) (last kws1))
-                 tail (list inter hw (car dws) (org-last dws))))
-         (add-to-list 'org-todo-heads hw 'append)
-         (push kws1 org-todo-sets)
-         (setq org-done-keywords (append org-done-keywords dws nil))
-         (setq org-todo-key-alist (append org-todo-key-alist kwsa))
-         (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1)
-         (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil)))
+    (let ((alist (org--setup-collect-keywords
+                 (org-make-options-regexp
+                  (append '("FILETAGS" "TAGS" "SETUPFILE")
+                          (and (not tags-only)
+                               '("ARCHIVE" "CATEGORY" "COLUMNS" "CONSTANTS"
+                                 "LINK" "OPTIONS" "PRIORITIES" "PROPERTY"
+                                 "SEQ_TODO" "STARTUP" "TODO" "TYP_TODO")))))))
+      ;; Startup options.  Get this early since it does change
+      ;; behavior for other options (e.g., tags).
+      (let ((startup (cdr (assq 'startup alist))))
+       (dolist (option startup)
+         (let ((entry (assoc-string option org-startup-options t)))
+           (when entry
+             (let ((var (nth 1 entry))
+                   (val (nth 2 entry)))
+               (if (not (nth 3 entry)) (set (make-local-variable var) val)
+                 (unless (listp (symbol-value var))
+                   (set (make-local-variable var) nil))
+                 (add-to-list var val)))))))
+      (setq-local org-file-tags
+                 (mapcar #'org-add-prop-inherited
+                         (cdr (assq 'filetags alist))))
+      (setq org-current-tag-alist
+           (append org-tag-persistent-alist
+                   (let ((tags (cdr (assq 'tags alist))))
+                     (if tags (org-tag-string-to-alist tags)
+                       org-tag-alist))))
+      (setq org-tag-groups-alist
+           (org-tag-alist-to-groups org-current-tag-alist))
+      (unless tags-only
+       ;; File properties.
+       (setq-local org-file-properties (cdr (assq 'property alist)))
+       ;; Archive location.
+       (let ((archive (cdr (assq 'archive alist))))
+         (when archive (setq-local org-archive-location archive)))
+       ;; Category.
+       (let ((cat (org-string-nw-p (cdr (assq 'category alist)))))
+         (when cat
+           (setq-local org-category (intern cat))
+           (setq-local org-file-properties
+                       (org--update-property-plist
+                        "CATEGORY" cat org-file-properties))))
+       ;; Columns.
+       (let ((column (cdr (assq 'columns alist))))
+         (when column (setq-local org-columns-default-format column)))
+       ;; Constants.
+       (setq org-table-formula-constants-local (cdr (assq 'constants alist)))
+       ;; Link abbreviations.
+       (let ((links (cdr (assq 'link alist))))
+         (when links (setq org-link-abbrev-alist-local (nreverse links))))
+       ;; Priorities.
+       (let ((priorities (cdr (assq 'priorities alist))))
+         (when priorities
+           (setq-local org-highest-priority (nth 0 priorities))
+           (setq-local org-lowest-priority (nth 1 priorities))
+           (setq-local org-default-priority (nth 2 priorities))))
+       ;; Scripts.
+       (let ((scripts (assq 'scripts alist)))
+         (when scripts
+           (setq-local org-use-sub-superscripts (cdr scripts))))
+       ;; TODO keywords.
+       (setq-local org-todo-kwd-alist nil)
+       (setq-local org-todo-key-alist nil)
+       (setq-local org-todo-key-trigger nil)
+       (setq-local org-todo-keywords-1 nil)
+       (setq-local org-done-keywords nil)
+       (setq-local org-todo-heads nil)
+       (setq-local org-todo-sets nil)
+       (setq-local org-todo-log-states nil)
+       (let ((todo-sequences
+              (or (nreverse (cdr (assq 'todo alist)))
+                  (let ((d (default-value 'org-todo-keywords)))
+                    (if (not (stringp (car d))) d
+                      ;; XXX: Backward compatibility code.
+                      (list (cons org-todo-interpretation d)))))))
+         (dolist (sequence todo-sequences)
+           (let* ((sequence (or (run-hook-with-args-until-success
+                                 'org-todo-setup-filter-hook sequence)
+                                sequence))
+                  (sequence-type (car sequence))
+                  (keywords (cdr sequence))
+                  (sep (member "|" keywords))
+                  names alist)
+             (dolist (k (remove "|" keywords))
+               (unless (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$"
+                                     k)
+                 (error "Invalid TODO keyword %s" k))
+               (let ((name (match-string 1 k))
+                     (key (match-string 2 k))
+                     (log (org-extract-log-state-settings k)))
+                 (push name names)
+                 (push (cons name (and key (string-to-char key))) alist)
+                 (when log (push log org-todo-log-states))))
+             (let* ((names (nreverse names))
+                    (done (if sep (org-remove-keyword-keys (cdr sep))
+                            (last names)))
+                    (head (car names))
+                    (tail (list sequence-type head (car done) (org-last 
done))))
+               (add-to-list 'org-todo-heads head 'append)
+               (push names org-todo-sets)
+               (setq org-done-keywords (append org-done-keywords done nil))
+               (setq org-todo-keywords-1 (append org-todo-keywords-1 names 
nil))
+               (setq org-todo-key-alist
+                     (append org-todo-key-alist
+                             (and alist
+                                  (append '((:startgroup))
+                                          (nreverse alist)
+                                          '((:endgroup))))))
+               (dolist (k names) (push (cons k tail) org-todo-kwd-alist))))))
        (setq org-todo-sets (nreverse org-todo-sets)
              org-todo-kwd-alist (nreverse org-todo-kwd-alist)
-             org-todo-key-trigger (delq nil (mapcar 'cdr org-todo-key-alist))
-             org-todo-key-alist (org-assign-fast-keys org-todo-key-alist)))
-      ;; Compute the regular expressions and other local variables.
-      ;; Using `org-outline-regexp-bol' would complicate them much,
-      ;; because of the fixed white space at the end of that string.
-      (if (not org-done-keywords)
-         (setq org-done-keywords (and org-todo-keywords-1
-                                      (list (org-last org-todo-keywords-1)))))
-      (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string)
-                                           (length org-scheduled-string)
-                                           (length org-clock-string)
-                                           (length org-closed-string)))
-           org-drawer-regexp
-           (concat "^[ \t]*:\\("
-                   (mapconcat 'regexp-quote org-drawers "\\|")
-                   "\\):[ \t]*$")
-           org-not-done-keywords
-           (org-delete-all org-done-keywords (copy-sequence 
org-todo-keywords-1))
-           org-todo-regexp
-           (concat "\\("
-                   (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
-                   "\\)")
-           org-not-done-regexp
-           (concat "\\("
-                   (mapconcat 'regexp-quote org-not-done-keywords "\\|")
-                   "\\)")
-           org-not-done-heading-regexp
-           (format org-heading-keyword-regexp-format org-not-done-regexp)
-           org-todo-line-regexp
-           (format org-heading-keyword-maybe-regexp-format org-todo-regexp)
-           org-complex-heading-regexp
-           (concat "^\\(\\*+\\)"
-                   "\\(?: +" org-todo-regexp "\\)?"
-                   "\\(?: +\\(\\[#.\\]\\)\\)?"
-                   "\\(?: +\\(.*?\\)\\)??"
-                   (org-re "\\(?:[ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)?")
-                   "[ \t]*$")
-           org-complex-heading-regexp-format
-           (concat "^\\(\\*+\\)"
-                   "\\(?: +" org-todo-regexp "\\)?"
-                   "\\(?: +\\(\\[#.\\]\\)\\)?"
-                   "\\(?: +"
-                   ;; Stats cookies can be stuck to body.
-                   "\\(?:\\[[0-9%%/]+\\] *\\)*"
-                   "\\(%s\\)"
-                   "\\(?: *\\[[0-9%%/]+\\]\\)*"
-                   "\\)"
-                   (org-re "\\(?:[ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)?")
-                   "[ \t]*$")
-           org-todo-line-tags-regexp
-           (concat "^\\(\\*+\\)"
-                   "\\(?: +" org-todo-regexp "\\)?"
-                   "\\(?: +\\(.*?\\)\\)??"
-                   (org-re "\\(?:[ \t]+\\(:[[:alnum:]:address@hidden:\\)\\)?")
-                   "[ \t]*$")
-           org-deadline-regexp (concat "\\<" org-deadline-string)
-           org-deadline-time-regexp
-           (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
-           org-deadline-time-hour-regexp
-           (concat "\\<" org-deadline-string
-                   " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy 
\t.]*\\)>")
-           org-deadline-line-regexp
-           (concat "\\<\\(" org-deadline-string "\\).*")
-           org-scheduled-regexp
-           (concat "\\<" org-scheduled-string)
-           org-scheduled-time-regexp
-           (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
-           org-scheduled-time-hour-regexp
-           (concat "\\<" org-scheduled-string
-                   " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy 
\t.]*\\)>")
-           org-closed-time-regexp
-           (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
-           org-keyword-time-regexp
-           (concat "\\<\\(" org-scheduled-string
-                   "\\|" org-deadline-string
-                   "\\|" org-closed-string
-                   "\\|" org-clock-string "\\)"
-                   " *[[<]\\([^]>]+\\)[]>]")
-           org-keyword-time-not-clock-regexp
-           (concat "\\<\\(" org-scheduled-string
-                   "\\|" org-deadline-string
-                   "\\|" org-closed-string
-                   "\\)"
-                   " *[[<]\\([^]>]+\\)[]>]")
-           org-maybe-keyword-time-regexp
-           (concat "\\(\\<\\(" org-scheduled-string
-                   "\\|" org-deadline-string
-                   "\\|" org-closed-string
-                   "\\|" org-clock-string "\\)\\)?"
-                   " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)")
-           org-all-time-keywords
-           (mapcar (lambda (w) (substring w 0 -1))
-                   (list org-scheduled-string org-deadline-string
-                         org-clock-string org-closed-string)))
-      (setq org-ota nil)
-      (org-compute-latex-and-related-regexp))))
+             org-todo-key-trigger (delq nil (mapcar #'cdr org-todo-key-alist))
+             org-todo-key-alist (org-assign-fast-keys org-todo-key-alist))
+       ;; Compute the regular expressions and other local variables.
+       ;; Using `org-outline-regexp-bol' would complicate them much,
+       ;; because of the fixed white space at the end of that string.
+       (unless org-done-keywords
+         (setq org-done-keywords
+               (and org-todo-keywords-1 (last org-todo-keywords-1))))
+       (setq org-not-done-keywords
+             (org-delete-all org-done-keywords
+                             (copy-sequence org-todo-keywords-1))
+             org-todo-regexp (regexp-opt org-todo-keywords-1 t)
+             org-not-done-regexp (regexp-opt org-not-done-keywords t)
+             org-not-done-heading-regexp
+             (format org-heading-keyword-regexp-format org-not-done-regexp)
+             org-todo-line-regexp
+             (format org-heading-keyword-maybe-regexp-format org-todo-regexp)
+             org-complex-heading-regexp
+             (concat "^\\(\\*+\\)"
+                     "\\(?: +" org-todo-regexp "\\)?"
+                     "\\(?: +\\(\\[#.\\]\\)\\)?"
+                     "\\(?: +\\(.*?\\)\\)??"
+                     "\\(?:[ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)?"
+                     "[ \t]*$")
+             org-complex-heading-regexp-format
+             (concat "^\\(\\*+\\)"
+                     "\\(?: +" org-todo-regexp "\\)?"
+                     "\\(?: +\\(\\[#.\\]\\)\\)?"
+                     "\\(?: +"
+                     ;; Stats cookies can be stuck to body.
+                     "\\(?:\\[[0-9%%/]+\\] *\\)*"
+                     "\\(%s\\)"
+                     "\\(?: *\\[[0-9%%/]+\\]\\)*"
+                     "\\)"
+                     "\\(?:[ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)?"
+                     "[ \t]*$")
+             org-todo-line-tags-regexp
+             (concat "^\\(\\*+\\)"
+                     "\\(?: +" org-todo-regexp "\\)?"
+                     "\\(?: +\\(.*?\\)\\)??"
+                     "\\(?:[ \t]+\\(:[[:alnum:]:address@hidden:\\)\\)?"
+                     "[ \t]*$"))
+       (org-compute-latex-and-related-regexp)))))
+
+(defun org--setup-collect-keywords (regexp &optional files alist)
+  "Return setup keywords values as an alist.
+
+REGEXP matches a subset of setup keywords.  FILES is a list of
+file names already visited.  It is used to avoid circular setup
+files.  ALIST, when non-nil, is the alist computed so far.
+
+Return value contains the following keys: `archive', `category',
+`columns', `constants', `filetags', `link', `priorities',
+`property', `scripts', `startup', `tags' and `todo'."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let ((case-fold-search t))
+     (while (re-search-forward regexp nil t)
+       (let ((element (org-element-at-point)))
+        (when (eq (org-element-type element) 'keyword)
+          (let ((key (org-element-property :key element))
+                (value (org-element-property :value element)))
+            (cond
+             ((equal key "ARCHIVE")
+              (when (org-string-nw-p value)
+                (push (cons 'archive value) alist)))
+             ((equal key "CATEGORY") (push (cons 'category value) alist))
+             ((equal key "COLUMNS") (push (cons 'columns value) alist))
+             ((equal key "CONSTANTS")
+              (let* ((constants (assq 'constants alist))
+                     (store (cdr constants)))
+                (dolist (pair (org-split-string value))
+                  (when (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)"
+                                      pair)
+                    (let* ((name (match-string 1 pair))
+                           (value (match-string 2 pair))
+                           (old (assoc name store)))
+                      (if old (setcdr old value)
+                        (push (cons name value) store)))))
+                (if constants (setcdr constants store)
+                  (push (cons 'constants store) alist))))
+             ((equal key "FILETAGS")
+              (when (org-string-nw-p value)
+                (let ((old (assq 'filetags alist))
+                      (new (apply #'nconc
+                                  (mapcar (lambda (x) (org-split-string x ":"))
+                                          (org-split-string value)))))
+                  (if old (setcdr old (append new (cdr old)))
+                    (push (cons 'filetags new) alist)))))
+             ((equal key "LINK")
+              (when (string-match "\\`\\(\\S-+\\)[ \t]+\\(.+\\)" value)
+                (let ((links (assq 'link alist))
+                      (pair (cons (match-string-no-properties 1 value)
+                                  (match-string-no-properties 2 value))))
+                  (if links (push pair (cdr links))
+                    (push (list 'link pair) alist)))))
+             ((equal key "OPTIONS")
+              (when (and (org-string-nw-p value)
+                         (string-match "\\^:\\(t\\|nil\\|{}\\)" value))
+                (push (cons 'scripts (read (match-string 1 value))) alist)))
+             ((equal key "PRIORITIES")
+              (push (cons 'priorities
+                          (let ((prio (org-split-string value)))
+                            (if (< (length prio) 3) '(?A ?C ?B)
+                              (mapcar #'string-to-char prio))))
+                    alist))
+             ((equal key "PROPERTY")
+              (when (string-match "\\(\\S-+\\)[ \t]+\\(.*\\)" value)
+                (let* ((property (assq 'property alist))
+                       (value (org--update-property-plist
+                               (match-string-no-properties 1 value)
+                               (match-string-no-properties 2 value)
+                               (cdr property))))
+                  (if property (setcdr property value)
+                    (push (cons 'property value) alist)))))
+             ((equal key "STARTUP")
+              (let ((startup (assq 'startup alist)))
+                (if startup
+                    (setcdr startup
+                            (append (cdr startup) (org-split-string value)))
+                  (push (cons 'startup (org-split-string value)) alist))))
+             ((equal key "TAGS")
+              (let ((tag-cell (assq 'tags alist)))
+                (if tag-cell
+                    (setcdr tag-cell (concat (cdr tag-cell) "\n" value))
+                  (push (cons 'tags value) alist))))
+             ((member key '("TODO" "SEQ_TODO" "TYP_TODO"))
+              (let ((todo (assq 'todo alist))
+                    (value (cons (if (equal key "TYP_TODO") 'type 'sequence)
+                                 (org-split-string value))))
+                (if todo (push value (cdr todo))
+                  (push (list 'todo value) alist))))
+             ((equal key "SETUPFILE")
+              (unless buffer-read-only ; Do not check in Gnus messages.
+                (let ((f (and (org-string-nw-p value)
+                              (expand-file-name
+                               (org-unbracket-string "\"" "\"" value)))))
+                  (when (and f (file-readable-p f) (not (member f files)))
+                    (with-temp-buffer
+                      (setq default-directory (file-name-directory f))
+                      (insert-file-contents f)
+                      (setq alist
+                            ;; Fake Org mode to benefit from cache
+                            ;; without recurring needlessly.
+                            (let ((major-mode 'org-mode))
+                              (org--setup-collect-keywords
+                               regexp (cons f files) alist)))))))))))))))
+  alist)
+
+(defun org-tag-string-to-alist (s)
+  "Return tag alist associated to string S.
+S is a value for TAGS keyword or produced with
+`org-tag-alist-to-string'.  Return value is an alist suitable for
+`org-tag-alist' or `org-tag-persistent-alist'."
+  (let ((lines (mapcar #'split-string (split-string s "\n" t)))
+       (tag-re (concat "\\`\\([[:alnum:address@hidden"
+                       "\\|{.+?}\\)"   ; regular expression
+                       "\\(?:(\\(.\\))\\)?\\'"))
+       alist group-flag)
+    (dolist (tokens lines (cdr (nreverse alist)))
+      (push '(:newline) alist)
+      (while tokens
+       (let ((token (pop tokens)))
+         (pcase token
+           ("{"
+            (push '(:startgroup) alist)
+            (when (equal (nth 1 tokens) ":") (setq group-flag t)))
+           ("}"
+            (push '(:endgroup) alist)
+            (setq group-flag nil))
+           ("["
+            (push '(:startgrouptag) alist)
+            (when (equal (nth 1 tokens) ":") (setq group-flag t)))
+           ("]"
+            (push '(:endgrouptag) alist)
+            (setq group-flag nil))
+           (":"
+            (push '(:grouptags) alist))
+           ((guard (string-match tag-re token))
+            (let ((tag (match-string 1 token))
+                  (key (and (match-beginning 2)
+                            (string-to-char (match-string 2 token)))))
+              ;; Push all tags in groups, no matter if they already
+              ;; appear somewhere else in the list.
+              (when (or group-flag (not (assoc tag alist)))
+                (push (cons tag key) alist))))))))))
+
+(defun org-tag-alist-to-string (alist &optional skip-key)
+  "Return tag string associated to ALIST.
+
+ALIST is an alist, as defined in `org-tag-alist' or
+`org-tag-persistent-alist', or produced with
+`org-tag-string-to-alist'.
+
+Return value is a string suitable as a value for \"TAGS\"
+keyword.
+
+When optional argument SKIP-KEY is non-nil, skip selection keys
+next to tags."
+  (mapconcat (lambda (token)
+              (pcase token
+                (`(:startgroup) "{")
+                (`(:endgroup) "}")
+                (`(:startgrouptag) "[")
+                (`(:endgrouptag) "]")
+                (`(:grouptags) ":")
+                (`(:newline) "\\n")
+                ((and
+                  (guard (not skip-key))
+                  `(,(and tag (pred stringp)) . ,(and key (pred characterp))))
+                 (format "%s(%c)" tag key))
+                (`(,(and tag (pred stringp)) . ,_) tag)
+                (_ (user-error "Invalid tag token: %S" token))))
+            alist
+            " "))
+
+(defun org-tag-alist-to-groups (alist)
+  "Return group alist from tag ALIST.
+ALIST is an alist, as defined in `org-tag-alist' or
+`org-tag-persistent-alist', or produced with
+`org-tag-string-to-alist'.  Return value is an alist following
+the pattern (GROUP-TAG TAGS) where GROUP-TAG is the tag, as
+a string, summarizing TAGS, as a list of strings."
+  (let (groups group-status current-group)
+    (dolist (token alist (nreverse groups))
+      (pcase token
+       (`(,(or :startgroup :startgrouptag)) (setq group-status t))
+       (`(,(or :endgroup :endgrouptag))
+        (when (eq group-status 'append)
+          (push (nreverse current-group) groups))
+        (setq group-status nil))
+       (`(:grouptags) (setq group-status 'append))
+       ((and `(,tag . ,_) (guard group-status))
+        (if (eq group-status 'append) (push tag current-group)
+          (setq current-group (list tag))))
+       (_ nil)))))
 
 (defun org-file-contents (file &optional noerror)
   "Return the contents of FILE, as a string."
-  (if (or (not file) (not (file-readable-p file)))
-      (if (not noerror)
-         (error "Cannot read file \"%s\"" file)
-       (message "Cannot read file \"%s\"" file)
-       "")
-    (with-temp-buffer
-      (insert-file-contents file)
-      (buffer-string))))
+  (if (and file (file-readable-p file))
+      (with-temp-buffer
+       (insert-file-contents file)
+       (buffer-string))
+    (funcall (if noerror 'message 'error)
+            "Cannot read file \"%s\"%s"
+            file
+            (let ((from (buffer-file-name (buffer-base-buffer))))
+              (if from (concat " (referenced in file \"" from "\")") "")))))
 
 (defun org-extract-log-state-settings (x)
   "Extract the log state setting from a TODO keyword string.
 This will extract info from a string like \"WAIT(w@/!)\"."
-  (let (kw key log1 log2)
-    (when (string-match 
"^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\(address@hidden)?\\(?:/\\(address@hidden)\\)?)\\)?$"
 x)
-      (setq kw (match-string 1 x)
-           key (and (match-end 2) (match-string 2 x))
-           log1 (and (match-end 3) (match-string 3 x))
-           log2 (and (match-end 4) (match-string 4 x)))
+  (when (string-match 
"^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\(address@hidden)?\\(?:/\\(address@hidden)\\)?)\\)?$"
 x)
+    (let ((kw (match-string 1 x))
+         (log1 (and (match-end 3) (match-string 3 x)))
+         (log2 (and (match-end 4) (match-string 4 x))))
       (and (or log1 log2)
           (list kw
                 (and log1 (if (equal log1 "!") 'time 'note))
@@ -5216,8 +5469,8 @@ This will extract info from a string like \"WAIT(w@/!)\"."
 (defun org-assign-fast-keys (alist)
   "Assign fast keys to a keyword-key alist.
 Respect keys that are already there."
-  (let (new (alt ?0))
-    (dolist (e alist)
+  (let (new e (alt ?0))
+    (while (setq e (pop alist))
       (if (or (memq (car e) '(:newline :grouptags :endgroup :startgroup))
              (cdr e)) ;; Key already assigned.
          (push e new)
@@ -5229,7 +5482,7 @@ Respect keys that are already there."
            (pop clist))
          (unless clist
            (while (rassoc alt used)
-             (incf alt)))
+             (cl-incf alt)))
          (push (cons (car e) (or (car clist) alt)) new))))
     (nreverse new)))
 
@@ -5242,13 +5495,7 @@ Respect keys that are already there."
 (defvar org-finish-function nil
   "Function to be called when `C-c C-c' is used.
 This is for getting out of special buffers like capture.")
-
-
-;; FIXME: Occasionally check by commenting these, to make sure
-;;        no other functions uses these, forgetting to let-bind them.
-(org-no-warnings (defvar entry)) ;; unprefixed, from calendar.el
 (defvar org-last-state)
-(org-no-warnings (defvar date)) ;; unprefixed, from calendar.el
 
 ;; Defined somewhere in this file, but used before definition.
 (defvar org-entities)     ;; defined in org-entities.el
@@ -5256,7 +5503,7 @@ This is for getting out of special buffers like capture.")
 (defvar org-org-menu)
 (defvar org-tbl-menu)
 
-;;;; Define the Org-mode
+;;;; Define the Org mode
 
 ;; We use a before-change function to check if a table might need
 ;; an update.
@@ -5264,7 +5511,7 @@ This is for getting out of special buffers like capture.")
   "Indicates that a table might need an update.
 This variable is set by `org-before-change-function'.
 `org-table-align' sets it back to nil.")
-(defun org-before-change-function (beg end)
+(defun org-before-change-function (_beg _end)
   "Every change indicates that a table might need an update."
   (setq org-table-may-need-update t))
 (defvar org-mode-map)
@@ -5278,13 +5525,12 @@ This variable is set by `org-before-change-function'.
 (defvar buffer-face-mode-face)
 
 (require 'outline)
-(if (and (not (keymapp outline-mode-map)) (featurep 'allout))
-    (error "Conflict with outdated version of allout.el.  Load org.el before 
allout.el, or upgrade to newer allout, for example by switching to Emacs 22"))
-(require 'noutline "noutline" 'noerror) ;; stock XEmacs does not have it
 
 ;; Other stuff we need.
 (require 'time-date)
+(unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))
 (require 'easymenu)
+(autoload 'easy-menu-add "easymenu")
 (require 'overlay)
 
 ;; (require 'org-macs) moved higher up in the file before it is first used
@@ -5305,15 +5551,15 @@ This variable is set by `org-before-change-function'.
   "Outline-based notes management and organizer, alias
 \"Carsten's outline-mode for keeping track of everything.\"
 
-Org-mode develops organizational tasks around a NOTES file which
-contains information about projects as plain text.  Org-mode is
-implemented on top of outline-mode, which is ideal to keep the content
+Org mode develops organizational tasks around a NOTES file which
+contains information about projects as plain text.  Org mode is
+implemented on top of Outline mode, which is ideal to keep the content
 of large files well structured.  It supports ToDo items, deadlines and
 time stamps, which magically appear in the diary listing of the Emacs
 calendar.  Tables are easily created with a built-in table editor.
 Plain text URL-like links connect to websites, emails (VM), Usenet
 messages (Gnus), BBDB entries, and any files related to the project.
-For printing and sharing of notes, an Org-mode file (or a part of it)
+For printing and sharing of notes, an Org file (or a part of it)
 can be exported as a structured ASCII or HTML file.
 
 The following commands are available:
@@ -5323,29 +5569,18 @@ The following commands are available:
   ;; Get rid of Outline menus, they are not needed
   ;; Need to do this here because define-derived-mode sets up
   ;; the keymap so late.  Still, it is a waste to call this each time
-  ;; we switch another buffer into org-mode.
-  (if (featurep 'xemacs)
-      (when (boundp 'outline-mode-menu-heading)
-       ;; Assume this is Greg's port, it uses easymenu
-       (easy-menu-remove outline-mode-menu-heading)
-       (easy-menu-remove outline-mode-menu-show)
-       (easy-menu-remove outline-mode-menu-hide))
-    (define-key org-mode-map [menu-bar headings] 'undefined)
-    (define-key org-mode-map [menu-bar hide] 'undefined)
-    (define-key org-mode-map [menu-bar show] 'undefined))
+  ;; we switch another buffer into Org mode.
+  (define-key org-mode-map [menu-bar headings] 'undefined)
+  (define-key org-mode-map [menu-bar hide] 'undefined)
+  (define-key org-mode-map [menu-bar show] 'undefined)
 
   (org-load-modules-maybe)
-  (when (featurep 'xemacs)
-    (easy-menu-add org-org-menu)
-    (easy-menu-add org-tbl-menu))
   (org-install-agenda-files-menu)
-  (if org-descriptive-links (add-to-invisibility-spec '(org-link)))
+  (when org-descriptive-links (add-to-invisibility-spec '(org-link)))
   (add-to-invisibility-spec '(org-cwidth))
   (add-to-invisibility-spec '(org-hide-block . t))
-  (when (featurep 'xemacs)
-    (org-set-local 'line-move-ignore-invisible t))
-  (org-set-local 'outline-regexp org-outline-regexp)
-  (org-set-local 'outline-level 'org-outline-level)
+  (setq-local outline-regexp org-outline-regexp)
+  (setq-local outline-level 'org-outline-level)
   (setq bidi-paragraph-direction 'left-to-right)
   (when (and org-ellipsis
              (fboundp 'set-display-table-slot) (boundp 'buffer-display-table)
@@ -5354,55 +5589,50 @@ The following commands are available:
       (setq org-display-table (make-display-table)))
     (set-display-table-slot
      org-display-table 4
-     (vconcat (mapcar
-              (lambda (c) (make-glyph-code c (and (not (stringp org-ellipsis))
-                                             org-ellipsis)))
-              (if (stringp org-ellipsis) org-ellipsis "..."))))
+     (vconcat (mapcar (lambda (c) (make-glyph-code c 'org-ellipsis))
+                     (if (stringp org-ellipsis) org-ellipsis "..."))))
     (setq buffer-display-table org-display-table))
-  (org-set-regexps-and-options-for-tags)
   (org-set-regexps-and-options)
   (org-set-font-lock-defaults)
   (when (and org-tag-faces (not org-tags-special-faces-re))
     ;; tag faces set outside customize.... force initialization.
     (org-set-tag-faces 'org-tag-faces org-tag-faces))
   ;; Calc embedded
-  (org-set-local 'calc-embedded-open-mode "# ")
+  (setq-local calc-embedded-open-mode "# ")
   ;; Modify a few syntax entries
   (modify-syntax-entry ?@ "w")
   (modify-syntax-entry ?\" "\"")
   (modify-syntax-entry ?\\ "_")
   (modify-syntax-entry ?~ "_")
-  (if org-startup-truncated (setq truncate-lines t))
-  (when org-startup-indented (require 'org-indent) (org-indent-mode 1))
-  (org-set-local 'font-lock-unfontify-region-function
-                'org-unfontify-region)
+  (setq-local font-lock-unfontify-region-function 'org-unfontify-region)
   ;; Activate before-change-function
-  (org-set-local 'org-table-may-need-update t)
-  (org-add-hook 'before-change-functions 'org-before-change-function nil
-               'local)
+  (setq-local org-table-may-need-update t)
+  (add-hook 'before-change-functions 'org-before-change-function nil 'local)
   ;; Check for running clock before killing a buffer
-  (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
+  (add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
   ;; Initialize macros templates.
   (org-macro-initialize-templates)
   ;; Initialize radio targets.
   (org-update-radio-target-regexp)
   ;; Indentation.
-  (org-set-local 'indent-line-function 'org-indent-line)
-  (org-set-local 'indent-region-function 'org-indent-region)
+  (setq-local indent-line-function 'org-indent-line)
+  (setq-local indent-region-function 'org-indent-region)
   ;; Filling and auto-filling.
   (org-setup-filling)
   ;; Comments.
   (org-setup-comments-handling)
+  ;; Initialize cache.
+  (org-element-cache-reset)
   ;; Beginning/end of defun
-  (org-set-local 'beginning-of-defun-function 'org-backward-element)
-  (org-set-local 'end-of-defun-function
-                (lambda ()
-                  (if (not (org-at-heading-p))
-                      (org-forward-element)
-                    (org-forward-element)
-                    (forward-char -1))))
+  (setq-local beginning-of-defun-function 'org-backward-element)
+  (setq-local end-of-defun-function
+             (lambda ()
+               (if (not (org-at-heading-p))
+                   (org-forward-element)
+                 (org-forward-element)
+                 (forward-char -1))))
   ;; Next error for sparse trees
-  (org-set-local 'next-error-function 'org-occur-next-match)
+  (setq-local next-error-function 'org-occur-next-match)
   ;; Make sure dependence stuff works reliably, even for users who set it
   ;; too late :-(
   (if org-enforce-todo-dependencies
@@ -5417,78 +5647,65 @@ The following commands are available:
                 'org-block-todo-from-checkboxes))
 
   ;; Align options lines
-  (org-set-local
-   'align-mode-rules-list
+  (setq-local
+   align-mode-rules-list
    '((org-in-buffer-settings
-      (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
+      (regexp . "^[ \t]*#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
       (modes . '(org-mode)))))
 
   ;; Imenu
-  (org-set-local 'imenu-create-index-function
-                'org-imenu-get-tree)
+  (setq-local imenu-create-index-function 'org-imenu-get-tree)
 
   ;; Make isearch reveal context
-  (if (or (featurep 'xemacs)
-         (not (boundp 'outline-isearch-open-invisible-function)))
-      ;; Emacs 21 and XEmacs make use of the hook
-      (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local)
-    ;; Emacs 22 deals with this through a special variable
-    (org-set-local 'outline-isearch-open-invisible-function
-                  (lambda (&rest ignore) (org-show-context 'isearch))))
+  (setq-local outline-isearch-open-invisible-function
+             (lambda (&rest _) (org-show-context 'isearch)))
 
   ;; Setup the pcomplete hooks
-  (set (make-local-variable 'pcomplete-command-completion-function)
-       'org-pcomplete-initial)
-  (set (make-local-variable 'pcomplete-command-name-function)
-       'org-command-at-point)
-  (set (make-local-variable 'pcomplete-default-completion-function)
-       'ignore)
-  (set (make-local-variable 'pcomplete-parse-arguments-function)
-       'org-parse-arguments)
-  (set (make-local-variable 'pcomplete-termination-string) "")
-  (when (>= emacs-major-version 23)
-    (set (make-local-variable 'buffer-face-mode-face) 'org-default))
-
-  ;; If empty file that did not turn on org-mode automatically, make it to.
-  (if (and org-insert-mode-line-in-empty-file
-          (org-called-interactively-p 'any)
-          (= (point-min) (point-max)))
-      (insert "#    -*- mode: org -*-\n\n"))
+  (setq-local pcomplete-command-completion-function 'org-pcomplete-initial)
+  (setq-local pcomplete-command-name-function 'org-command-at-point)
+  (setq-local pcomplete-default-completion-function 'ignore)
+  (setq-local pcomplete-parse-arguments-function 'org-parse-arguments)
+  (setq-local pcomplete-termination-string "")
+  (setq-local buffer-face-mode-face 'org-default)
+
+  ;; If empty file that did not turn on Org mode automatically, make
+  ;; it to.
+  (when (and org-insert-mode-line-in-empty-file
+            (called-interactively-p 'any)
+            (= (point-min) (point-max)))
+    (insert "#    -*- mode: org -*-\n\n"))
   (unless org-inhibit-startup
     (org-unmodified
-     (and org-startup-with-beamer-mode (org-beamer-mode))
+     (when org-startup-with-beamer-mode (org-beamer-mode))
      (when org-startup-align-all-tables
-       (org-table-map-tables 'org-table-align 'quietly))
-     (when org-startup-with-inline-images
-       (org-display-inline-images))
-     (when org-startup-with-latex-preview
-       (org-preview-latex-fragment))
-     (unless org-inhibit-startup-visibility-stuff
-       (org-set-startup-visibility))))
-  ;; Try to set org-hide correctly
+       (org-table-map-tables #'org-table-align t))
+     (when org-startup-with-inline-images (org-display-inline-images))
+     (when org-startup-with-latex-preview (org-toggle-latex-fragment '(16)))
+     (unless org-inhibit-startup-visibility-stuff (org-set-startup-visibility))
+     (when org-startup-truncated (setq truncate-lines t))
+     (when org-startup-indented (require 'org-indent) (org-indent-mode 1))
+     (org-refresh-effort-properties)))
+  ;; Try to set `org-hide' face correctly.
   (let ((foreground (org-find-invisible-foreground)))
-    (if foreground
-        (set-face-foreground 'org-hide foreground))))
+    (when foreground
+      (set-face-foreground 'org-hide foreground))))
 
 ;; Update `customize-package-emacs-version-alist'
 (add-to-list 'customize-package-emacs-version-alist
             '(Org ("6.21b" . "23.1")  ("6.33x" . "23.2")
                   ("7.8.11" . "24.1") ("7.9.4" . "24.3")
-                  ("8.2.6" . "24.4")))
+                  ("8.2.6" . "24.4") ("8.2.10" . "24.5")
+                  ("9.0" . "26.1")))
 
 (defvar org-mode-transpose-word-syntax-table
-  (let ((st (make-syntax-table)))
-    (mapc (lambda(c) (modify-syntax-entry
-                     (string-to-char (car c)) "w p" st))
-         org-emphasis-alist)
-    st))
+  (let ((st (make-syntax-table text-mode-syntax-table)))
+    (dolist (c org-emphasis-alist st)
+      (modify-syntax-entry (string-to-char (car c)) "w p" st))))
 
 (when (fboundp 'abbrev-table-put)
   (abbrev-table-put org-mode-abbrev-table
                    :parents (list text-mode-abbrev-table)))
 
-(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
-
 (defun org-find-invisible-foreground ()
   (let ((candidates (remove
                     "unspecified-bg"
@@ -5498,7 +5715,7 @@ The following commands are available:
                      (mapcar
                       (lambda (alist)
                         (when (boundp alist)
-                          (cdr (assoc 'background-color (symbol-value 
alist)))))
+                          (cdr (assq 'background-color (symbol-value alist)))))
                       '(default-frame-alist initial-frame-alist 
window-system-default-frame-alist))
                      (list (face-foreground 'org-hide))))))
     (car (remove nil candidates))))
@@ -5541,8 +5758,6 @@ the rounding returns a past time."
 (require 'font-lock)
 
 (defconst org-non-link-chars "]\t\n\r<>")
-(defvar org-link-types '("http" "https" "ftp" "mailto" "file" "news"
-                        "shell" "elisp" "doi" "message"))
 (defvar org-link-types-re nil
   "Matches a link that has a url-like prefix like \"http:\"")
 (defvar org-link-re-with-space nil
@@ -5591,27 +5806,26 @@ stacked delimiters is N.  Escaping delimiters is not 
possible."
            next (concat "\\(?:" nothing left next right "\\)+" nothing)))
     (concat left "\\(" re "\\)" right)))
 
-(defvar org-match-substring-regexp
+(defconst org-match-substring-regexp
   (concat
    "\\(\\S-\\)\\([_^]\\)\\("
-   "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
+   "\\(?:" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
    "\\|"
-   "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
+   "\\(?:" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
    "\\|"
-   "\\(\\(?:\\*\\|address@hidden \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
+   "\\(?:\\*\\|[+-]?[[:alnum:].,\\]*[[:alnum:]]\\)\\)")
   "The regular expression matching a sub- or superscript.")
 
-(defvar org-match-substring-with-braces-regexp
+(defconst org-match-substring-with-braces-regexp
   (concat
-   "\\(\\S-\\)\\([_^]\\)\\("
-   "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
-   "\\)")
+   "\\(\\S-\\)\\([_^]\\)"
+   "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)")
   "The regular expression matching a sub- or superscript, forcing braces.")
 
 (defun org-make-link-regexps ()
   "Update the link regular expressions.
-This should be called after the variable `org-link-types' has changed."
-  (let ((types-re (regexp-opt org-link-types t)))
+This should be called after the variable `org-link-parameters' has changed."
+  (let ((types-re (regexp-opt (org-link-types) t)))
     (setq org-link-types-re
          (concat "\\`" types-re ":")
          org-link-re-with-space
@@ -5629,14 +5843,12 @@ This should be called after the variable 
`org-link-types' has changed."
                  "\\([^" org-non-link-chars " ]"
                  "[^\t\n\r]*\\)")
          org-angle-link-re
-         (concat "<" types-re ":"
-                 "\\([^" org-non-link-chars " ]"
-                 "[^" org-non-link-chars "]*"
-                 "\\)>")
+         (format "<%s:\\([^>\n]*\\(?:\n[ \t]*[^> \t\n][^>\n]*\\)*\\)>"
+                 types-re)
          org-plain-link-re
          (concat
           "\\<" types-re ":"
-          (org-re "\\([^ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] 
\t\n]\\|/\\)\\)\\)"))
+          "\\([^][ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] 
\t\n]\\|/\\)\\)\\)")
          ;;     "\\([^]\t\n\r<>() ]+[^]\t\n\r<>,.;() ]\\)")
          org-bracket-link-regexp
          "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
@@ -5651,77 +5863,46 @@ This should be called after the variable 
`org-link-types' has changed."
          org-bracket-link-analytic-regexp++
          (concat
           "\\[\\["
-          "\\(" (regexp-opt (cons "coderef" org-link-types) t) ":\\)?"
+          "\\(" (regexp-opt (cons "coderef" (org-link-types)) t) ":\\)?"
           "\\([^]]+\\)"
           "\\]"
           "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
-          "\\]")
-         org-any-link-re
-         (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
-                 org-angle-link-re "\\)\\|\\("
-                 org-plain-link-re "\\)"))))
-
-(org-make-link-regexps)
-
-(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^\r\n>]*?\\)>"
-  "Regular expression for fast time stamp matching.")
-(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^]\r\n>]*?\\)[]>]"
-  "Regular expression for fast time stamp matching.")
-(defconst org-ts-regexp0
-  "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\( 
+[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
-  "Regular expression matching time strings for analysis.
-This one does not require the space after the date, so it can be used
-on a string that terminates immediately after the date.")
-(defconst org-ts-regexp1 
"\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]+0-9>\r\n 
-]*\\)\\( \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
-  "Regular expression matching time strings for analysis.")
-(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>")
-  "Regular expression matching time stamps, with groups.")
-(defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]")
-  "Regular expression matching time stamps (also [..]), with groups.")
-(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
-  "Regular expression matching a time stamp range.")
-(defconst org-tr-regexp-both
-  (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
-  "Regular expression matching a time stamp range.")
-(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
-                                org-ts-regexp "\\)?")
-  "Regular expression matching a time stamp or time stamp range.")
-(defconst org-tsr-regexp-both
-  (concat org-ts-regexp-both "\\(--?-?"
-         org-ts-regexp-both "\\)?")
-  "Regular expression matching a time stamp or time stamp range.
-The time stamps may be either active or inactive.")
+          "\\]")
+         org-any-link-re
+         (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
+                 org-angle-link-re "\\)\\|\\("
+                 org-plain-link-re "\\)"))))
+
+(org-make-link-regexps)
 
 (defvar org-emph-face nil)
 
 (defun org-do-emphasis-faces (limit)
-  "Run through the buffer and add overlays to emphasized strings."
+  "Run through the buffer and emphasize strings."
   (let (rtn a)
     (while (and (not rtn) (re-search-forward org-emph-re limit t))
       (let* ((border (char-after (match-beginning 3)))
             (bre (regexp-quote (char-to-string border))))
-       (if (and (not (= border (char-after (match-beginning 4))))
-                (not (save-match-data
-                       (string-match (concat bre ".*" bre)
-                                     (replace-regexp-in-string
-                                      "\n" " "
-                                      (substring (match-string 2) 1 -1))))))
-           (progn
-             (setq rtn t)
-             (setq a (assoc (match-string 3) org-emphasis-alist))
-             (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
-                                              'face
-                                              (nth 1 a))
-             (and (nth 2 a)
-                  (org-remove-flyspell-overlays-in
-                   (match-beginning 0) (match-end 0)))
-             (add-text-properties (match-beginning 2) (match-end 2)
-                                  '(font-lock-multiline t org-emphasis t))
-             (when org-hide-emphasis-markers
-               (add-text-properties (match-end 4) (match-beginning 5)
-                                    '(invisible org-link))
-               (add-text-properties (match-beginning 3) (match-end 3)
-                                    '(invisible org-link))))))
+       (when (and (not (= border (char-after (match-beginning 4))))
+                  (not (string-match-p (concat bre ".*" bre)
+                                       (replace-regexp-in-string
+                                        "\n" " "
+                                        (substring (match-string 2) 1 -1)))))
+         (setq rtn t)
+         (setq a (assoc (match-string 3) org-emphasis-alist))
+         (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
+                                          'face
+                                          (nth 1 a))
+         (and (nth 2 a)
+              (org-remove-flyspell-overlays-in
+               (match-beginning 0) (match-end 0)))
+         (add-text-properties (match-beginning 2) (match-end 2)
+                              '(font-lock-multiline t org-emphasis t))
+         (when org-hide-emphasis-markers
+           (add-text-properties (match-end 4) (match-beginning 5)
+                                '(invisible org-link))
+           (add-text-properties (match-beginning 3) (match-end 3)
+                                '(invisible org-link)))))
       (goto-char (1+ (match-beginning 0))))
     rtn))
 
@@ -5736,19 +5917,20 @@ If CHAR is not given (for example in an interactive 
call) it will be
 prompted for."
   (interactive)
   (let ((erc org-emphasis-regexp-components)
-       (prompt "")
-       (string "") beg end move c s)
+       (string "") beg end move s)
     (if (org-region-active-p)
-       (setq beg (region-beginning) end (region-end)
+       (setq beg (region-beginning)
+             end (region-end)
              string (buffer-substring beg end))
       (setq move t))
 
     (unless char
       (message "Emphasis marker or tag: [%s]"
-              (mapconcat (lambda(e) (car e)) org-emphasis-alist ""))
+              (mapconcat #'car org-emphasis-alist ""))
       (setq char (read-char-exclusive)))
-    (if (equal char ?\ )
-       (setq s "" move nil)
+    (if (equal char ?\s)
+       (setq s ""
+             move nil)
       (unless (assoc (char-to-string char) org-emphasis-alist)
        (user-error "No such emphasis marker: \"%c\"" char))
       (setq s (char-to-string char)))
@@ -5757,7 +5939,7 @@ prompted for."
                (assoc (substring string 0 1) org-emphasis-alist))
       (setq string (substring string 1 -1)))
     (setq string (concat s string s))
-    (if beg (delete-region beg end))
+    (when beg (delete-region beg end))
     (unless (or (bolp)
                (string-match (concat "[" (nth 0 erc) "\n]")
                              (char-to-string (char-before (point)))))
@@ -5775,37 +5957,86 @@ prompted for."
 (defsubst org-rear-nonsticky-at (pos)
   (add-text-properties (1- pos) pos (list 'rear-nonsticky 
org-nonsticky-props)))
 
-(defun org-activate-plain-links (limit)
-  "Run through the buffer and add overlays to links."
-  (let (f hl)
-    (when (and (re-search-forward (concat org-plain-link-re) limit t)
-              (not (org-in-src-block-p)))
-      (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-      (setq f (get-text-property (match-beginning 0) 'face))
-      (setq hl (org-match-string-no-properties 0))
-      (if (or (eq f 'org-tag)
-             (and (listp f) (memq 'org-tag f)))
-         nil
-       (add-text-properties (match-beginning 0) (match-end 0)
-                            (list 'mouse-face 'highlight
-                                  'face 'org-link
-                                  'htmlize-link `(:uri ,hl)
-                                  'keymap org-mouse-map))
-       (org-rear-nonsticky-at (match-end 0)))
-      t)))
+(defun org-activate-links (limit)
+  "Add link properties to links.
+This includes angle, plain, and bracket links."
+  (catch :exit
+    (while (re-search-forward org-any-link-re limit t)
+      (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (style (cond ((eq ?< (char-after start)) 'angle)
+                         ((eq ?\[ (char-after (1+ start))) 'bracket)
+                         (t 'plain))))
+       (when (and (memq style org-highlight-links)
+                  ;; Do not confuse plain links with tags.
+                  (not (and (eq style 'plain)
+                            (let ((face (get-text-property
+                                         (max (1- start) (point-min)) 'face)))
+                              (if (consp face) (memq 'org-tag face)
+                                (eq 'org-tag face))))))
+         (let* ((link-object (save-excursion
+                               (goto-char start)
+                               (save-match-data (org-element-link-parser))))
+                (link (org-element-property :raw-link link-object))
+                (type (org-element-property :type link-object))
+                (path (org-element-property :path link-object))
+                (properties            ;for link's visible part
+                 (list
+                  'face (pcase (org-link-get-parameter type :face)
+                          ((and (pred functionp) face) (funcall face path))
+                          ((and (pred facep) face) face)
+                          ((and (pred consp) face) face) ;anonymous
+                          (_ 'org-link))
+                  'mouse-face (or (org-link-get-parameter type :mouse-face)
+                                  'highlight)
+                  'keymap (or (org-link-get-parameter type :keymap)
+                              org-mouse-map)
+                  'help-echo (pcase (org-link-get-parameter type :help-echo)
+                               ((and (pred stringp) echo) echo)
+                               ((and (pred functionp) echo) echo)
+                               (_ (concat "LINK: " link)))
+                  'htmlize-link (pcase (org-link-get-parameter type
+                                                               :htmlize-link)
+                                  ((and (pred functionp) f) (funcall f))
+                                  (_ `(:uri ,link)))
+                  'font-lock-multiline t)))
+           (org-remove-flyspell-overlays-in start end)
+           (org-rear-nonsticky-at end)
+           (if (not (eq 'bracket style))
+               (add-text-properties start end properties)
+             ;; Handle invisible parts in bracket links.
+             (remove-text-properties start end '(invisible nil))
+             (let ((hidden
+                    (append `(invisible
+                              ,(or (org-link-get-parameter type :display)
+                                   'org-link))
+                            properties))
+                   (visible-start (or (match-beginning 4) (match-beginning 2)))
+                   (visible-end (or (match-end 4) (match-end 2))))
+               (add-text-properties start visible-start hidden)
+               (add-text-properties visible-start visible-end properties)
+               (add-text-properties visible-end end hidden)
+               (org-rear-nonsticky-at visible-start)
+               (org-rear-nonsticky-at visible-end)))
+           (let ((f (org-link-get-parameter type :activate-func)))
+             (when (functionp f)
+               (funcall f start end path (eq style 'bracket))))
+           (throw :exit t)))))         ;signal success
+    nil))
 
 (defun org-activate-code (limit)
-  (if (re-search-forward "^[ \t]*\\(:\\(?: .*\\|$\\)\n?\\)" limit t)
-      (progn
-       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-       (remove-text-properties (match-beginning 0) (match-end 0)
-                               '(display t invisible t intangible t))
-       t)))
+  (when (re-search-forward "^[ \t]*\\(:\\(?: .*\\|$\\)\n?\\)" limit t)
+    (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
+    (remove-text-properties (match-beginning 0) (match-end 0)
+                           '(display t invisible t intangible t))
+    t))
 
-(defcustom org-src-fontify-natively nil
-  "When non-nil, fontify code in code blocks."
+(defcustom org-src-fontify-natively t
+  "When non-nil, fontify code in code blocks.
+See also the `org-block' face."
   :type 'boolean
-  :version "24.1"
+  :version "24.4"
+  :package-version '(Org . "8.3")
   :group 'org-appearance
   :group 'org-babel)
 
@@ -5820,221 +6051,248 @@ by a #."
 (defun org-fontify-meta-lines-and-blocks (limit)
   (condition-case nil
       (org-fontify-meta-lines-and-blocks-1 limit)
-    (error (message "org-mode fontification error"))))
+    (error (message "org-mode fontification error in %S at %d"
+                   (current-buffer)
+                   (line-number-at-pos)))))
 
 (defun org-fontify-meta-lines-and-blocks-1 (limit)
   "Fontify #+ lines and blocks."
   (let ((case-fold-search t))
-    (if (re-search-forward
-        "^\\([ \t]*#\\(\\(\\+[a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ 
\t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)"
-        limit t)
-       (let ((beg (match-beginning 0))
-             (block-start (match-end 0))
-             (block-end nil)
-             (lang (match-string 7))
-             (beg1 (line-beginning-position 2))
-             (dc1 (downcase (match-string 2)))
-             (dc3 (downcase (match-string 3)))
-             end end1 quoting block-type ovl)
-         (cond
-          ((member dc1 '("+html:" "+ascii:" "+latex:"))
-           ;; a single line of backend-specific content
-           (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-           (remove-text-properties (match-beginning 0) (match-end 0)
-                                   '(display t invisible t intangible t))
-           (add-text-properties (match-beginning 1) (match-end 3)
-                                '(font-lock-fontified t face org-meta-line))
-           (add-text-properties (match-beginning 6) (+ (match-end 6) 1)
-                                '(font-lock-fontified t face org-block))
-                                       ; for backend-specific code
-           t)
-          ((and (match-end 4) (equal dc3 "+begin"))
-           ;; Truly a block
-           (setq block-type (downcase (match-string 5))
-                 quoting (member block-type org-protecting-blocks))
-           (when (re-search-forward
-                  (concat "^[ \t]*#\\+end" (match-string 4) "\\>.*")
-                  nil t)  ;; on purpose, we look further than LIMIT
-             (setq end (min (point-max) (match-end 0))
-                   end1 (min (point-max) (1- (match-beginning 0))))
-             (setq block-end (match-beginning 0))
-             (when quoting
-               (remove-text-properties beg end
-                                       '(display t invisible t intangible t)))
-             (add-text-properties
-              beg end
-              '(font-lock-fontified t font-lock-multiline t))
-             (add-text-properties beg beg1 '(face org-meta-line))
-             (add-text-properties end1 (min (point-max) (1+ end))
-                                  '(face org-meta-line)) ; for end_src
-             (cond
-              ((and lang (not (string= lang "")) org-src-fontify-natively)
-               (org-src-font-lock-fontify-block lang block-start block-end)
-               ;; remove old background overlays
-               (mapc (lambda (ov)
-                       (if (eq (overlay-get ov 'face) 'org-block-background)
-                           (delete-overlay ov)))
-                     (overlays-at (/ (+ beg1 block-end) 2)))
-               ;; add a background overlay
-               (setq ovl (make-overlay beg1 block-end))
-                (overlay-put ovl 'face 'org-block-background)
-                (overlay-put ovl 'evaporate t))  ;; make it go away when empty
-              (quoting
-               (add-text-properties beg1 (min (point-max) (1+ end1))
-                                    '(face org-block))) ; end of source block
-              ((not org-fontify-quote-and-verse-blocks))
-              ((string= block-type "quote")
-               (add-text-properties beg1 (min (point-max) (1+ end1)) '(face 
org-quote)))
-              ((string= block-type "verse")
-               (add-text-properties beg1 (min (point-max) (1+ end1)) '(face 
org-verse))))
-             (add-text-properties beg beg1 '(face org-block-begin-line))
-             (add-text-properties (min (point-max) (1+ end)) (min (point-max) 
(1+ end1))
-                                  '(face org-block-end-line))
-             t))
-          ((member dc1 '("+title:" "+author:" "+email:" "+date:"))
-           (add-text-properties
-            beg (match-end 3)
-            (if (member (intern (substring dc1 1 -1)) org-hidden-keywords)
-                '(font-lock-fontified t invisible t)
-              '(font-lock-fontified t face org-document-info-keyword)))
-           (add-text-properties
-            (match-beginning 6) (min (point-max) (1+ (match-end 6)))
-            (if (string-equal dc1 "+title:")
-                '(font-lock-fontified t face org-document-title)
-              '(font-lock-fontified t face org-document-info))))
-          ((or (equal dc1 "+results")
-               (member dc1 '("+begin:" "+end:" "+caption:" "+label:"
-                             "+orgtbl:" "+tblfm:" "+tblname:" "+results:"
-                             "+call:" "+header:" "+headers:" "+name:"))
-               (and (match-end 4) (equal dc3 "+attr")))
-           (add-text-properties
-            beg (match-end 0)
-            '(font-lock-fontified t face org-meta-line))
-           t)
-          ((member dc3 '(" " ""))
-           (add-text-properties
-            beg (match-end 0)
-            '(font-lock-fontified t face font-lock-comment-face)))
-          ((not (member (char-after beg) '(?\  ?\t)))
-           ;; just any other in-buffer setting, but not indented
+    (when (re-search-forward
+          "^\\([ \t]*#\\(\\(\\+[a-zA-Z]+:?\\| 
\\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ \t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)"
+          limit t)
+      (let ((beg (match-beginning 0))
+           (block-start (match-end 0))
+           (block-end nil)
+           (lang (match-string 7))
+           (beg1 (line-beginning-position 2))
+           (dc1 (downcase (match-string 2)))
+           (dc3 (downcase (match-string 3)))
+           end end1 quoting block-type)
+       (cond
+        ((and (match-end 4) (equal dc3 "+begin"))
+         ;; Truly a block
+         (setq block-type (downcase (match-string 5))
+               quoting (member block-type org-protecting-blocks))
+         (when (re-search-forward
+                (concat "^[ \t]*#\\+end" (match-string 4) "\\>.*")
+                nil t)  ;; on purpose, we look further than LIMIT
+           (setq end (min (point-max) (match-end 0))
+                 end1 (min (point-max) (1- (match-beginning 0))))
+           (setq block-end (match-beginning 0))
+           (when quoting
+             (org-remove-flyspell-overlays-in beg1 end1)
+             (remove-text-properties beg end
+                                     '(display t invisible t intangible t)))
            (add-text-properties
-            beg (match-end 0)
-            '(font-lock-fontified t face org-meta-line))
-           t)
-          (t nil))))))
-
-(defun org-activate-angle-links (limit)
-  "Run through the buffer and add overlays to links."
-  (if (and (re-search-forward org-angle-link-re limit t)
-          (not (org-in-src-block-p)))
-      (progn
-       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-       (add-text-properties (match-beginning 0) (match-end 0)
-                            (list 'mouse-face 'highlight
-                                  'keymap org-mouse-map))
-       (org-rear-nonsticky-at (match-end 0))
-       t)))
+            beg end '(font-lock-fontified t font-lock-multiline t))
+           (add-text-properties beg beg1 '(face org-meta-line))
+           (org-remove-flyspell-overlays-in beg beg1)
+           (add-text-properties        ; For end_src
+            end1 (min (point-max) (1+ end)) '(face org-meta-line))
+           (org-remove-flyspell-overlays-in end1 end)
+           (cond
+            ((and lang (not (string= lang "")) org-src-fontify-natively)
+             (org-src-font-lock-fontify-block lang block-start block-end)
+             (add-text-properties beg1 block-end '(src-block t)))
+            (quoting
+             (add-text-properties beg1 (min (point-max) (1+ end1))
+                                  (list 'face
+                                        (list :inherit
+                                              (let ((face-name
+                                                     (intern (format 
"org-block-%s" lang))))
+                                                (append (and (facep face-name) 
(list face-name))
+                                                        '(org-block))))))) ; 
end of source block
+            ((not org-fontify-quote-and-verse-blocks))
+            ((string= block-type "quote")
+             (add-face-text-property
+              beg1 (min (point-max) (1+ end1)) 'org-quote t))
+            ((string= block-type "verse")
+             (add-face-text-property
+              beg1 (min (point-max) (1+ end1)) 'org-verse t)))
+           (add-text-properties beg beg1 '(face org-block-begin-line))
+           (add-text-properties (min (point-max) (1+ end)) (min (point-max) 
(1+ end1))
+                                '(face org-block-end-line))
+           t))
+        ((member dc1 '("+title:" "+author:" "+email:" "+date:"))
+         (org-remove-flyspell-overlays-in
+          (match-beginning 0)
+          (if (equal "+title:" dc1) (match-end 2) (match-end 0)))
+         (add-text-properties
+          beg (match-end 3)
+          (if (member (intern (substring dc1 1 -1)) org-hidden-keywords)
+              '(font-lock-fontified t invisible t)
+            '(font-lock-fontified t face org-document-info-keyword)))
+         (add-text-properties
+          (match-beginning 6) (min (point-max) (1+ (match-end 6)))
+          (if (string-equal dc1 "+title:")
+              '(font-lock-fontified t face org-document-title)
+            '(font-lock-fontified t face org-document-info))))
+        ((string-prefix-p "+caption" dc1)
+         (org-remove-flyspell-overlays-in (match-end 2) (match-end 0))
+         (remove-text-properties (match-beginning 0) (match-end 0)
+                                 '(display t invisible t intangible t))
+         ;; Handle short captions.
+         (save-excursion
+           (beginning-of-line)
+           (looking-at "\\([ \t]*#\\+caption\\(?:\\[.*\\]\\)?:\\)[ \t]*"))
+         (add-text-properties (line-beginning-position) (match-end 1)
+                              '(font-lock-fontified t face org-meta-line))
+         (add-text-properties (match-end 0) (line-end-position)
+                              '(font-lock-fontified t face org-block))
+         t)
+        ((member dc3 '(" " ""))
+         (org-remove-flyspell-overlays-in beg (match-end 0))
+         (add-text-properties
+          beg (match-end 0)
+          '(font-lock-fontified t face font-lock-comment-face)))
+        (t ;; just any other in-buffer setting, but not indented
+         (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
+         (remove-text-properties (match-beginning 0) (match-end 0)
+                                 '(display t invisible t intangible t))
+         (add-text-properties beg (match-end 0)
+                              '(font-lock-fontified t face org-meta-line))
+         t))))))
+
+(defun org-fontify-drawers (limit)
+  "Fontify drawers."
+  (when (re-search-forward org-drawer-regexp limit t)
+    (add-text-properties
+     (match-beginning 0) (match-end 0)
+     '(font-lock-fontified t face org-special-keyword))
+    (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
+    t))
+
+(defun org-fontify-macros (limit)
+  "Fontify macros."
+  (when (re-search-forward "\\({{{\\).+?\\(}}}\\)" limit t)
+    (add-text-properties
+     (match-beginning 0) (match-end 0)
+     '(font-lock-fontified t face org-macro))
+    (when org-hide-macro-markers
+      (add-text-properties (match-end 2) (match-beginning 2)
+                          '(invisible t))
+      (add-text-properties (match-beginning 1) (match-end 1)
+                          '(invisible t)))
+    (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
+    t))
 
 (defun org-activate-footnote-links (limit)
-  "Run through the buffer and add overlays to footnotes."
+  "Add text properties for footnotes."
   (let ((fn (org-footnote-next-reference-or-definition limit)))
     (when fn
-      (let ((beg (nth 1 fn)) (end (nth 2 fn)))
-       (org-remove-flyspell-overlays-in beg end)
+      (let* ((beg (nth 1 fn))
+            (end (nth 2 fn))
+            (label (car fn))
+            (referencep (/= (line-beginning-position) beg)))
+       (when (and referencep (nth 3 fn))
+         (save-excursion
+           (goto-char beg)
+           (search-forward (or label "fn:"))
+           (org-remove-flyspell-overlays-in beg (match-end 0))))
        (add-text-properties beg end
                             (list 'mouse-face 'highlight
                                   'keymap org-mouse-map
                                   'help-echo
-                                  (if (= (point-at-bol) beg)
-                                      "Footnote definition"
-                                    "Footnote reference")
+                                  (if referencep "Footnote reference"
+                                    "Footnote definition")
                                   'font-lock-fontified t
                                   'font-lock-multiline t
                                   'face 'org-footnote))))))
 
-(defun org-activate-bracket-links (limit)
-  "Run through the buffer and add overlays to bracketed links."
-  (if (and (re-search-forward org-bracket-link-regexp limit t)
-          (not (org-in-src-block-p)))
-      (let* ((hl (org-match-string-no-properties 1))
-            (help (concat "LINK: " (save-match-data (org-link-unescape hl))))
-            (ip (org-maybe-intangible
-                 (list 'invisible 'org-link
-                       'keymap org-mouse-map 'mouse-face 'highlight
-                       'font-lock-multiline t 'help-echo help
-                       'htmlize-link `(:uri ,hl))))
-            (vp (list 'keymap org-mouse-map 'mouse-face 'highlight
-                      'font-lock-multiline t 'help-echo help
-                      'htmlize-link `(:uri ,hl))))
-       ;; We need to remove the invisible property here.  Table narrowing
-       ;; may have made some of this invisible.
-       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-       (remove-text-properties (match-beginning 0) (match-end 0)
-                               '(invisible nil))
-       (if (match-end 3)
-           (progn
-             (add-text-properties (match-beginning 0) (match-beginning 3) ip)
-             (org-rear-nonsticky-at (match-beginning 3))
-             (add-text-properties (match-beginning 3) (match-end 3) vp)
-             (org-rear-nonsticky-at (match-end 3))
-             (add-text-properties (match-end 3) (match-end 0) ip)
-             (org-rear-nonsticky-at (match-end 0)))
-         (add-text-properties (match-beginning 0) (match-beginning 1) ip)
-         (org-rear-nonsticky-at (match-beginning 1))
-         (add-text-properties (match-beginning 1) (match-end 1) vp)
-         (org-rear-nonsticky-at (match-end 1))
-         (add-text-properties (match-end 1) (match-end 0) ip)
-         (org-rear-nonsticky-at (match-end 0)))
-       t)))
-
 (defun org-activate-dates (limit)
-  "Run through the buffer and add overlays to dates."
-  (if (and (re-search-forward org-tsr-regexp-both limit t)
-          (not (equal (char-before (match-beginning 0)) 91)))
-      (progn
-       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-       (add-text-properties (match-beginning 0) (match-end 0)
-                            (list 'mouse-face 'highlight
-                                  'keymap org-mouse-map))
-       (org-rear-nonsticky-at (match-end 0))
-       (when org-display-custom-times
-         (if (match-end 3)
-             (org-display-custom-time (match-beginning 3) (match-end 3)))
-         (org-display-custom-time (match-beginning 1) (match-end 1)))
-       t)))
-
-(defvar org-target-link-regexp nil
+  "Add text properties for dates."
+  (when (and (re-search-forward org-tsr-regexp-both limit t)
+            (not (equal (char-before (match-beginning 0)) 91)))
+    (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
+    (add-text-properties (match-beginning 0) (match-end 0)
+                        (list 'mouse-face 'highlight
+                              'keymap org-mouse-map))
+    (org-rear-nonsticky-at (match-end 0))
+    (when org-display-custom-times
+      (if (match-end 3)
+         (org-display-custom-time (match-beginning 3) (match-end 3))
+       (org-display-custom-time (match-beginning 1) (match-end 1))))
+    t))
+
+(defvar-local org-target-link-regexp nil
   "Regular expression matching radio targets in plain text.")
-(make-variable-buffer-local 'org-target-link-regexp)
-(defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
+
+(defconst org-target-regexp (let ((border "[^<>\n\r \t]"))
+                             (format "<<\\(%s\\|%s[^<>\n\r]*%s\\)>>"
+                                     border border border))
   "Regular expression matching a link target.")
-(defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
+
+(defconst org-radio-target-regexp (format "<%s>" org-target-regexp)
   "Regular expression matching a radio target.")
-(defvar org-any-target-regexp "<<<?\\([^<>\n\r]+\\)>>>?" ; FIXME, not exact, 
would match <<<aaa>>  as a radio target.
+
+(defconst org-any-target-regexp
+  (format "%s\\|%s" org-radio-target-regexp org-target-regexp)
   "Regular expression matching any target.")
 
 (defun org-activate-target-links (limit)
-  "Run through the buffer and add overlays to target matches."
+  "Add text properties for target matches."
   (when org-target-link-regexp
     (let ((case-fold-search t))
-      (if (re-search-forward org-target-link-regexp limit t)
-         (progn
-           (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
-           (add-text-properties (match-beginning 0) (match-end 0)
-                                (list 'mouse-face 'highlight
-                                      'keymap org-mouse-map
-                                      'help-echo "Radio target link"
-                                      'org-linked-text t))
-           (org-rear-nonsticky-at (match-end 0))
-           t)))))
+      (when (re-search-forward org-target-link-regexp limit t)
+       (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1))
+       (add-text-properties (match-beginning 1) (match-end 1)
+                            (list 'mouse-face 'highlight
+                                  'keymap org-mouse-map
+                                  'help-echo "Radio target link"
+                                  'org-linked-text t))
+       (org-rear-nonsticky-at (match-end 1))
+       t))))
 
 (defun org-update-radio-target-regexp ()
-  "Find all radio targets in this file and update the regular expression."
+  "Find all radio targets in this file and update the regular expression.
+Also refresh fontification if needed."
   (interactive)
-  (when (memq 'radio org-activate-links)
+  (let ((old-regexp org-target-link-regexp)
+       (before-re "\\(?:^\\|[^[:alnum:]]\\)\\(")
+       (after-re "\\)\\(?:$\\|[^[:alnum:]]\\)")
+       (targets
+        (org-with-wide-buffer
+         (goto-char (point-min))
+         (let (rtn)
+           (while (re-search-forward org-radio-target-regexp nil t)
+             ;; Make sure point is really within the object.
+             (backward-char)
+             (let ((obj (org-element-context)))
+               (when (eq (org-element-type obj) 'radio-target)
+                 (cl-pushnew (org-element-property :value obj) rtn
+                             :test #'equal))))
+           rtn))))
     (setq org-target-link-regexp
-         (org-make-target-link-regexp (org-all-targets 'radio)))
-    (org-restart-font-lock)))
+         (and targets
+              (concat before-re
+                      (mapconcat
+                       (lambda (x)
+                         (replace-regexp-in-string
+                          " +" "\\s-+" (regexp-quote x) t t))
+                       targets
+                       "\\|")
+                      after-re)))
+    (unless (equal old-regexp org-target-link-regexp)
+      ;; Clean-up cache.
+      (let ((regexp (cond ((not old-regexp) org-target-link-regexp)
+                         ((not org-target-link-regexp) old-regexp)
+                         (t
+                          (concat before-re
+                                  (mapconcat
+                                   (lambda (re)
+                                     (substring re (length before-re)
+                                                (- (length after-re))))
+                                   (list old-regexp org-target-link-regexp)
+                                   "\\|")
+                                  after-re)))))
+       (org-with-wide-buffer
+        (goto-char (point-min))
+        (while (re-search-forward regexp nil t)
+          (org-element-cache-refresh (match-beginning 1)))))
+      ;; Re fontify buffer.
+      (when (memq 'radio org-highlight-links)
+       (org-restart-font-lock)))))
 
 (defun org-hide-wide-columns (limit)
   (let (s e)
@@ -6042,20 +6300,18 @@ by a #."
                               'org-cwidth t))
     (when s
       (setq e (next-single-property-change s 'org-cwidth))
-      (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
+      (add-text-properties s e '(invisible org-cwidth))
       (goto-char e)
       t)))
 
 (defvar org-latex-and-related-regexp nil
   "Regular expression for highlighting LaTeX, entities and sub/superscript.")
-(defvar org-match-substring-regexp)
-(defvar org-match-substring-with-braces-regexp)
 
 (defun org-compute-latex-and-related-regexp ()
   "Compute regular expression for LaTeX, entities and sub/superscript.
 Result depends on variable `org-highlight-latex-and-related'."
-  (org-set-local
-   'org-latex-and-related-regexp
+  (setq-local
+   org-latex-and-related-regexp
    (let* ((re-sub
           (cond ((not (memq 'script org-highlight-latex-and-related)) nil)
                 ((eq org-use-sub-superscripts '{})
@@ -6081,9 +6337,13 @@ done, nil otherwise."
   (when (org-string-nw-p org-latex-and-related-regexp)
     (catch 'found
       (while (re-search-forward org-latex-and-related-regexp limit t)
-       (unless (memq (car-safe (get-text-property (1+ (match-beginning 0))
-                                                  'face))
-                     '(org-code org-verbatim underline))
+       (unless
+           (cl-some
+            (lambda (f)
+              (memq f '(org-code org-verbatim underline org-special-keyword)))
+            (save-excursion
+              (goto-char (1+ (match-beginning 0)))
+              (face-at-point nil t)))
          (let ((offset (if (memq (char-after (1+ (match-beginning 0)))
                                  '(?_ ?^))
                            1
@@ -6102,63 +6362,32 @@ done, nil otherwise."
     (font-lock-mode -1)
     (font-lock-mode 1)))
 
-(defun org-all-targets (&optional radio)
-  "Return a list of all targets in this file.
-When optional argument RADIO is non-nil, only find radio
-targets."
-  (let ((re (if radio org-radio-target-regexp org-target-regexp)) rtn)
-    (save-excursion
-      (goto-char (point-min))
-      (while (re-search-forward re nil t)
-       ;; Make sure point is really within the object.
-       (backward-char)
-       (let ((obj (org-element-context)))
-         (when (memq (org-element-type obj) '(radio-target target))
-           (add-to-list 'rtn (downcase (org-element-property :value obj))))))
-      rtn)))
-
-(defun org-make-target-link-regexp (targets)
-  "Make regular expression matching all strings in TARGETS.
-The regular expression finds the targets also if there is a line break
-between words."
-  (and targets
-       (concat
-       "\\_<\\("
-       (mapconcat
-        (lambda (x)
-          (setq x (regexp-quote x))
-          (while (string-match " +" x)
-            (setq x (replace-match "\\s-+" t t x)))
-          x)
-        targets
-        "\\|")
-       "\\)\\_>")))
-
 (defun org-activate-tags (limit)
-  (if (re-search-forward (org-re "^\\*+.*[ 
\t]\\(:[[:alnum:address@hidden:]+:\\)[ \r\n]") limit t)
-      (progn
-       (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1))
-       (add-text-properties (match-beginning 1) (match-end 1)
-                            (list 'mouse-face 'highlight
-                                  'keymap org-mouse-map))
-       (org-rear-nonsticky-at (match-end 1))
-       t)))
+  (when (re-search-forward
+        "^\\*+.*[ \t]\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$" limit t)
+    (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1))
+    (add-text-properties (match-beginning 1) (match-end 1)
+                        (list 'mouse-face 'highlight
+                              'keymap org-mouse-map))
+    (org-rear-nonsticky-at (match-end 1))
+    t))
 
 (defun org-outline-level ()
   "Compute the outline level of the heading at point.
-If this is called at a normal headline, the level is the number of stars.
-Use `org-reduced-level' to remove the effect of `org-odd-levels'."
-  (save-excursion
-    (if (not (condition-case nil
-                (org-back-to-heading t)
-              (error nil)))
-       0
-      (looking-at org-outline-regexp)
-      (1- (- (match-end 0) (match-beginning 0))))))
+
+If this is called at a normal headline, the level is the number
+of stars.  Use `org-reduced-level' to remove the effect of
+`org-odd-levels'.  Unlike to `org-current-level', this function
+takes into consideration inlinetasks."
+  (org-with-wide-buffer
+   (end-of-line)
+   (if (re-search-backward org-outline-regexp-bol nil t)
+       (1- (- (match-end 0) (match-beginning 0)))
+     0)))
 
 (defvar org-font-lock-keywords nil)
 
-(defsubst org-re-property (property &optional literal allow-null)
+(defsubst org-re-property (property &optional literal allow-null value)
   "Return a regexp matching a PROPERTY line.
 
 When optional argument LITERAL is non-nil, do not quote PROPERTY.
@@ -6166,17 +6395,25 @@ This is useful when PROPERTY is a regexp.  When 
ALLOW-NULL is
 non-nil, match properties even without a value.
 
 Match group 3 is set to the value when it exists.  If there is no
-value and ALLOW-NULL is non-nil, it is set to the empty string."
+value and ALLOW-NULL is non-nil, it is set to the empty string.
+
+With optional argument VALUE, match only property lines with
+that value; in this case, ALLOW-NULL is ignored.  VALUE is quoted
+unless LITERAL is non-nil."
   (concat
    "^\\(?4:[ \t]*\\)"
    (format "\\(?1::\\(?2:%s\\):\\)"
           (if literal property (regexp-quote property)))
-   (if allow-null
-       "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$"
-     "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$")))
+   (cond (value
+         (format "[ \t]+\\(?3:%s\\)\\(?5:[ \t]*\\)$"
+                 (if literal value (regexp-quote value))))
+        (allow-null
+         "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$")
+        (t
+         "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$"))))
 
 (defconst org-property-re
-  (org-re-property ".*?" 'literal t)
+  (org-re-property "\\S-+" 'literal t)
   "Regular expression matching a property line.
 There are four matching groups:
 1: :PROPKEY: including the leading and trailing colon,
@@ -6188,6 +6425,8 @@ There are four matching groups:
 (defvar org-font-lock-hook nil
   "Functions to be called for special font lock stuff.")
 
+(defvar org-font-lock-extra-keywords nil) ;Dynamically scoped.
+
 (defvar org-font-lock-set-keywords-hook nil
   "Functions that can manipulate `org-font-lock-extra-keywords'.
 This is called after `org-font-lock-extra-keywords' is defined, but before
@@ -6201,7 +6440,7 @@ needs to be inserted at a specific position in the 
font-lock sequence.")
 (defun org-set-font-lock-defaults ()
   "Set font lock defaults for the current buffer."
   (let* ((em org-fontify-emphasized-text)
-        (lk org-activate-links)
+        (lk org-highlight-links)
         (org-font-lock-extra-keywords
          (list
           ;; Call the hook
@@ -6222,26 +6461,23 @@ needs to be inserted at a specific position in the 
font-lock sequence.")
           '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
           '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t))
           ;; Drawers
-          (list org-drawer-regexp '(0 'org-special-keyword t))
-          (list "^[ \t]*:END:" '(0 'org-special-keyword t))
+          '(org-fontify-drawers)
           ;; Properties
           (list org-property-re
                 '(1 'org-special-keyword t)
                 '(3 'org-property-value t))
-          ;; Links
-          (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
-          (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
-          (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
-          (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
-          (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
-          (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
-          (if (memq 'footnote lk) '(org-activate-footnote-links))
+          ;; Link related fontification.
+          '(org-activate-links)
+          (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
+          (when (memq 'radio lk) '(org-activate-target-links (1 'org-link t)))
+          (when (memq 'date lk) '(org-activate-dates (0 'org-date t)))
+          (when (memq 'footnote lk) '(org-activate-footnote-links))
            ;; Targets.
            (list org-any-target-regexp '(0 'org-target t))
           ;; Diary sexps.
           '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
           ;; Macro
-          '("{{{.+}}}" (0 'org-macro t))
+          '(org-fontify-macros)
           '(org-hide-wide-columns (0 nil append))
           ;; TODO keyword
           (list (format org-heading-keyword-regexp-format
@@ -6261,27 +6497,24 @@ needs to be inserted at a specific position in the 
font-lock sequence.")
           ;; Tags
           '(org-font-lock-add-tag-faces)
           ;; Tags groups
-          (if (and org-group-tags org-tag-groups-alist)
-              (list (concat org-outline-regexp-bol ".+\\(:"
-                            (regexp-opt (mapcar 'car org-tag-groups-alist))
-                            ":\\).*$")
-                    '(1 'org-tag-group prepend)))
+          (when (and org-group-tags org-tag-groups-alist)
+            (list (concat org-outline-regexp-bol ".+\\(:"
+                          (regexp-opt (mapcar 'car org-tag-groups-alist))
+                          ":\\).*$")
+                  '(1 'org-tag-group prepend)))
           ;; Special keywords
           (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
           (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword 
t))
           (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
           (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
           ;; Emphasis
-          (if em
-               (if (featurep 'xemacs)
-                   '(org-do-emphasis-faces (0 nil append))
-                 '(org-do-emphasis-faces)))
+          (when em '(org-do-emphasis-faces))
           ;; Checkboxes
           '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ 
\t]+\\(?:address@hidden(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
             1 'org-checkbox prepend)
-          (if (cdr (assq 'checkbox org-list-automatic-rules))
-              '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
-                (0 (org-get-checkbox-statistics-face) t)))
+          (when (cdr (assq 'checkbox org-list-automatic-rules))
+            '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
+              (0 (org-get-checkbox-statistics-face) t)))
           ;; Description list items
           '("^[ \t]*[-+*][ \t]+\\(.*?[ \t]+::\\)\\([ \t]+\\|$\\)"
             1 'org-list-dt prepend)
@@ -6297,83 +6530,92 @@ needs to be inserted at a specific position in the 
font-lock sequence.")
           ;; Code
           '(org-activate-code (1 'org-code t))
           ;; COMMENT
-          (list (format org-heading-keyword-regexp-format
-                        (concat "\\("
-                                org-comment-string "\\|" org-quote-string
-                                "\\)"))
-                '(2 'org-special-keyword t))
+          (list (format
+                 "^\\*+\\(?: +%s\\)?\\(?: +\\[#[A-Z0-9]\\]\\)? 
+\\(?9:%s\\)\\(?: \\|$\\)"
+                 org-todo-regexp
+                 org-comment-string)
+                '(9 'org-special-keyword t))
           ;; Blocks and meta lines
           '(org-fontify-meta-lines-and-blocks))))
     (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
     (run-hooks 'org-font-lock-set-keywords-hook)
     ;; Now set the full font-lock-keywords
-    (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
-    (org-set-local 'font-lock-defaults
-                  '(org-font-lock-keywords t nil nil backward-paragraph))
-    (kill-local-variable 'font-lock-keywords) nil))
+    (setq-local org-font-lock-keywords org-font-lock-extra-keywords)
+    (setq-local font-lock-defaults
+               '(org-font-lock-keywords t nil nil backward-paragraph))
+    (kill-local-variable 'font-lock-keywords)
+    nil))
 
 (defun org-toggle-pretty-entities ()
   "Toggle the composition display of entities as UTF8 characters."
   (interactive)
-  (org-set-local 'org-pretty-entities (not org-pretty-entities))
+  (setq-local org-pretty-entities (not org-pretty-entities))
   (org-restart-font-lock)
   (if org-pretty-entities
       (message "Entities are now displayed as UTF8 characters")
     (save-restriction
       (widen)
-      (org-decompose-region (point-min) (point-max))
+      (decompose-region (point-min) (point-max))
       (message "Entities are now displayed as plain text"))))
 
-(defvar org-custom-properties-overlays nil
+(defvar-local org-custom-properties-overlays nil
   "List of overlays used for custom properties.")
-(make-variable-buffer-local 'org-custom-properties-overlays)
 
 (defun org-toggle-custom-properties-visibility ()
   "Display or hide properties in `org-custom-properties'."
   (interactive)
   (if org-custom-properties-overlays
-      (progn (mapc 'delete-overlay org-custom-properties-overlays)
+      (progn (mapc #'delete-overlay org-custom-properties-overlays)
             (setq org-custom-properties-overlays nil))
-    (unless (not org-custom-properties)
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (while (re-search-forward org-property-re nil t)
-           (mapc (lambda(p)
-                   (when (equal p (substring (match-string 1) 1 -1))
-                     (let ((o (make-overlay (match-beginning 0) (1+ (match-end 
0)))))
-                       (overlay-put o 'invisible t)
-                       (overlay-put o 'org-custom-property t)
-                       (push o org-custom-properties-overlays))))
-                 org-custom-properties)))))))
+    (when org-custom-properties
+      (org-with-wide-buffer
+       (goto-char (point-min))
+       (let ((regexp (org-re-property (regexp-opt org-custom-properties) t t)))
+        (while (re-search-forward regexp nil t)
+          (let ((end (cdr (save-match-data (org-get-property-block)))))
+            (when (and end (< (point) end))
+              ;; Hide first custom property in current drawer.
+              (let ((o (make-overlay (match-beginning 0) (1+ (match-end 0)))))
+                (overlay-put o 'invisible t)
+                (overlay-put o 'org-custom-property t)
+                (push o org-custom-properties-overlays))
+              ;; Hide additional custom properties in the same drawer.
+              (while (re-search-forward regexp end t)
+                (let ((o (make-overlay (match-beginning 0) (1+ (match-end 
0)))))
+                  (overlay-put o 'invisible t)
+                  (overlay-put o 'org-custom-property t)
+                  (push o org-custom-properties-overlays)))))
+          ;; Each entry is limited to a single property drawer.
+          (outline-next-heading)))))))
 
 (defun org-fontify-entities (limit)
   "Find an entity to fontify."
   (let (ee)
     (when org-pretty-entities
       (catch 'match
+       ;; "\_ "-family is left out on purpose.  Only the first one,
+       ;; i.e., "\_ ", could be fontified anyway, and it would be
+       ;; confusing when adding a second white space character.
        (while (re-search-forward
                
"\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]\n]\\)"
                limit t)
-         (if (and (not (org-in-indented-comment-line))
-                  (setq ee (org-entity-get (match-string 1)))
-                  (= (length (nth 6 ee)) 1))
-             (let*
-                 ((end (if (equal (match-string 2) "{}")
+         (when (and (not (org-at-comment-p))
+                    (setq ee (org-entity-get (match-string 1)))
+                    (= (length (nth 6 ee)) 1))
+           (let* ((end (if (equal (match-string 2) "{}")
                            (match-end 2)
                          (match-end 1))))
-               (add-text-properties
-                (match-beginning 0) end
-                (list 'font-lock-fontified t))
-               (compose-region (match-beginning 0) end
-                               (nth 6 ee) nil)
-               (backward-char 1)
-               (throw 'match t))))
+             (add-text-properties
+              (match-beginning 0) end
+              (list 'font-lock-fontified t))
+             (compose-region (match-beginning 0) end
+                             (nth 6 ee) nil)
+             (backward-char 1)
+             (throw 'match t))))
        nil))))
 
 (defun org-fontify-like-in-org-mode (s &optional odd-levels)
-  "Fontify string S like in Org-mode."
+  "Fontify string S like in Org mode."
   (with-temp-buffer
     (insert s)
     (let ((org-odd-levels-only odd-levels))
@@ -6387,33 +6629,55 @@ needs to be inserted at a specific position in the 
font-lock sequence.")
 (defun org-get-level-face (n)
   "Get the right face for match N in font-lock matching of headlines."
   (setq org-l (- (match-end 2) (match-beginning 1) 1))
-  (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
+  (when org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
   (if org-cycle-level-faces
       (setq org-f (nth (% (1- org-l) org-n-level-faces) org-level-faces))
     (setq org-f (nth (1- (min org-l org-n-level-faces)) org-level-faces)))
   (cond
    ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
    ((eq n 2) org-f)
-   (t (if org-level-color-stars-only nil org-f))))
+   (t (unless org-level-color-stars-only org-f))))
 
+(defun org-face-from-face-or-color (context inherit face-or-color)
+  "Create a face list that inherits INHERIT, but sets the foreground color.
+When FACE-OR-COLOR is not a string, just return it."
+  (if (stringp face-or-color)
+      (list :inherit inherit
+           (cdr (assoc context org-faces-easy-properties))
+           face-or-color)
+    face-or-color))
 
 (defun org-get-todo-face (kwd)
   "Get the right face for a TODO keyword KWD.
 If KWD is a number, get the corresponding match group."
-  (if (numberp kwd) (setq kwd (match-string kwd)))
+  (when (numberp kwd) (setq kwd (match-string kwd)))
   (or (org-face-from-face-or-color
        'todo 'org-todo (cdr (assoc kwd org-todo-keyword-faces)))
       (and (member kwd org-done-keywords) 'org-done)
       'org-todo))
 
-(defun org-face-from-face-or-color (context inherit face-or-color)
-  "Create a face list that inherits INHERIT, but sets the foreground color.
-When FACE-OR-COLOR is not a string, just return it."
-  (if (stringp face-or-color)
-      (list :inherit inherit
-           (cdr (assoc context org-faces-easy-properties))
-           face-or-color)
-    face-or-color))
+(defun org-get-priority-face (priority)
+  "Get the right face for PRIORITY.
+PRIORITY is a character."
+  (or (org-face-from-face-or-color
+       'priority 'org-priority (cdr (assq priority org-priority-faces)))
+      'org-priority))
+
+(defun org-get-tag-face (tag)
+  "Get the right face for TAG.
+If TAG is a number, get the corresponding match group."
+  (let ((tag (if (wholenump tag) (match-string tag) tag)))
+    (or (org-face-from-face-or-color
+        'tag 'org-tag (cdr (assoc tag org-tag-faces)))
+       'org-tag)))
+
+(defun org-font-lock-add-priority-faces (limit)
+  "Add the special priority faces."
+  (while (re-search-forward "^\\*+ .*?\\(\\[#\\(.\\)\\]\\)" limit t)
+    (add-text-properties
+     (match-beginning 1) (match-end 1)
+     (list 'face (org-get-priority-face (string-to-char (match-string 2)))
+          'font-lock-fontified t))))
 
 (defun org-font-lock-add-tag-faces (limit)
   "Add the special tag faces."
@@ -6424,39 +6688,18 @@ When FACE-OR-COLOR is not a string, just return it."
                                 'font-lock-fontified t))
       (backward-char 1))))
 
-(defun org-font-lock-add-priority-faces (limit)
-  "Add the special priority faces."
-  (while (re-search-forward "\\[#\\([A-Z0-9]\\)\\]" limit t)
-    (when (save-match-data (org-at-heading-p))
-      (add-text-properties
-       (match-beginning 0) (match-end 0)
-       (list 'face (or (org-face-from-face-or-color
-                       'priority 'org-priority
-                       (cdr (assoc (char-after (match-beginning 1))
-                                   org-priority-faces)))
-                      'org-priority)
-            'font-lock-fontified t)))))
-
-(defun org-get-tag-face (kwd)
-  "Get the right face for a TODO keyword KWD.
-If KWD is a number, get the corresponding match group."
-  (if (numberp kwd) (setq kwd (match-string kwd)))
-  (or (org-face-from-face-or-color
-       'tag 'org-tag (cdr (assoc kwd org-tag-faces)))
-      'org-tag))
-
-(defun org-unfontify-region (beg end &optional maybe_loudly)
+(defun org-unfontify-region (beg end &optional _maybe_loudly)
   "Remove fontification and activation overlays from links."
   (font-lock-default-unfontify-region beg end)
   (let* ((buffer-undo-list t)
         (inhibit-read-only t) (inhibit-point-motion-hooks t)
         (inhibit-modification-hooks t)
         deactivate-mark buffer-file-name buffer-file-truename)
-    (org-decompose-region beg end)
+    (decompose-region beg end)
     (remove-text-properties beg end
                            '(mouse-face t keymap t org-linked-text t
                                         invisible t intangible t
-                                        org-no-flyspell t org-emphasis t))
+                                        org-emphasis t))
     (org-remove-font-lock-display-properties beg end)))
 
 (defconst org-script-display  '(((raise -0.3) (height 0.7))
@@ -6473,59 +6716,56 @@ and subscripts."
     (while (< beg end)
       (setq next (next-single-property-change beg 'display nil end)
            prop (get-text-property beg 'display))
-      (if (member prop org-script-display)
-         (put-text-property beg next 'display nil))
+      (when (member prop org-script-display)
+       (put-text-property beg next 'display nil))
       (setq beg next))))
 
 (defun org-raise-scripts (limit)
   "Add raise properties to sub/superscripts."
-  (when (and org-pretty-entities org-pretty-entities-include-sub-superscripts)
-    (if (re-search-forward
-        (if (eq org-use-sub-superscripts t)
-            org-match-substring-regexp
-          org-match-substring-with-braces-regexp)
-        limit t)
-       (let* ((pos (point)) table-p comment-p
-              (mpos (match-beginning 3))
-              (emph-p (get-text-property mpos 'org-emphasis))
-              (link-p (get-text-property mpos 'mouse-face))
-              (keyw-p (eq 'org-special-keyword (get-text-property mpos 
'face))))
-         (goto-char (point-at-bol))
-         (setq table-p (org-looking-at-p org-table-dataline-regexp)
-               comment-p (org-looking-at-p "^[ \t]*#[ +]"))
-         (goto-char pos)
-         ;; Handle a_b^c
-         (if (member (char-after) '(?_ ?^)) (goto-char (1- pos)))
-         (if (or comment-p emph-p link-p keyw-p)
-             t
-           (put-text-property (match-beginning 3) (match-end 0)
-                              'display
-                              (if (equal (char-after (match-beginning 2)) ?^)
-                                  (nth (if table-p 3 1) org-script-display)
-                                (nth (if table-p 2 0) org-script-display)))
-           (add-text-properties (match-beginning 2) (match-end 2)
-                                (list 'invisible t
-                                      'org-dwidth t 'org-dwidth-n 1))
-           (if (and (eq (char-after (match-beginning 3)) ?{)
-                    (eq (char-before (match-end 3)) ?}))
-               (progn
-                 (add-text-properties
-                  (match-beginning 3) (1+ (match-beginning 3))
-                  (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))
-                 (add-text-properties
-                  (1- (match-end 3)) (match-end 3)
-                  (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))))
-           t)))))
+  (when (and org-pretty-entities org-pretty-entities-include-sub-superscripts
+            (re-search-forward
+             (if (eq org-use-sub-superscripts t)
+                 org-match-substring-regexp
+               org-match-substring-with-braces-regexp)
+             limit t))
+    (let* ((pos (point)) table-p comment-p
+          (mpos (match-beginning 3))
+          (emph-p (get-text-property mpos 'org-emphasis))
+          (link-p (get-text-property mpos 'mouse-face))
+          (keyw-p (eq 'org-special-keyword (get-text-property mpos 'face))))
+      (goto-char (point-at-bol))
+      (setq table-p (looking-at-p org-table-dataline-regexp)
+           comment-p (looking-at-p "^[ \t]*#[ +]"))
+      (goto-char pos)
+      ;; Handle a_b^c
+      (when (member (char-after) '(?_ ?^)) (goto-char (1- pos)))
+      (unless (or comment-p emph-p link-p keyw-p)
+       (put-text-property (match-beginning 3) (match-end 0)
+                          'display
+                          (if (equal (char-after (match-beginning 2)) ?^)
+                              (nth (if table-p 3 1) org-script-display)
+                            (nth (if table-p 2 0) org-script-display)))
+       (add-text-properties (match-beginning 2) (match-end 2)
+                            (list 'invisible t
+                                  'org-dwidth t 'org-dwidth-n 1))
+       (if (and (eq (char-after (match-beginning 3)) ?{)
+                (eq (char-before (match-end 3)) ?}))
+           (progn
+             (add-text-properties
+              (match-beginning 3) (1+ (match-beginning 3))
+              (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))
+             (add-text-properties
+              (1- (match-end 3)) (match-end 3)
+              (list 'invisible t 'org-dwidth t 'org-dwidth-n 1)))))
+      t)))
 
 ;;;; Visibility cycling, including org-goto and indirect buffer
 
 ;;; Cycling
 
-(defvar org-cycle-global-status nil)
-(make-variable-buffer-local 'org-cycle-global-status)
+(defvar-local org-cycle-global-status nil)
 (put 'org-cycle-global-status 'org-state t)
-(defvar org-cycle-subtree-status nil)
-(make-variable-buffer-local 'org-cycle-subtree-status)
+(defvar-local org-cycle-subtree-status nil)
 (put 'org-cycle-subtree-status 'org-state t)
 
 (defvar org-inlinetask-min-level)
@@ -6537,52 +6777,58 @@ and subscripts."
 
 ;;;###autoload
 (defun org-cycle (&optional arg)
-  "TAB-action and visibility cycling for Org-mode.
+  "TAB-action and visibility cycling for Org mode.
 
-This is the command invoked in Org-mode by the TAB key.  Its main purpose
-is outline visibility cycling, but it also invokes other actions
+This is the command invoked in Org mode by the `TAB' key.  Its main
+purpose is outline visibility cycling, but it also invokes other actions
 in special contexts.
 
-- When this function is called with a prefix argument, rotate the entire
-  buffer through 3 states (global cycling)
+When this function is called with a `\\[universal-argument]' prefix, rotate \
+the entire
+buffer through 3 states (global cycling)
   1. OVERVIEW: Show only top-level headlines.
   2. CONTENTS: Show all headlines of all levels, but no body text.
   3. SHOW ALL: Show everything.
-  When called with two `C-u C-u' prefixes, switch to the startup visibility,
-  determined by the variable `org-startup-folded', and by any VISIBILITY
-  properties in the buffer.
-  When called with three `C-u C-u C-u' prefixed, show the entire buffer,
-  including any drawers.
 
-- When inside a table, re-align the table and move to the next field.
+With a `\\[universal-argument] \\[universal-argument]' prefix argument, \
+switch to the startup visibility,
+determined by the variable `org-startup-folded', and by any VISIBILITY
+properties in the buffer.
+
+With a `\\[universal-argument] \\[universal-argument] \
+\\[universal-argument]' prefix argument, show the entire buffer, including
+any drawers.
 
-- When point is at the beginning of a headline, rotate the subtree started
-  by this line through 3 different states (local cycling)
+When inside a table, re-align the table and move to the next field.
+
+When point is at the beginning of a headline, rotate the subtree started
+by this line through 3 different states (local cycling)
   1. FOLDED:   Only the main headline is shown.
   2. CHILDREN: The main headline and the direct children are shown.
                From this state, you can move to one of the children
                and zoom in further.
   3. SUBTREE:  Show the entire subtree, including body text.
-  If there is no subtree, switch directly from CHILDREN to FOLDED.
-
-- When point is at the beginning of an empty headline and the variable
-  `org-cycle-level-after-item/entry-creation' is set, cycle the level
-  of the headline by demoting and promoting it to likely levels.  This
-  speeds up creation document structure by pressing TAB once or several
-  times right after creating a new headline.
-
-- When there is a numeric prefix, go up to a heading with level ARG, do
-  a `show-subtree' and return to the previous cursor position.  If ARG
-  is negative, go up that many levels.
-
-- When point is not at the beginning of a headline, execute the global
-  binding for TAB, which is re-indenting the line.  See the option
-  `org-cycle-emulate-tab' for details.
-
-- Special case: if point is at the beginning of the buffer and there is
-  no headline in line 1, this function will act as if called with prefix arg
-  (C-u TAB, same as S-TAB) also when called without prefix arg.
-  But only if also the variable `org-cycle-global-at-bob' is t."
+If there is no subtree, switch directly from CHILDREN to FOLDED.
+
+When point is at the beginning of an empty headline and the variable
+`org-cycle-level-after-item/entry-creation' is set, cycle the level
+of the headline by demoting and promoting it to likely levels.  This
+speeds up creation document structure by pressing `TAB' once or several
+times right after creating a new headline.
+
+When there is a numeric prefix, go up to a heading with level ARG, do
+a `show-subtree' and return to the previous cursor position.  If ARG
+is negative, go up that many levels.
+
+When point is not at the beginning of a headline, execute the global
+binding for `TAB', which is re-indenting the line.  See the option
+`org-cycle-emulate-tab' for details.
+
+As a special case, if point is at the beginning of the buffer and there is
+no headline in line 1, this function will act as if called with prefix arg
+\(`\\[universal-argument] TAB', same as `S-TAB') also when called without \
+prefix arg, but only
+if the variable `org-cycle-global-at-bob' is t."
   (interactive "P")
   (org-load-modules-maybe)
   (unless (or (run-hook-with-args-until-success 'org-tab-first-hook)
@@ -6611,10 +6857,6 @@ in special contexts.
              org-cycle-hook))
           (pos (point)))
 
-      (if (or bob-special (equal arg '(4)))
-         ;; special case:  use global cycling
-         (setq arg t))
-
       (cond
 
        ((equal arg '(16))
@@ -6623,32 +6865,36 @@ in special contexts.
        (org-unlogged-message "Startup visibility, plus VISIBILITY properties"))
 
        ((equal arg '(64))
-       (show-all)
+       (outline-show-all)
        (org-unlogged-message "Entire buffer visible, including drawers"))
 
+       ((equal arg '(4)) (org-cycle-internal-global))
+
+       ;; Try hiding block at point.
+       ((org-hide-block-toggle-maybe))
+
        ;; Try cdlatex TAB completion
        ((org-try-cdlatex-tab))
 
        ;; Table: enter it or move to the next field.
        ((org-at-table-p 'any)
        (if (org-at-table.el-p)
-           (message "%s" "Use C-c ' to edit table.el tables")
+           (message "%s" (substitute-command-keys "\\<org-mode-map>\
+Use `\\[org-edit-special]' to edit table.el tables"))
          (if arg (org-table-edit-field t)
            (org-table-justify-field-maybe)
            (call-interactively 'org-table-next-field))))
 
-       ((run-hook-with-args-until-success
-        'org-tab-after-check-for-table-hook))
+       ((run-hook-with-args-until-success 'org-tab-after-check-for-table-hook))
 
        ;; Global cycling: delegate to `org-cycle-internal-global'.
-       ((eq arg t) (org-cycle-internal-global))
+       (bob-special (org-cycle-internal-global))
 
        ;; Drawers: delegate to `org-flag-drawer'.
-       ((and org-drawers org-drawer-regexp
-            (save-excursion
-              (beginning-of-line 1)
-              (looking-at org-drawer-regexp)))
-       (org-flag-drawer ; toggle block visibility
+       ((save-excursion
+         (beginning-of-line 1)
+         (looking-at org-drawer-regexp))
+       (org-flag-drawer                ; toggle block visibility
         (not (get-char-property (match-end 0) 'invisible))))
 
        ;; Show-subtree, ARG levels up from here.
@@ -6667,7 +6913,7 @@ in special contexts.
 
        ;; At an item/headline: delegate to `org-cycle-internal-local'.
        ((and (or (and org-cycle-include-plain-lists (org-at-item-p))
-                (save-excursion (beginning-of-line 1)
+                (save-excursion (move-beginning-of-line 1)
                                 (looking-at org-outline-regexp)))
             (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
        (org-cycle-internal-local))
@@ -6722,7 +6968,7 @@ in special contexts.
           (eq org-cycle-global-status 'contents))
       ;; We just showed the table of contents - now show everything
       (run-hook-with-args 'org-pre-cycle-hook 'all)
-      (show-all)
+      (outline-show-all)
       (unless ga (org-unlogged-message "SHOW ALL"))
       (setq org-cycle-global-status 'all)
       (run-hook-with-args 'org-cycle-hook 'all))
@@ -6738,6 +6984,11 @@ in special contexts.
 (defvar org-called-with-limited-levels nil
   "Non-nil when `org-with-limited-levels' is currently active.")
 
+(defun org-invisible-p (&optional pos)
+  "Non-nil if the character after POS is invisible.
+If POS is nil, use `point' instead."
+  (get-char-property (or pos (point)) 'invisible))
+
 (defun org-cycle-internal-local ()
   "Do the local cycling action."
   (let ((goal-column 0) eoh eol eos has-children children-skipped struct)
@@ -6765,15 +7016,10 @@ in special contexts.
                    (org-list-search-forward (org-item-beginning-re) eos t)))))
       ;; Determine end invisible part of buffer (EOL)
       (beginning-of-line 2)
-      ;; XEmacs doesn't have `next-single-char-property-change'
-      (if (featurep 'xemacs)
-         (while (and (not (eobp)) ;; this is like `next-line'
-                     (get-char-property (1- (point)) 'invisible))
-           (beginning-of-line 2))
-       (while (and (not (eobp)) ;; this is like `next-line'
-                   (get-char-property (1- (point)) 'invisible))
-         (goto-char (next-single-char-property-change (point) 'invisible))
-         (and (eolp) (beginning-of-line 2))))
+      (while (and (not (eobp)) ;This is like `next-line'.
+                 (get-char-property (1- (point)) 'invisible))
+       (goto-char (next-single-char-property-change (point) 'invisible))
+       (and (eolp) (beginning-of-line 2)))
       (setq eol (point)))
     ;; Find out what to do next and set `this-command'
     (cond
@@ -6786,7 +7032,7 @@ in special contexts.
       (save-excursion
        (goto-char eos)
        (outline-next-heading)
-       (if (outline-invisible-p) (org-flag-heading nil))))
+       (when (org-invisible-p) (org-flag-heading nil))))
      ((and (or (>= eol eos)
               (not (string-match "\\S-" (buffer-substring eol eos))))
           (or has-children
@@ -6798,7 +7044,7 @@ in special contexts.
       (if (org-at-item-p)
          (org-list-set-item-visibility (point-at-bol) struct 'children)
        (org-show-entry)
-       (org-with-limited-levels (show-children))
+       (org-with-limited-levels (org-show-children))
        ;; FIXME: This slows down the func way too much.
        ;; How keep drawers hidden in subtree anyway?
        ;; (when (memq 'org-cycle-hide-drawers org-cycle-hook)
@@ -6813,14 +7059,14 @@ in special contexts.
              (let* ((struct (org-list-struct))
                     (prevs (org-list-prevs-alist struct))
                     (end (org-list-get-bottom-point struct)))
-               (mapc (lambda (e) (org-list-set-item-visibility e struct 
'folded))
-                     (org-list-get-all-items (point) struct prevs))
+               (dolist (e (org-list-get-all-items (point) struct prevs))
+                 (org-list-set-item-visibility e struct 'folded))
                (goto-char (if (< end eos) end eos)))))))
       (org-unlogged-message "CHILDREN")
       (save-excursion
        (goto-char eos)
        (outline-next-heading)
-       (if (outline-invisible-p) (org-flag-heading nil)))
+       (when (org-invisible-p) (org-flag-heading nil)))
       (setq org-cycle-subtree-status 'children)
       (unless (org-before-first-heading-p)
        (run-hook-with-args 'org-cycle-hook 'children)))
@@ -6849,15 +7095,15 @@ in special contexts.
 ;;;###autoload
 (defun org-global-cycle (&optional arg)
   "Cycle the global visibility.  For details see `org-cycle'.
-With \\[universal-argument] prefix arg, switch to startup visibility.
+With `\\[universal-argument]' prefix ARG, switch to startup visibility.
 With a numeric prefix, show all headlines up to that level."
   (interactive "P")
   (let ((org-cycle-include-plain-lists
         (if (derived-mode-p 'org-mode) org-cycle-include-plain-lists nil)))
     (cond
      ((integerp arg)
-      (show-all)
-      (hide-sublevels arg)
+      (outline-show-all)
+      (outline-hide-sublevels arg)
       (setq org-cycle-global-status 'contents))
      ((equal arg '(4))
       (org-set-startup-visibility)
@@ -6874,9 +7120,9 @@ With a numeric prefix, show all headlines up to that 
level."
     (org-content))
    ((or (eq org-startup-folded 'showeverything)
        (eq org-startup-folded nil))
-    (show-all)))
+    (outline-show-all)))
   (unless (eq org-startup-folded 'showeverything)
-    (if org-hide-block-startup (org-hide-block-all))
+    (when org-hide-block-startup (org-hide-block-all))
     (org-set-visibility-according-to-property 'no-cleanup)
     (org-cycle-hide-archived-subtrees 'all)
     (org-cycle-hide-drawers 'all)
@@ -6885,34 +7131,32 @@ With a numeric prefix, show all headlines up to that 
level."
 (defun org-set-visibility-according-to-property (&optional no-cleanup)
   "Switch subtree visibilities according to :VISIBILITY: property."
   (interactive)
-  (let (org-show-entry-below state)
-    (save-excursion
-      (goto-char (point-min))
-      (while (re-search-forward
-             "^[ \t]*:VISIBILITY:[ \t]+\\([a-z]+\\)"
-             nil t)
-       (setq state (match-string 1))
-       (save-excursion
-         (org-back-to-heading t)
-         (hide-subtree)
-         (org-reveal)
-         (cond
-          ((equal state '("fold" "folded"))
-           (hide-subtree))
-          ((equal state "children")
-           (org-show-hidden-entry)
-           (show-children))
-          ((equal state "content")
-           (save-excursion
-             (save-restriction
-               (org-narrow-to-subtree)
-               (org-content))))
-          ((member state '("all" "showall"))
-           (show-subtree)))))
-      (unless no-cleanup
-       (org-cycle-hide-archived-subtrees 'all)
-       (org-cycle-hide-drawers 'all)
-       (org-cycle-show-empty-lines 'all)))))
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (while (re-search-forward "^[ \t]*:VISIBILITY:" nil t)
+     (if (not (org-at-property-p)) (outline-next-heading)
+       (let ((state (match-string 3)))
+        (save-excursion
+          (org-back-to-heading t)
+          (outline-hide-subtree)
+          (org-reveal)
+          (cond
+           ((equal state "folded")
+            (outline-hide-subtree))
+           ((equal state "children")
+            (org-show-hidden-entry)
+            (org-show-children))
+           ((equal state "content")
+            (save-excursion
+              (save-restriction
+                (org-narrow-to-subtree)
+                (org-content))))
+           ((member state '("all" "showall"))
+            (outline-show-subtree)))))))
+   (unless no-cleanup
+     (org-cycle-hide-archived-subtrees 'all)
+     (org-cycle-hide-drawers 'all)
+     (org-cycle-show-empty-lines 'all))))
 
 ;; This function uses outline-regexp instead of the more fundamental
 ;; org-outline-regexp so that org-cycle-global works outside of Org
@@ -6928,11 +7172,10 @@ results."
     (let ((level
           (save-excursion
             (goto-char (point-min))
-            (if (re-search-forward (concat "^" outline-regexp) nil t)
-                (progn
-                  (goto-char (match-beginning 0))
-                  (funcall outline-level))))))
-      (and level (hide-sublevels level)))))
+            (when (re-search-forward (concat "^" outline-regexp) nil t)
+              (goto-char (match-beginning 0))
+              (funcall outline-level)))))
+      (and level (outline-hide-sublevels level)))))
 
 (defun org-content (&optional arg)
   "Show all headlines in the buffer, like a table of contents.
@@ -6950,9 +7193,9 @@ With numerical argument N, show content up to level N."
                         t)
                  (looking-at org-outline-regexp))
        (if (integerp arg)
-           (show-children (1- arg))
-         (show-branches))
-       (if (bobp) (throw 'exit nil))))))
+           (org-show-children (1- arg))
+         (outline-show-branches))
+       (when (bobp) (throw 'exit nil))))))
 
 (defun org-optimize-window-after-visibility-change (state)
   "Adjust the window after a change in outline visibility.
@@ -6967,13 +7210,11 @@ This function is the default value of the hook 
`org-cycle-hook'."
 
 (defun org-remove-empty-overlays-at (pos)
   "Remove outline overlays that do not contain non-white stuff."
-  (mapc
-   (lambda (o)
-     (and (eq 'outline (overlay-get o 'invisible))
-         (not (string-match "\\S-" (buffer-substring (overlay-start o)
-                                                     (overlay-end o))))
-         (delete-overlay o)))
-   (overlays-at pos)))
+  (dolist (o (overlays-at pos))
+    (and (eq 'outline (overlay-get o 'invisible))
+        (not (string-match "\\S-" (buffer-substring (overlay-start o)
+                                                    (overlay-end o))))
+        (delete-overlay o))))
 
 (defun org-clean-visibility-after-subtree-move ()
   "Fix visibility issues after moving a subtree."
@@ -6991,7 +7232,7 @@ This function is the default value of the hook 
`org-cycle-hook'."
                    (point-at-eol)
                  (point))))
         (level (looking-at "\\*+"))
-        (re (if level (concat "^" (regexp-quote (match-string 0)) " "))))
+        (re (when level (concat "^" (regexp-quote (match-string 0)) " "))))
     (save-excursion
       (save-restriction
        (narrow-to-region beg end)
@@ -6999,10 +7240,10 @@ This function is the default value of the hook 
`org-cycle-hook'."
          ;; Properly fold already folded siblings
          (goto-char (point-min))
          (while (re-search-forward re nil t)
-           (if (and (not (outline-invisible-p))
-                    (save-excursion
-                      (goto-char (point-at-eol)) (outline-invisible-p)))
-               (hide-entry))))
+           (when (and (not (org-invisible-p))
+                      (save-excursion
+                        (goto-char (point-at-eol)) (org-invisible-p)))
+             (outline-hide-entry))))
        (org-cycle-show-empty-lines 'overview)
        (org-cycle-hide-drawers 'overview)))))
 
@@ -7012,7 +7253,7 @@ The region to be covered depends on STATE when called 
through
 `org-cycle-hook'.  Lisp program can use t for STATE to get the
 entire buffer covered.  Note that an empty line is only shown if there
 are at least `org-cycle-separator-lines' empty lines before the headline."
-  (when (not (= org-cycle-separator-lines 0))
+  (when (/= org-cycle-separator-lines 0)
     (save-excursion
       (let* ((n (abs org-cycle-separator-lines))
             (re (cond
@@ -7021,38 +7262,34 @@ are at least `org-cycle-separator-lines' empty lines 
before the headline."
                  (t (let ((ns (number-to-string (- n 2))))
                       (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}"
                               "[ \t]*\\(\n[ \t]*\n\\*+\\) ")))))
-            beg end b e)
+            beg end)
        (cond
         ((memq state '(overview contents t))
          (setq beg (point-min) end (point-max)))
         ((memq state '(children folded))
-         (setq beg (point) end (progn (org-end-of-subtree t t)
-                                      (beginning-of-line 2)
-                                      (point)))))
+         (setq beg (point)
+               end (progn (org-end-of-subtree t t)
+                          (line-beginning-position 2)))))
        (when beg
          (goto-char beg)
          (while (re-search-forward re end t)
            (unless (get-char-property (match-end 1) 'invisible)
-             (setq e (match-end 1))
-             (if (< org-cycle-separator-lines 0)
-                 (setq b (save-excursion
-                           (goto-char (match-beginning 0))
-                           (org-back-over-empty-lines)
-                           (if (save-excursion
-                                 (goto-char (max (point-min) (1- (point))))
-                                 (org-at-heading-p))
-                               (1- (point))
-                             (point))))
-               (setq b (match-beginning 1)))
-             (outline-flag-region b e nil)))))))
+             (let ((e (match-end 1))
+                   (b (if (>= org-cycle-separator-lines 0)
+                          (match-beginning 1)
+                        (save-excursion
+                          (goto-char (match-beginning 0))
+                          (skip-chars-backward " \t\n")
+                          (line-end-position)))))
+               (outline-flag-region b e nil))))))))
   ;; Never hide empty lines at the end of the file.
   (save-excursion
     (goto-char (point-max))
     (outline-previous-heading)
     (outline-end-of-heading)
-    (if (and (looking-at "[ \t\n]+")
-            (= (match-end 0) (point-max)))
-       (outline-flag-region (point) (match-end 0) nil))))
+    (when (and (looking-at "[ \t\n]+")
+              (= (match-end 0) (point-max)))
+      (outline-flag-region (point) (match-end 0) nil))))
 
 (defun org-show-empty-lines-in-parent ()
   "Move to the parent and re-show empty lines before visible headlines."
@@ -7061,28 +7298,28 @@ are at least `org-cycle-separator-lines' empty lines 
before the headline."
       (org-cycle-show-empty-lines context))))
 
 (defun org-files-list ()
-  "Return `org-agenda-files' list, plus all open org-mode files.
+  "Return `org-agenda-files' list, plus all open Org files.
 This is useful for operations that need to scan all of a user's
 open and agenda-wise Org files."
   (let ((files (mapcar 'expand-file-name (org-agenda-files))))
     (dolist (buf (buffer-list))
       (with-current-buffer buf
-       (if (and (derived-mode-p 'org-mode) (buffer-file-name))
-           (let ((file (expand-file-name (buffer-file-name))))
-             (unless (member file files)
-               (push file files))))))
+       (when (and (derived-mode-p 'org-mode) (buffer-file-name))
+         (cl-pushnew (expand-file-name (buffer-file-name)) files))))
     files))
 
 (defsubst org-entry-beginning-position ()
   "Return the beginning position of the current entry."
-  (save-excursion (outline-back-to-heading t) (point)))
+  (save-excursion (org-back-to-heading t) (point)))
 
 (defsubst org-entry-end-position ()
   "Return the end position of the current entry."
   (save-excursion (outline-next-heading) (point)))
 
-(defun org-cycle-hide-drawers (state)
-  "Re-hide all drawers after a visibility state change."
+(defun org-cycle-hide-drawers (state &optional exceptions)
+  "Re-hide all drawers after a visibility state change.
+When non-nil, optional argument EXCEPTIONS is a list of strings
+specifying which drawers should not be hidden."
   (when (and (derived-mode-p 'org-mode)
             (not (memq state '(overview folded contents))))
     (save-excursion
@@ -7093,36 +7330,39 @@ open and agenda-wise Org files."
                        (save-excursion (outline-next-heading) (point))
                      (org-end-of-subtree t)))))
        (goto-char beg)
-       (while (re-search-forward org-drawer-regexp end t)
-         (org-flag-drawer t))))))
-
-(defun org-cycle-hide-inline-tasks (state)
-  "Re-hide inline tasks when switching to `contents' or `children'
-visibility state."
-  (case state
-    (contents
-     (when (org-bound-and-true-p org-inlinetask-min-level)
-       (hide-sublevels (1- org-inlinetask-min-level))))
-    (children
-     (when (featurep 'org-inlinetask)
-       (save-excursion
-        (while (and (outline-next-heading)
-                    (org-inlinetask-at-task-p))
-          (org-inlinetask-toggle-visibility)
-          (org-inlinetask-goto-end)))))))
-
-(defun org-flag-drawer (flag)
-  "When FLAG is non-nil, hide the drawer we are within.
-Otherwise make it visible."
-  (save-excursion
-    (beginning-of-line 1)
-    (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:")
-      (let ((b (match-end 0)))
-       (if (re-search-forward
-            "^[ \t]*:END:"
-            (save-excursion (outline-next-heading) (point)) t)
-           (outline-flag-region b (point-at-eol) flag)
-         (user-error ":END: line missing at position %s" b))))))
+       (while (re-search-forward org-drawer-regexp (max end (point)) t)
+         (unless (member-ignore-case (match-string 1) exceptions)
+           (let ((drawer (org-element-at-point)))
+             (when (memq (org-element-type drawer) '(drawer property-drawer))
+               (org-flag-drawer t drawer)
+               ;; Make sure to skip drawer entirely or we might flag
+               ;; it another time when matching its ending line with
+               ;; `org-drawer-regexp'.
+               (goto-char (org-element-property :end drawer))))))))))
+
+(defun org-flag-drawer (flag &optional element)
+  "When FLAG is non-nil, hide the drawer we are at.
+Otherwise make it visible.  When optional argument ELEMENT is
+a parsed drawer, as returned by `org-element-at-point', hide or
+show that drawer instead."
+  (let ((drawer (or element
+                   (and (save-excursion
+                          (beginning-of-line)
+                          (looking-at-p org-drawer-regexp))
+                        (org-element-at-point)))))
+    (when (memq (org-element-type drawer) '(drawer property-drawer))
+      (let ((post (org-element-property :post-affiliated drawer)))
+       (save-excursion
+         (outline-flag-region
+          (progn (goto-char post) (line-end-position))
+          (progn (goto-char (org-element-property :end drawer))
+                 (skip-chars-backward " \r\t\n")
+                 (line-end-position))
+          flag))
+       ;; When the drawer is hidden away, make sure point lies in
+       ;; a visible part of the buffer.
+       (when (and flag (> (line-beginning-position) post))
+         (goto-char post))))))
 
 (defun org-subtree-end-visible-p ()
   "Is the end of the current subtree visible?"
@@ -7131,9 +7371,11 @@ Otherwise make it visible."
 
 (defun org-first-headline-recenter ()
   "Move cursor to the first headline and recenter the headline."
-  (goto-char (point-min))
-  (when (re-search-forward (concat "^\\(" org-outline-regexp "\\)") nil t)
-    (set-window-start (selected-window) (point-at-bol))))
+  (let ((window (get-buffer-window)))
+    (when window
+      (goto-char (point-min))
+      (when (re-search-forward (concat "^\\(" org-outline-regexp "\\)") nil t)
+       (set-window-start window (line-beginning-position))))))
 
 ;;; Saving and restoring visibility
 
@@ -7144,38 +7386,30 @@ The return value is a list of cons cells, with start 
and stop
 positions for each overlay.
 If USE-MARKERS is set, return the positions as markers."
   (let (beg end)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (delq nil
-             (mapcar (lambda (o)
-                       (when (eq (overlay-get o 'invisible) 'outline)
-                         (setq beg (overlay-start o)
-                               end (overlay-end o))
-                         (and beg end (> end beg)
-                              (if use-markers
-                                  (cons (move-marker (make-marker) beg)
-                                        (move-marker (make-marker) end))
-                                (cons beg end)))))
-                     (overlays-in (point-min) (point-max))))))))
+    (org-with-wide-buffer
+     (delq nil
+          (mapcar (lambda (o)
+                    (when (eq (overlay-get o 'invisible) 'outline)
+                      (setq beg (overlay-start o)
+                            end (overlay-end o))
+                      (and beg end (> end beg)
+                           (if use-markers
+                               (cons (copy-marker beg)
+                                     (copy-marker end t))
+                             (cons beg end)))))
+                  (overlays-in (point-min) (point-max)))))))
 
 (defun org-set-outline-overlay-data (data)
   "Create visibility overlays for all positions in DATA.
 DATA should have been made by `org-outline-overlay-data'."
-  (let (o)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (show-all)
-       (mapc (lambda (c)
-               (outline-flag-region (car c) (cdr c) t))
-             data)))))
+  (org-with-wide-buffer
+   (outline-show-all)
+   (dolist (c data) (outline-flag-region (car c) (cdr c) t))))
 
 ;;; Folding of blocks
 
-(defvar org-hide-block-overlays nil
+(defvar-local org-hide-block-overlays nil
   "Overlays hiding blocks.")
-(make-variable-buffer-local 'org-hide-block-overlays)
 
 (defun org-block-map (function &optional start end)
   "Call FUNCTION at the head of all source blocks in the current buffer.
@@ -7192,74 +7426,85 @@ Optional arguments START and END can be used to limit 
the range."
 
 (defun org-hide-block-toggle-all ()
   "Toggle the visibility of all blocks in the current buffer."
-  (org-block-map #'org-hide-block-toggle))
+  (org-block-map 'org-hide-block-toggle))
 
 (defun org-hide-block-all ()
   "Fold all blocks in the current buffer."
   (interactive)
   (org-show-block-all)
-  (org-block-map #'org-hide-block-toggle-maybe))
+  (org-block-map 'org-hide-block-toggle-maybe))
 
 (defun org-show-block-all ()
   "Unfold all blocks in the current buffer."
   (interactive)
-  (mapc 'delete-overlay org-hide-block-overlays)
+  (mapc #'delete-overlay org-hide-block-overlays)
   (setq org-hide-block-overlays nil))
 
 (defun org-hide-block-toggle-maybe ()
-  "Toggle visibility of block at point."
+  "Toggle visibility of block at point.
+Unlike to `org-hide-block-toggle', this function does not throw
+an error.  Return a non-nil value when toggling is successful."
   (interactive)
-  (let ((case-fold-search t))
-    (if (save-excursion
-          (beginning-of-line 1)
-          (looking-at org-block-regexp))
-        (progn (org-hide-block-toggle)
-               t) ;; to signal that we took action
-      nil))) ;; to signal that we did not
+  (ignore-errors (org-hide-block-toggle)))
 
 (defun org-hide-block-toggle (&optional force)
-  "Toggle the visibility of the current block."
+  "Toggle the visibility of the current block.
+When optional argument FORCE is `off', make block visible.  If it
+is non-nil, hide it unconditionally.  Throw an error when not at
+a block.  Return a non-nil value when toggling is successful."
   (interactive)
-  (save-excursion
-    (beginning-of-line)
-    (if (re-search-forward org-block-regexp nil t)
-        (let ((start (- (match-beginning 4) 1)) ;; beginning of body
-              (end (match-end 0)) ;; end of entire body
-              ov)
-          (if (memq t (mapcar (lambda (overlay)
-                                (eq (overlay-get overlay 'invisible)
-                                   'org-hide-block))
-                              (overlays-at start)))
-              (if (or (not force) (eq force 'off))
-                  (mapc (lambda (ov)
-                          (when (member ov org-hide-block-overlays)
-                            (setq org-hide-block-overlays
-                                  (delq ov org-hide-block-overlays)))
-                          (when (eq (overlay-get ov 'invisible)
-                                    'org-hide-block)
-                            (delete-overlay ov)))
-                        (overlays-at start)))
-            (setq ov (make-overlay start end))
-            (overlay-put ov 'invisible 'org-hide-block)
-            ;; make the block accessible to isearch
-            (overlay-put
-             ov 'isearch-open-invisible
-             (lambda (ov)
-               (when (member ov org-hide-block-overlays)
-                 (setq org-hide-block-overlays
-                       (delq ov org-hide-block-overlays)))
-               (when (eq (overlay-get ov 'invisible)
-                         'org-hide-block)
-                 (delete-overlay ov))))
-            (push ov org-hide-block-overlays)))
-      (user-error "Not looking at a source block"))))
-
-;; org-tab-after-check-for-cycling-hook
-(add-hook 'org-tab-first-hook 'org-hide-block-toggle-maybe)
+  (let ((element (org-element-at-point)))
+    (unless (memq (org-element-type element)
+                 '(center-block comment-block dynamic-block example-block
+                                export-block quote-block special-block
+                                src-block verse-block))
+      (user-error "Not at a block"))
+    (let* ((start (save-excursion
+                   (goto-char (org-element-property :post-affiliated element))
+                   (line-end-position)))
+          (end (save-excursion
+                 (goto-char (org-element-property :end element))
+                 (skip-chars-backward " \r\t\n")
+                 (line-end-position)))
+          (overlays (overlays-at start)))
+      (cond
+       ;; Do nothing when not before or at the block opening line or
+       ;; at the block closing line.
+       ((let ((eol (line-end-position))) (and (> eol start) (/= eol end))) nil)
+       ((and (not (eq force 'off))
+            (not (memq t (mapcar
+                          (lambda (o)
+                            (eq (overlay-get o 'invisible) 'org-hide-block))
+                          overlays))))
+       (let ((ov (make-overlay start end)))
+         (overlay-put ov 'invisible 'org-hide-block)
+         ;; Make the block accessible to `isearch'.
+         (overlay-put
+          ov 'isearch-open-invisible
+          (lambda (ov)
+            (when (memq ov org-hide-block-overlays)
+              (setq org-hide-block-overlays (delq ov org-hide-block-overlays)))
+            (when (eq (overlay-get ov 'invisible) 'org-hide-block)
+              (delete-overlay ov))))
+         (push ov org-hide-block-overlays)
+         ;; When the block is hidden away, make sure point is left in
+         ;; a visible part of the buffer.
+         (when (> (line-beginning-position) start)
+           (goto-char start)
+           (beginning-of-line))
+         ;; Signal successful toggling.
+         t))
+       ((or (not force) (eq force 'off))
+       (dolist (ov overlays t)
+         (when (memq ov org-hide-block-overlays)
+           (setq org-hide-block-overlays (delq ov org-hide-block-overlays)))
+         (when (eq (overlay-get ov 'invisible) 'org-hide-block)
+           (delete-overlay ov))))))))
+
 ;; Remove overlays when changing major mode
 (add-hook 'org-mode-hook
-         (lambda () (org-add-hook 'change-major-mode-hook
-                                  'org-show-block-all 'append 'local)))
+         (lambda () (add-hook 'change-major-mode-hook
+                              'org-show-block-all 'append 'local)))
 
 ;;; Org-goto
 
@@ -7305,7 +7550,7 @@ Optional arguments START and END can be used to limit the 
range."
 (defconst org-goto-help
   "Browse buffer copy, to find location or copy text.%s
 RET=jump to location             C-g=quit and return to previous location
-[Up]/[Down]=next/prev headline   TAB=cycle visibility   [/] org-occur")
+\[Up]/[Down]=next/prev headline   TAB=cycle visibility   [/] org-occur")
 
 (defvar org-goto-start-pos) ; dynamically scoped parameter
 
@@ -7343,23 +7588,23 @@ With a prefix argument, use the alternative interface: 
e.g., if
         (selected-point
          (if (eq interface 'outline)
              (car (org-get-location (current-buffer) org-goto-help))
-           (let ((pa (org-refile-get-location "Goto" nil nil t)))
+           (let ((pa (org-refile-get-location "Goto")))
              (org-refile-check-position pa)
              (nth 3 pa)))))
     (if selected-point
        (progn
          (org-mark-ring-push org-goto-start-pos)
          (goto-char selected-point)
-         (if (or (outline-invisible-p) (org-invisible-p2))
-             (org-show-context 'org-goto)))
+         (when (or (org-invisible-p) (org-invisible-p2))
+           (org-show-context 'org-goto)))
       (message "Quit"))))
 
 (defvar org-goto-selected-point nil) ; dynamically scoped parameter
 (defvar org-goto-exit-command nil) ; dynamically scoped parameter
 (defvar org-goto-local-auto-isearch-map) ; defined below
 
-(defun org-get-location (buf help)
-  "Let the user select a location in the Org-mode buffer BUF.
+(defun org-get-location (_buf help)
+  "Let the user select a location in current buffer.
 This function uses a recursive edit.  It returns the selected position
 or nil."
   (org-no-popups
@@ -7372,7 +7617,7 @@ or nil."
        (save-window-excursion
         (delete-other-windows)
         (and (get-buffer "*org-goto*") (kill-buffer "*org-goto*"))
-        (org-pop-to-buffer-same-window
+        (pop-to-buffer-same-window
          (condition-case nil
              (make-indirect-buffer (current-buffer) "*org-goto*")
            (error (make-indirect-buffer (current-buffer) "*org-goto*"))))
@@ -7390,11 +7635,9 @@ or nil."
         (setq buffer-read-only t)
         (if (and (boundp 'org-goto-start-pos)
                  (integer-or-marker-p org-goto-start-pos))
-            (let ((org-show-hierarchy-above t)
-                  (org-show-siblings t)
-                  (org-show-following-heading t))
-              (goto-char org-goto-start-pos)
-              (and (outline-invisible-p) (org-show-context)))
+            (progn (goto-char org-goto-start-pos)
+                   (when (org-invisible-p)
+                     (org-show-set-visibility 'lineage)))
           (goto-char (point-min)))
         (let (org-special-ctrl-a/e) (org-beginning-of-line))
         (message "Select location and press RET")
@@ -7405,8 +7648,14 @@ or nil."
 
 (defvar org-goto-local-auto-isearch-map (make-sparse-keymap))
 (set-keymap-parent org-goto-local-auto-isearch-map isearch-mode-map)
-(define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char)
-(define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char)
+;; `isearch-other-control-char' was removed in Emacs 24.4.
+(if (fboundp 'isearch-other-control-char)
+    (progn
+      (define-key org-goto-local-auto-isearch-map "\C-i" 
'isearch-other-control-char)
+      (define-key org-goto-local-auto-isearch-map "\C-m" 
'isearch-other-control-char))
+  (define-key org-goto-local-auto-isearch-map "\C-i" nil)
+  (define-key org-goto-local-auto-isearch-map "\C-m" nil)
+  (define-key org-goto-local-auto-isearch-map [return] nil))
 
 (defun org-goto-local-search-headings (string bound noerror)
   "Search and make sure that any matches are in headlines."
@@ -7414,9 +7663,12 @@ or nil."
     (while (if isearch-forward
                (search-forward string bound noerror)
              (search-backward string bound noerror))
-      (when (let ((context (mapcar 'car (save-match-data (org-context)))))
-             (and (member :headline context)
-                  (not (member :tags context))))
+      (when (save-match-data
+             (and (save-excursion
+                    (beginning-of-line)
+                    (looking-at org-complex-heading-regexp))
+                  (or (not (match-beginning 5))
+                      (< (point) (match-beginning 5)))))
        (throw 'return (point))))))
 
 (defun org-goto-local-auto-isearch ()
@@ -7428,11 +7680,11 @@ or nil."
       (isearch-mode t)
       (isearch-process-search-char (string-to-char keys)))))
 
-(defun org-goto-ret (&optional arg)
+(defun org-goto-ret (&optional _arg)
   "Finish `org-goto' by going to the new location."
   (interactive "P")
-  (setq org-goto-selected-point (point)
-       org-goto-exit-command 'return)
+  (setq org-goto-selected-point (point))
+  (setq org-goto-exit-command 'return)
   (throw 'exit nil))
 
 (defun org-goto-left ()
@@ -7471,17 +7723,18 @@ or nil."
 
 (defun org-tree-to-indirect-buffer (&optional arg)
   "Create indirect buffer and narrow it to current subtree.
+
 With a numerical prefix ARG, go up to this level and then take that tree.
 If ARG is negative, go up that many levels.
 
 If `org-indirect-buffer-display' is not `new-frame', the command removes the
 indirect buffer previously made with this command, to avoid proliferation of
 indirect buffers.  However, when you call the command with a \
-\\[universal-argument] prefix, or
-when `org-indirect-buffer-display' is `new-frame', the last buffer
-is kept so that you can work with several indirect buffers at the same time.
-If `org-indirect-buffer-display' is `dedicated-frame', the \
-\\[universal-argument] prefix also
+`\\[universal-argument]' prefix, or
+when `org-indirect-buffer-display' is `new-frame', the last buffer is kept
+so that you can work with several indirect buffers at the same time.  If
+`org-indirect-buffer-display' is `dedicated-frame', the \
+`\\[universal-argument]' prefix also
 requests that a new frame be made for the new buffer, so that the dedicated
 frame is not changed."
   (interactive "P")
@@ -7493,26 +7746,26 @@ frame is not changed."
       (org-back-to-heading t)
       (when (numberp arg)
        (setq level (org-outline-level))
-       (if (< arg 0) (setq arg (+ level arg)))
+       (when (< arg 0) (setq arg (+ level arg)))
        (while (> (setq level (org-outline-level)) arg)
          (org-up-heading-safe)))
       (setq beg (point)
-           heading (org-get-heading))
+           heading (org-get-heading 'no-tags))
       (org-end-of-subtree t t)
-      (if (org-at-heading-p) (backward-char 1))
+      (when (org-at-heading-p) (backward-char 1))
       (setq end (point)))
-    (if (and (buffer-live-p org-last-indirect-buffer)
-            (not (eq org-indirect-buffer-display 'new-frame))
-            (not arg))
-       (kill-buffer org-last-indirect-buffer))
-    (setq ibuf (org-get-indirect-buffer cbuf)
+    (when (and (buffer-live-p org-last-indirect-buffer)
+              (not (eq org-indirect-buffer-display 'new-frame))
+              (not arg))
+      (kill-buffer org-last-indirect-buffer))
+    (setq ibuf (org-get-indirect-buffer cbuf heading)
          org-last-indirect-buffer ibuf)
     (cond
      ((or (eq org-indirect-buffer-display 'new-frame)
          (and arg (eq org-indirect-buffer-display 'dedicated-frame)))
       (select-frame (make-frame))
       (delete-other-windows)
-      (org-pop-to-buffer-same-window ibuf)
+      (pop-to-buffer-same-window ibuf)
       (org-set-frame-title heading))
      ((eq org-indirect-buffer-display 'dedicated-frame)
       (raise-frame
@@ -7521,26 +7774,28 @@ frame is not changed."
                              org-indirect-dedicated-frame)
                         (setq org-indirect-dedicated-frame (make-frame)))))
       (delete-other-windows)
-      (org-pop-to-buffer-same-window ibuf)
+      (pop-to-buffer-same-window ibuf)
       (org-set-frame-title (concat "Indirect: " heading)))
      ((eq org-indirect-buffer-display 'current-window)
-      (org-pop-to-buffer-same-window ibuf))
+      (pop-to-buffer-same-window ibuf))
      ((eq org-indirect-buffer-display 'other-window)
       (pop-to-buffer ibuf))
      (t (error "Invalid value")))
-    (if (featurep 'xemacs)
-        (save-excursion (org-mode) (turn-on-font-lock)))
     (narrow-to-region beg end)
-    (show-all)
+    (outline-show-all)
     (goto-char pos)
     (run-hook-with-args 'org-cycle-hook 'all)
     (and (window-live-p cwin) (select-window cwin))))
 
-(defun org-get-indirect-buffer (&optional buffer)
+(defun org-get-indirect-buffer (&optional buffer heading)
   (setq buffer (or buffer (current-buffer)))
   (let ((n 1) (base (buffer-name buffer)) bname)
     (while (buffer-live-p
-           (get-buffer (setq bname (concat base "-" (number-to-string n)))))
+           (get-buffer
+            (setq bname
+                  (concat base "-"
+                          (if heading (concat heading "-" (number-to-string n))
+                            (number-to-string n))))))
       (setq n (1+ n)))
     (condition-case nil
         (make-indirect-buffer buffer bname 'clone)
@@ -7548,57 +7803,70 @@ frame is not changed."
 
 (defun org-set-frame-title (title)
   "Set the title of the current frame to the string TITLE."
-  ;; FIXME: how to name a single frame in XEmacs???
-  (unless (featurep 'xemacs)
-    (modify-frame-parameters (selected-frame) (list (cons 'name title)))))
+  (modify-frame-parameters (selected-frame) (list (cons 'name title))))
 
 ;;;; Structure editing
 
 ;;; Inserting headlines
 
-(defun org-previous-line-empty-p (&optional next)
-  "Is the previous line a blank line?
-When NEXT is non-nil, check the next line instead."
+(defun org--line-empty-p (n)
+  "Is the Nth next line empty?
+
+Counts the current line as N = 1 and the previous line as N = 0;
+see `beginning-of-line'."
   (save-excursion
     (and (not (bobp))
-        (or (beginning-of-line (if next 2 0)) t)
+        (or (beginning-of-line n) t)
         (save-match-data
           (looking-at "[ \t]*$")))))
 
-(defun org-insert-heading (&optional arg invisible-ok)
-  "Insert a new heading or an item with the same depth at point.
-
-If point is at the beginning of a heading or a list item, insert
-a new heading or a new item above the current one.  If point is
-at the beginning of a normal line, turn the line into a heading.
+(defun org-previous-line-empty-p ()
+  "Is the previous line a blank line?
+When NEXT is non-nil, check the next line instead."
+  (org--line-empty-p 0))
 
-If point is in the middle of a headline or a list item, split the
-headline or the item and create a new headline/item with the text
-in the current line after point \(see `org-M-RET-may-split-line'
-on how to modify this behavior).
+(defun org-next-line-empty-p ()
+  "Is the previous line a blank line?
+When NEXT is non-nil, check the next line instead."
+  (org--line-empty-p 2))
 
-With one universal prefix argument, set the user option
-`org-insert-heading-respect-content' to t for the duration of
-the command.  This modifies the behavior described above in this
-ways: on list items and at the beginning of normal lines, force
-the insertion of a heading after the current subtree.
+(defun org-insert-heading (&optional arg invisible-ok top)
+  "Insert a new heading or an item with the same depth at point.
 
-With two universal prefix arguments, insert the heading at the
-end of the grandparent subtree.  For example, if point is within
-a 2nd-level heading, then it will insert a 2nd-level heading at
-the end of the 1st-level parent heading.
+If point is at the beginning of a heading or a list item, insert
+a new heading or a new item above the current one.  When at the
+beginning of a regular line of text, turn it into a heading.
+
+If point is in the middle of a line, split it and create a new
+headline/item with the text in the current line after point (see
+`org-M-RET-may-split-line' on how to modify this behavior).  As
+a special case, on a headline, splitting can only happen on the
+title itself.  E.g., this excludes breaking stars or tags.
+
+With a `\\[universal-argument]' prefix, set \
+`org-insert-heading-respect-content' to
+a non-nil value for the duration of the command.  This forces the
+insertion of a heading after the current subtree, independently
+on the location of point.
+
+With a `\\[universal-argument] \\[universal-argument]' prefix, \
+insert the heading at the end of the tree
+above the current heading.  For example, if point is within a
+2nd-level heading, then it will insert a 2nd-level heading at
+the end of the 1st-level parent subtree.
 
 When INVISIBLE-OK is set, stop at invisible headlines when going
 back.  This is important for non-interactive uses of the
-command."
+command.
+
+When optional argument TOP is non-nil, insert a level 1 heading,
+unconditionally."
   (interactive "P")
-  (if (org-called-interactively-p 'any) (org-reveal))
-  (let ((itemp (org-in-item-p))
+  (let ((itemp (and (not top) (org-in-item-p)))
        (may-split (org-get-alist-option org-M-RET-may-split-line 'headline))
        (respect-content (or org-insert-heading-respect-content
                             (equal arg '(4))))
-       (initial-content "")
-       (adjust-empty-lines t))
+       (initial-content ""))
 
     (cond
 
@@ -7621,9 +7889,7 @@ command."
               (insert "\n* ")))
       (run-hooks 'org-insert-heading-hook))
 
-     ((and itemp (not (member arg '((4) (16)))))
-      ;; Insert an item
-      (org-insert-item))
+     ((and itemp (not (member arg '((4) (16)))) (org-insert-item)))
 
      (t
       ;; Maybe move at the end of the subtree
@@ -7639,25 +7905,26 @@ command."
                                 (org-previous-line-empty-p)
                               ;; We will decide later
                               nil))
-              ;; Get a level string to fall back on
+              ;; Get a level string to fall back on.
               (fix-level
                (if (org-before-first-heading-p) "*"
                  (save-excursion
                    (org-back-to-heading t)
-                   (if (org-previous-line-empty-p) (setq empty-line-p t))
+                   (when (org-previous-line-empty-p) (setq empty-line-p t))
                    (looking-at org-outline-regexp)
                    (make-string (1- (length (match-string 0))) ?*))))
               (stars
                (save-excursion
                  (condition-case nil
-                     (progn
+                     (if top "* "
                        (org-back-to-heading invisible-ok)
                        (when (and (not on-heading)
                                   (featurep 'org-inlinetask)
                                   (integerp org-inlinetask-min-level)
                                   (>= (length (match-string 0))
                                       org-inlinetask-min-level))
-                         ;; Find a heading level before the inline task
+                         ;; Find a heading level before the inline
+                         ;; task.
                          (while (and (setq level (org-up-heading-safe))
                                      (>= level org-inlinetask-min-level)))
                          (if (org-at-heading-p)
@@ -7668,23 +7935,22 @@ command."
                                         (org-backward-heading-same-level
                                          1 invisible-ok))
                                       (= (point) (match-beginning 0)))
-                                    (not (org-previous-line-empty-p t)))
+                                    (not (org-next-line-empty-p)))
                          (setq empty-line-p (or empty-line-p
                                                 (org-previous-line-empty-p))))
                        (match-string 0))
                    (error (or fix-level "* ")))))
               (blank-a (cdr (assq 'heading org-blank-before-new-entry)))
-              (blank (if (eq blank-a 'auto) empty-line-p blank-a))
-              pos hide-previous previous-pos)
+              (blank (if (eq blank-a 'auto) empty-line-p blank-a)))
 
-         ;; If we insert after content, move there and clean up whitespace
-         (when (and respect-content
-                    (not (org-looking-at-p org-outline-regexp-bol)))
+         ;; If we insert after content, move there and clean up
+         ;; whitespace.
+         (when respect-content
            (if (not (org-before-first-heading-p))
                (org-end-of-subtree nil t)
              (re-search-forward org-outline-regexp-bol)
              (beginning-of-line 0))
-           (skip-chars-backward " \r\n")
+           (skip-chars-backward " \r\t\n")
            (and (not (looking-back "^\\*+" (line-beginning-position)))
                 (looking-at "[ \t]+") (replace-match ""))
            (unless (eobp) (forward-char 1))
@@ -7692,14 +7958,17 @@ command."
              (unless (bobp) (backward-char 1))
              (insert "\n")))
 
-         ;; If we are splitting, grab the text that should be moved to the new 
headline
+         ;; If we are splitting, grab the text that should be moved
+         ;; to the new headline.
          (when may-split
-           (if (org-on-heading-p)
-               ;; This is a heading, we split intelligently (keeping tags)
+           (if (org-at-heading-p)
+               ;; This is a heading: split intelligently (keeping
+               ;; tags).
                (let ((pos (point)))
-                 (goto-char (point-at-bol))
-                 (unless (looking-at org-complex-heading-regexp)
-                   (error "This should not happen"))
+                 (beginning-of-line)
+                 (let ((case-fold-search nil))
+                   (unless (looking-at org-complex-heading-regexp)
+                     (error "This should not happen")))
                  (when (and (match-beginning 4)
                             (> pos (match-beginning 4))
                             (< pos (match-end 4)))
@@ -7708,31 +7977,35 @@ command."
                    (delete-region (point) (match-end 4))
                    (if (looking-at "[ \t]*$")
                        (replace-match "")
-                     (insert (make-string (length initial-content) ?\ )))
+                     (insert (make-string (length initial-content) ?\s)))
                    (setq initial-content (org-trim initial-content)))
                  (goto-char pos))
-             ;; a normal line
+             ;; A normal line.
              (setq initial-content
-                   (org-trim (buffer-substring (point) (point-at-eol))))
-             (delete-region (point) (point-at-eol))))
+                   (org-trim
+                    (delete-and-extract-region (point) (line-end-position))))))
 
-         ;; If we are at the beginning of the line, insert before it.  Else 
after
+         ;; If we are at the beginning of the line, insert before it.
+         ;; Otherwise, after it.
          (cond
           ((and (bolp) (looking-at "[ \t]*$")))
-          ((and (bolp) (not (looking-at "[ \t]*$")))
-           (open-line 1))
-          (t
-           (goto-char (point-at-eol))
-           (insert "\n")))
+          ((bolp) (save-excursion (insert "\n")))
+          (t (end-of-line)
+             (insert "\n")))
 
          ;; Insert the new heading
          (insert stars)
          (just-one-space)
          (insert initial-content)
-         (when adjust-empty-lines
-           (if (or (not blank)
-                   (and blank (not (org-previous-line-empty-p))))
-               (org-N-empty-lines-before-current (if blank 1 0))))
+         (unless (and blank (org-previous-line-empty-p))
+           (org-N-empty-lines-before-current (if blank 1 0)))
+         ;; Adjust visibility, which may be messed up if we removed
+         ;; blank lines while previous entry was hidden.
+         (let ((bol (line-beginning-position)))
+           (dolist (o (overlays-at (1- bol)))
+             (when (and (eq (overlay-get o 'invisible) 'outline)
+                        (eq (overlay-end o) bol))
+               (move-overlay o (overlay-start o) (1- bol)))))
          (run-hooks 'org-insert-heading-hook)))))))
 
 (defun org-N-empty-lines-before-current (N)
@@ -7752,20 +8025,23 @@ When NO-TAGS is non-nil, don't include tags.
 When NO-TODO is non-nil, don't include TODO keywords."
   (save-excursion
     (org-back-to-heading t)
-    (cond
-     ((and no-tags no-todo)
-      (looking-at org-complex-heading-regexp)
-      (match-string 4))
-     (no-tags
-      (looking-at (concat org-outline-regexp
-                         "\\(.*?\\)"
-                         "\\(?:[ \t]+:[[:alnum:]:address@hidden:\\)?[ \t]*$"))
-      (match-string 1))
-     (no-todo
-      (looking-at org-todo-line-regexp)
-      (match-string 3))
-     (t (looking-at org-heading-regexp)
-       (match-string 2)))))
+    (let ((case-fold-search nil))
+      (cond
+       ((and no-tags no-todo)
+       (looking-at org-complex-heading-regexp)
+       ;; Return value has to be a string, but match group 4 is
+       ;; optional.
+       (or (match-string 4) ""))
+       (no-tags
+       (looking-at (concat org-outline-regexp
+                           "\\(.*?\\)"
+                           "\\(?:[ \t]+:[[:alnum:]:address@hidden:\\)?[ 
\t]*$"))
+       (match-string 1))
+       (no-todo
+       (looking-at org-todo-line-regexp)
+       (match-string 3))
+       (t (looking-at org-heading-regexp)
+         (match-string 2))))))
 
 (defvar orgstruct-mode)   ; defined below
 
@@ -7780,24 +8056,24 @@ This is a list with the following elements:
 - the tags string, or nil."
   (save-excursion
     (org-back-to-heading t)
-    (if (let (case-fold-search)
-          (looking-at
-           (if orgstruct-mode
-               org-heading-regexp
-             org-complex-heading-regexp)))
-        (if orgstruct-mode
-            (list (length (match-string 1))
-                  (org-reduced-level (length (match-string 1)))
-                  nil
-                  nil
-                  (match-string 2)
-                  nil)
-          (list (length (match-string 1))
-                (org-reduced-level (length (match-string 1)))
-                (org-match-string-no-properties 2)
-                (and (match-end 3) (aref (match-string 3) 2))
-                (org-match-string-no-properties 4)
-                (org-match-string-no-properties 5))))))
+    (when (let (case-fold-search)
+           (looking-at
+            (if orgstruct-mode
+                org-heading-regexp
+              org-complex-heading-regexp)))
+      (if orgstruct-mode
+         (list (length (match-string 1))
+               (org-reduced-level (length (match-string 1)))
+               nil
+               nil
+               (match-string 2)
+               nil)
+       (list (length (match-string 1))
+             (org-reduced-level (length (match-string 1)))
+             (match-string-no-properties 2)
+             (and (match-end 3) (aref (match-string 3) 2))
+             (match-string-no-properties 4)
+             (match-string-no-properties 5))))))
 
 (defun org-get-entry ()
   "Get the entry text, after heading, entire subtree."
@@ -7805,6 +8081,24 @@ This is a list with the following elements:
     (org-back-to-heading t)
     (buffer-substring (point-at-bol 2) (org-end-of-subtree t))))
 
+(defun org-edit-headline (&optional heading)
+  "Edit the current headline.
+Set it to HEADING when provided."
+  (interactive)
+  (org-with-wide-buffer
+   (org-back-to-heading t)
+   (let ((case-fold-search nil))
+     (when (looking-at org-complex-heading-regexp)
+       (let* ((old (match-string-no-properties 4))
+             (new (save-match-data
+                    (org-trim (or heading (read-string "Edit: " old))))))
+        (unless (equal old new)
+          (if old (replace-match new t t nil 4)
+            (goto-char (or (match-end 3) (match-end 2) (match-end 1)))
+            (insert " " new))
+          (org-set-tags nil t)
+          (when (looking-at "[ \t]*$") (replace-match ""))))))))
+
 (defun org-insert-heading-after-current ()
   "Insert a new heading with same level as current, after current subtree."
   (interactive)
@@ -7825,9 +8119,14 @@ This is a list with the following elements:
 
 (defun org-insert-todo-heading (arg &optional force-heading)
   "Insert a new heading with the same level and TODO state as current heading.
-If the heading has no TODO state, or if the state is DONE, use the first
-state (TODO by default).  Also with one prefix arg, force first state.  With
-two prefix args, force inserting at the end of the parent subtree."
+
+If the heading has no TODO state, or if the state is DONE, use
+the first state (TODO by default).  Also with one prefix arg,
+force first state.  With two prefix args, force inserting at the
+end of the parent subtree.
+
+When called at a plain list item, insert a new item with an
+unchecked check box."
   (interactive "P")
   (when (or force-heading (not (org-insert-item 'checkbox)))
     (org-insert-heading (or (and (equal arg '(16)) '(16))
@@ -7835,19 +8134,18 @@ two prefix args, force inserting at the end of the 
parent subtree."
     (save-excursion
       (org-back-to-heading)
       (outline-previous-heading)
-      (looking-at org-todo-line-regexp))
-    (let*
-        ((new-mark-x
-         (if (or (equal arg '(4))
-                 (not (match-beginning 2))
-                 (member (match-string 2) org-done-keywords))
-             (car org-todo-keywords-1)
-           (match-string 2)))
-        (new-mark
-         (or
-          (run-hook-with-args-until-success
-           'org-todo-get-default-hook new-mark-x nil)
-          new-mark-x)))
+      (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)))
+    (let* ((new-mark-x
+           (if (or (equal arg '(4))
+                   (not (match-beginning 2))
+                   (member (match-string 2) org-done-keywords))
+               (car org-todo-keywords-1)
+             (match-string 2)))
+          (new-mark
+           (or
+            (run-hook-with-args-until-success
+             'org-todo-get-default-hook new-mark-x nil)
+            new-mark-x)))
       (beginning-of-line 1)
       (and (looking-at org-outline-regexp) (goto-char (match-end 0))
           (if org-treat-insert-todo-heading-as-state-change
@@ -7895,18 +8193,17 @@ See also `org-promote'."
   (org-fix-position-after-promote))
 
 (defun org-demote-subtree ()
-  "Demote the entire subtree.  See `org-demote'.
-See also `org-promote'."
+  "Demote the entire subtree.
+See `org-demote' and `org-promote'."
   (interactive)
   (save-excursion
     (org-with-limited-levels (org-map-tree 'org-demote)))
   (org-fix-position-after-promote))
 
-
 (defun org-do-promote ()
   "Promote the current heading higher up the tree.
-If the region is active in `transient-mark-mode', promote all headings
-in the region."
+If the region is active in `transient-mark-mode', promote all
+headings in the region."
   (interactive)
   (save-excursion
     (if (org-region-active-p)
@@ -7916,8 +8213,8 @@ in the region."
 
 (defun org-do-demote ()
   "Demote the current heading lower down the tree.
-If the region is active in `transient-mark-mode', demote all headings
-in the region."
+If the region is active in `transient-mark-mode', demote all
+headings in the region."
   (interactive)
   (save-excursion
     (if (org-region-active-p)
@@ -7926,23 +8223,24 @@ in the region."
   (org-fix-position-after-promote))
 
 (defun org-fix-position-after-promote ()
-  "Make sure that after pro/demotion cursor position is right."
+  "Fix cursor position and indentation after demoting/promoting."
   (let ((pos (point)))
     (when (save-excursion
-           (beginning-of-line 1)
-           (looking-at org-todo-line-regexp)
-           (or (equal pos (match-end 1)) (equal pos (match-end 2))))
+           (beginning-of-line)
+           (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))
+           (or (eq pos (match-end 1)) (eq pos (match-end 2))))
       (cond ((eobp) (insert " "))
            ((eolp) (insert " "))
-           ((equal (char-after) ?\ ) (forward-char 1))))))
+           ((equal (char-after) ?\s) (forward-char 1))))))
 
 (defun org-current-level ()
   "Return the level of the current entry, or nil if before the first headline.
-The level is the number of stars at the beginning of the headline."
-  (save-excursion
-    (org-with-limited-levels
-     (if (ignore-errors (org-back-to-heading t))
-        (funcall outline-level)))))
+The level is the number of stars at the beginning of the
+headline.  Use `org-reduced-level' to remove the effect of
+`org-odd-levels'.  Unlike to `org-outline-level', this function
+ignores inlinetasks."
+  (let ((level (org-with-limited-levels (org-outline-level))))
+    (and (> level 0) level)))
 
 (defun org-get-previous-line-level ()
   "Return the outline depth of the last headline before the current line.
@@ -7978,50 +8276,39 @@ even level numbers will become the next higher odd 
number."
            ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
     (max 1 (+ level (or change 0)))))
 
-(if (boundp 'define-obsolete-function-alias)
-    (if (or (featurep 'xemacs) (< emacs-major-version 23))
-       (define-obsolete-function-alias 'org-get-legal-level
-         'org-get-valid-level)
-      (define-obsolete-function-alias 'org-get-legal-level
-       'org-get-valid-level "23.1")))
-
 (defun org-promote ()
-  "Promote the current heading higher up the tree.
-If the region is active in `transient-mark-mode', promote all headings
-in the region."
-  (org-back-to-heading t)
-  (let* ((level (save-match-data (funcall outline-level)))
-        (after-change-functions (remove 'flyspell-after-change-function
-                                        after-change-functions))
-        (up-head (concat (make-string (org-get-valid-level level -1) ?*) " "))
-        (diff (abs (- level (length up-head) -1))))
-    (cond ((and (= level 1) org-called-with-limited-levels
-               org-allow-promoting-top-level-subtree)
-          (replace-match "# " nil t))
-         ((= level 1)
-          (user-error "Cannot promote to level 0.  UNDO to recover if 
necessary"))
-         (t (replace-match up-head nil t)))
-    ;; Fixup tag positioning
-    (unless (= level 1)
-      (and org-auto-align-tags (org-set-tags nil 'ignore-column))
-      (if org-adapt-indentation (org-fixup-indentation (- diff))))
-    (run-hooks 'org-after-promote-entry-hook)))
+  "Promote the current heading higher up the tree."
+  (org-with-wide-buffer
+   (org-back-to-heading t)
+   (let* ((after-change-functions (remq 'flyspell-after-change-function
+                                       after-change-functions))
+         (level (save-match-data (funcall outline-level)))
+         (up-head (concat (make-string (org-get-valid-level level -1) ?*) " "))
+         (diff (abs (- level (length up-head) -1))))
+     (cond
+      ((and (= level 1) org-allow-promoting-top-level-subtree)
+       (replace-match "# " nil t))
+      ((= level 1)
+       (user-error "Cannot promote to level 0.  UNDO to recover if necessary"))
+      (t (replace-match up-head nil t)))
+     (unless (= level 1)
+       (when org-auto-align-tags (org-set-tags nil 'ignore-column))
+       (when org-adapt-indentation (org-fixup-indentation (- diff))))
+     (run-hooks 'org-after-promote-entry-hook))))
 
 (defun org-demote ()
-  "Demote the current heading lower down the tree.
-If the region is active in `transient-mark-mode', demote all headings
-in the region."
-  (org-back-to-heading t)
-  (let* ((level (save-match-data (funcall outline-level)))
-        (after-change-functions (remove 'flyspell-after-change-function
-                                        after-change-functions))
-        (down-head (concat (make-string (org-get-valid-level level 1) ?*) " "))
-        (diff (abs (- level (length down-head) -1))))
-    (replace-match down-head nil t)
-    ;; Fixup tag positioning
-    (and org-auto-align-tags (org-set-tags nil 'ignore-column))
-    (if org-adapt-indentation (org-fixup-indentation diff))
-    (run-hooks 'org-after-demote-entry-hook)))
+  "Demote the current heading lower down the tree."
+  (org-with-wide-buffer
+   (org-back-to-heading t)
+   (let* ((after-change-functions (remq 'flyspell-after-change-function
+                                       after-change-functions))
+         (level (save-match-data (funcall outline-level)))
+         (down-head (concat (make-string (org-get-valid-level level 1) ?*) " 
"))
+         (diff (abs (- level (length down-head) -1))))
+     (replace-match down-head nil t)
+     (when org-auto-align-tags (org-set-tags nil 'ignore-column))
+     (when org-adapt-indentation (org-fixup-indentation diff))
+     (run-hooks 'org-after-demote-entry-hook))))
 
 (defun org-cycle-level ()
   "Cycle the level of an empty headline through possible states.
@@ -8036,32 +8323,32 @@ After top level, it switches back to sibling level."
         (cond
          ;; If first headline in file, promote to top-level.
          ((= prev-level 0)
-          (loop repeat (/ (- cur-level 1) (org-level-increment))
-                do (org-do-promote)))
+          (cl-loop repeat (/ (- cur-level 1) (org-level-increment))
+                  do (org-do-promote)))
          ;; If same level as prev, demote one.
          ((= prev-level cur-level)
           (org-do-demote))
          ;; If parent is top-level, promote to top level if not already.
          ((= prev-level 1)
-          (loop repeat (/ (- cur-level 1) (org-level-increment))
-                do (org-do-promote)))
+          (cl-loop repeat (/ (- cur-level 1) (org-level-increment))
+                  do (org-do-promote)))
          ;; If top-level, return to prev-level.
          ((= cur-level 1)
-          (loop repeat (/ (- prev-level 1) (org-level-increment))
-                do (org-do-demote)))
+          (cl-loop repeat (/ (- prev-level 1) (org-level-increment))
+                  do (org-do-demote)))
          ;; If less than prev-level, promote one.
          ((< cur-level prev-level)
           (org-do-promote))
          ;; If deeper than prev-level, promote until higher than
          ;; prev-level.
          ((> cur-level prev-level)
-          (loop repeat (+ 1 (/ (- cur-level prev-level) (org-level-increment)))
-                do (org-do-promote))))
+          (cl-loop repeat (+ 1 (/ (- cur-level prev-level) 
(org-level-increment)))
+                  do (org-do-promote))))
         t))))
 
 (defun org-map-tree (fun)
   "Call FUN for every heading underneath the current one."
-  (org-back-to-heading)
+  (org-back-to-heading t)
   (let ((level (funcall outline-level)))
     (save-excursion
       (funcall fun)
@@ -8077,39 +8364,123 @@ After top level, it switches back to sibling level."
     (save-excursion
       (setq end (copy-marker end))
       (goto-char beg)
-      (if (and (re-search-forward org-outline-regexp-bol nil t)
-              (< (point) end))
-         (funcall fun))
+      (when (and (re-search-forward org-outline-regexp-bol nil t)
+                (< (point) end))
+       (funcall fun))
       (while (and (progn
                    (outline-next-heading)
                    (< (point) end))
                  (not (eobp)))
        (funcall fun)))))
 
-(defvar org-property-end-re) ; silence byte-compiler
 (defun org-fixup-indentation (diff)
   "Change the indentation in the current entry by DIFF.
-However, if any line in the current entry has no indentation, or if it
-would end up with no indentation after the change, nothing at all is done."
-  (save-excursion
-    (let ((end (save-excursion (outline-next-heading)
-                              (point-marker)))
-         (prohibit (if (> diff 0)
-                       "^\\S-"
-                     (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
-         col)
-      (unless (save-excursion (end-of-line 1)
-                             (re-search-forward prohibit end t))
-       (while (and (< (point) end)
-                   (re-search-forward "^[ \t]+" end t))
-         (goto-char (match-end 0))
-         (setq col (current-column))
-         (if (< diff 0) (replace-match ""))
-         (org-indent-to-column (+ diff col))))
-      (move-marker end nil))))
+
+DIFF is an integer.  Indentation is done according to the
+following rules:
+
+  - Planning information and property drawers are always indented
+    according to the new level of the headline;
+
+  - Footnote definitions and their contents are ignored;
+
+  - Inlinetasks' boundaries are not shifted;
+
+  - Empty lines are ignored;
+
+  - Other lines' indentation are shifted by DIFF columns, unless
+    it would introduce a structural change in the document, in
+    which case no shifting is done at all.
+
+Assume point is at a heading or an inlinetask beginning."
+  (org-with-wide-buffer
+   (narrow-to-region (line-beginning-position)
+                    (save-excursion
+                      (if (org-with-limited-levels (org-at-heading-p))
+                          (org-with-limited-levels (outline-next-heading))
+                        (org-inlinetask-goto-end))
+                      (point)))
+   (forward-line)
+   ;; Indent properly planning info and property drawer.
+   (when (looking-at-p org-planning-line-re)
+     (org-indent-line)
+     (forward-line))
+   (when (looking-at org-property-drawer-re)
+     (goto-char (match-end 0))
+     (forward-line)
+     (save-excursion (org-indent-region (match-beginning 0) (match-end 0))))
+   (catch 'no-shift
+     (when (zerop diff) (throw 'no-shift nil))
+     ;; If DIFF is negative, first check if a shift is possible at all
+     ;; (e.g., it doesn't break structure).  This can only happen if
+     ;; some contents are not properly indented.
+     (let ((case-fold-search t))
+       (when (< diff 0)
+        (let ((diff (- diff))
+              (forbidden-re (concat org-outline-regexp
+                                    "\\|"
+                                    (substring org-footnote-definition-re 1))))
+          (save-excursion
+            (while (not (eobp))
+              (cond
+               ((looking-at-p "[ \t]*$") (forward-line))
+               ((and (looking-at-p org-footnote-definition-re)
+                     (let ((e (org-element-at-point)))
+                       (and (eq (org-element-type e) 'footnote-definition)
+                            (goto-char (org-element-property :end e))))))
+               ((looking-at-p org-outline-regexp) (forward-line))
+               ;; Give up if shifting would move before column 0 or
+               ;; if it would introduce a headline or a footnote
+               ;; definition.
+               (t
+                (skip-chars-forward " \t")
+                (let ((ind (current-column)))
+                  (when (or (< ind diff)
+                            (and (= ind diff) (looking-at-p forbidden-re)))
+                    (throw 'no-shift nil)))
+                ;; Ignore contents of example blocks and source
+                ;; blocks if their indentation is meant to be
+                ;; preserved.  Jump to block's closing line.
+                (beginning-of-line)
+                (or (and (looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)")
+                         (let ((e (org-element-at-point)))
+                           (and (memq (org-element-type e)
+                                      '(example-block src-block))
+                                (or org-src-preserve-indentation
+                                    (org-element-property :preserve-indent e))
+                                (goto-char (org-element-property :end e))
+                                (progn (skip-chars-backward " \r\t\n")
+                                       (beginning-of-line)
+                                       t))))
+                    (forward-line))))))))
+       ;; Shift lines but footnote definitions, inlinetasks boundaries
+       ;; by DIFF.  Also skip contents of source or example blocks
+       ;; when indentation is meant to be preserved.
+       (while (not (eobp))
+        (cond
+         ((and (looking-at-p org-footnote-definition-re)
+               (let ((e (org-element-at-point)))
+                 (and (eq (org-element-type e) 'footnote-definition)
+                      (goto-char (org-element-property :end e))))))
+         ((looking-at-p org-outline-regexp) (forward-line))
+         ((looking-at-p "[ \t]*$") (forward-line))
+         (t
+          (indent-line-to (+ (org-get-indentation) diff))
+          (beginning-of-line)
+          (or (and (looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)")
+                   (let ((e (org-element-at-point)))
+                     (and (memq (org-element-type e)
+                                '(example-block src-block))
+                          (or org-src-preserve-indentation
+                              (org-element-property :preserve-indent e))
+                          (goto-char (org-element-property :end e))
+                          (progn (skip-chars-backward " \r\t\n")
+                                 (beginning-of-line)
+                                 t))))
+              (forward-line)))))))))
 
 (defun org-convert-to-odd-levels ()
-  "Convert an org-mode file with all levels allowed to one with odd levels.
+  "Convert an Org file with all levels allowed to one with odd levels.
 This will leave level 1 alone, convert level 2 to level 3, level 3 to
 level 5 etc."
   (interactive)
@@ -8125,7 +8496,7 @@ level 5 etc."
          (end-of-line 1))))))
 
 (defun org-convert-to-oddeven-levels ()
-  "Convert an org-mode file with only odd levels to one with odd/even levels.
+  "Convert an Org file with only odd levels to one with odd/even levels.
 This promotes level 3 to level 2, level 5 to level 3 etc.  If the
 file contains a section with an even level, conversion would
 destroy the structure of the file.  An error is signaled in this
@@ -8134,7 +8505,7 @@ case."
   (goto-char (point-min))
   ;; First check if there are no even levels
   (when (re-search-forward "^\\(\\*\\*\\)+ " nil t)
-    (org-show-context t)
+    (org-show-set-visibility 'canonical)
     (error "Not all levels are odd in this file.  Conversion not possible"))
   (when (yes-or-no-p "Are you sure you want to globally change levels to 
odd-even? ")
     (let ((outline-regexp org-outline-regexp)
@@ -8177,7 +8548,7 @@ case."
       (setq beg (point)))
     (save-match-data
       (save-excursion (outline-end-of-heading)
-                     (setq folded (outline-invisible-p)))
+                     (setq folded (org-invisible-p)))
       (progn (org-end-of-subtree nil t)
             (unless (eobp) (backward-char))))
     (outline-next-heading)
@@ -8196,12 +8567,12 @@ case."
          (progn (goto-char beg0)
                 (user-error "Cannot move past superior level or buffer 
limit")))
       (setq cnt (1- cnt)))
-    (if (> arg 0)
-       ;; Moving forward - still need to move over subtree
-       (progn (org-end-of-subtree t t)
-              (save-excursion
-                (org-back-over-empty-lines)
-                (or (bolp) (newline)))))
+    (when (> arg 0)
+      ;; Moving forward - still need to move over subtree
+      (org-end-of-subtree t t)
+      (save-excursion
+       (org-back-over-empty-lines)
+       (or (bolp) (newline))))
     (setq ne-ins (org-back-over-empty-lines))
     (move-marker ins-point (point))
     (setq txt (buffer-substring beg end))
@@ -8230,9 +8601,9 @@ case."
       (insert (make-string (- ne-ins ne-beg) ?\n)))
     (move-marker ins-point nil)
     (if folded
-       (hide-subtree)
+       (outline-hide-subtree)
       (org-show-entry)
-      (show-children)
+      (org-show-children)
       (org-cycle-hide-drawers 'children))
     (org-clean-visibility-after-subtree-move)
     ;; move back to the initial column we were at
@@ -8264,7 +8635,7 @@ of some markers in the region, even if CUT is non-nil.  
This is
 useful if the caller implements cut-and-paste as copy-then-paste-then-cut."
   (interactive "p")
   (let (beg end folded (beg0 (point)))
-    (if (org-called-interactively-p 'any)
+    (if (called-interactively-p 'any)
        (org-back-to-heading nil) ; take what looks like a subtree
       (org-back-to-heading t)) ; take what is really there
     (setq beg (point))
@@ -8273,11 +8644,14 @@ useful if the caller implements cut-and-paste as 
copy-then-paste-then-cut."
       (if nosubtrees
          (outline-next-heading)
        (save-excursion (outline-end-of-heading)
-                       (setq folded (outline-invisible-p)))
-       (condition-case nil
-           (org-forward-heading-same-level (1- n) t)
-         (error nil))
+                       (setq folded (org-invisible-p)))
+       (ignore-errors (org-forward-heading-same-level (1- n) t))
        (org-end-of-subtree t t)))
+    ;; Include the end of an inlinetask
+    (when (and (featurep 'org-inlinetask)
+              (looking-at-p (concat (org-inlinetask-outline-regexp)
+                                    "END[ \t]*$")))
+      (end-of-line))
     (setq end (point))
     (goto-char beg0)
     (when (> end beg)
@@ -8290,7 +8664,7 @@ useful if the caller implements cut-and-paste as 
copy-then-paste-then-cut."
               (if cut "Cut" "Copied")
               (length org-subtree-clip)))))
 
-(defun org-paste-subtree (&optional level tree for-yank)
+(defun org-paste-subtree (&optional level tree for-yank remove)
   "Paste the clipboard as a subtree, with modification of headline level.
 The entire subtree is promoted or demoted in order to match a new headline
 level.
@@ -8313,15 +8687,17 @@ If optional TREE is given, use this text instead of the 
kill ring.
 
 When FOR-YANK is set, this is called by `org-yank'.  In this case, do not
 move back over whitespace before inserting, and move point to the end of
-the inserted text when done."
+the inserted text when done.
+
+When REMOVE is non-nil, remove the subtree from the clipboard."
   (interactive "P")
   (setq tree (or tree (and kill-ring (current-kill 0))))
   (unless (org-kill-is-subtree-p tree)
     (user-error "%s"
-          (substitute-command-keys
-           "The kill is not a (set of) tree(s) - please use \\[yank] to yank 
anyway")))
+               (substitute-command-keys
+                "The kill is not a (set of) tree(s) - please use \\[yank] to 
yank anyway")))
   (org-with-limited-levels
-   (let* ((visp (not (outline-invisible-p)))
+   (let* ((visp (not (org-invisible-p)))
          (txt tree)
          (^re_ "\\(\\*+\\)[  \t]*")
          (old-level (if (string-match org-outline-regexp-bol txt)
@@ -8364,22 +8740,22 @@ the inserted text when done."
          (org-odd-levels-only nil)
          beg end newend)
      ;; Remove the forced level indicator
-     (if force-level
-        (delete-region (point-at-bol) (point)))
+     (when force-level
+       (delete-region (point-at-bol) (point)))
      ;; Paste
      (beginning-of-line (if (bolp) 1 2))
      (setq beg (point))
      (and (fboundp 'org-id-paste-tracker) (org-id-paste-tracker txt))
      (insert-before-markers txt)
-     (unless (string-match "\n\\'" txt) (insert "\n"))
+     (unless (string-suffix-p "\n" txt) (insert "\n"))
      (setq newend (point))
      (org-reinstall-markers-in-region beg)
      (setq end (point))
      (goto-char beg)
      (skip-chars-forward " \t\n\r")
      (setq beg (point))
-     (if (and (outline-invisible-p) visp)
-        (save-excursion (outline-show-heading)))
+     (when (and (org-invisible-p) visp)
+       (save-excursion (outline-show-heading)))
      ;; Shift if necessary
      (unless (= shift 0)
        (save-restriction
@@ -8389,15 +8765,16 @@ the inserted text when done."
           (setq shift (+ delta shift)))
         (goto-char (point-min))
         (setq newend (point-max))))
-     (when (or (org-called-interactively-p 'interactive) for-yank)
+     (when (or (called-interactively-p 'interactive) for-yank)
        (message "Clipboard pasted as level %d subtree" new-level))
-     (if (and (not for-yank) ; in this case, org-yank will decide about folding
-             kill-ring
-             (eq org-subtree-clip (current-kill 0))
-             org-subtree-clip-folded)
-        ;; The tree was folded before it was killed/copied
-        (hide-subtree))
-     (and for-yank (goto-char newend)))))
+     (when (and (not for-yank) ; in this case, org-yank will decide about 
folding
+               kill-ring
+               (eq org-subtree-clip (current-kill 0))
+               org-subtree-clip-folded)
+       ;; The tree was folded before it was killed/copied
+       (outline-hide-subtree))
+     (and for-yank (goto-char newend))
+     (and remove (setq kill-ring (cdr kill-ring))))))
 
 (defun org-kill-is-subtree-p (&optional txt)
   "Check if the current kill is an outline subtree, or a set of trees.
@@ -8447,15 +8824,14 @@ called immediately, to move the markers with the 
entries."
   "Check if MARKER is between BEG and END.
 If yes, remember the marker and the distance to BEG."
   (when (and (marker-buffer marker)
-            (equal (marker-buffer marker) (current-buffer)))
-    (if (and (>= marker beg) (< marker end))
-       (push (cons marker (- marker beg)) org-markers-to-move))))
+            (equal (marker-buffer marker) (current-buffer))
+            (>= marker beg) (< marker end))
+    (push (cons marker (- marker beg)) org-markers-to-move)))
 
 (defun org-reinstall-markers-in-region (beg)
   "Move all remembered markers to their position relative to BEG."
-  (mapc (lambda (x)
-         (move-marker (car x) (+ beg (cdr x))))
-       org-markers-to-move)
+  (dolist (x org-markers-to-move)
+    (move-marker (car x) (+ beg (cdr x))))
   (setq org-markers-to-move nil))
 
 (defun org-narrow-to-subtree ()
@@ -8467,7 +8843,7 @@ If yes, remember the marker and the distance to BEG."
        (narrow-to-region
        (progn (org-back-to-heading t) (point))
        (progn (org-end-of-subtree t t)
-              (if (and (org-at-heading-p) (not (eobp))) (backward-char 1))
+              (when (and (org-at-heading-p) (not (eobp))) (backward-char 1))
               (point)))))))
 
 (defun org-narrow-to-block ()
@@ -8480,10 +8856,6 @@ If yes, remember the marker and the distance to BEG."
        (narrow-to-region (car blockp) (cdr blockp))
       (user-error "Not in a block"))))
 
-(eval-when-compile
-  (defvar org-property-drawer-re))
-
-(defvar org-property-start-re)  ;; defined below
 (defun org-clone-subtree-with-time-shift (n &optional shift)
   "Clone the task (subtree) at point N times.
 The clones will be inserted as siblings.
@@ -8500,6 +8872,9 @@ stamps in the subtree shifted for each clone produced.  
If SHIFT
 is nil or the empty string, time stamps will be left alone.  The
 ID property of the original subtree is removed.
 
+In each clone, all the CLOCK entries will be removed.  This
+prevents Org from considering that the clocked times overlap.
+
 If the original subtree did contain time stamps with a repeater,
 the following will happen:
 - the repeater will be removed in each clone
@@ -8510,80 +8885,86 @@ the following will happen:
 - the start days in the repeater in the original entry will be shifted
   to past the last clone.
 In this way you can spell out a number of instances of a repeating task,
-and still retain the repeater to cover future instances of the task."
+and still retain the repeater to cover future instances of the task.
+
+As described above, N+1 clones are produced when the original
+subtree has a repeater.  Setting N to 0, then, can be used to
+remove the repeater from a subtree and create a shifted clone
+with the original repeater."
   (interactive "nNumber of clones to produce: ")
-  (let ((shift
-        (or shift
-            (if (and (not (equal current-prefix-arg '(4)))
-                     (save-excursion
-                       (re-search-forward org-ts-regexp-both
-                                          (save-excursion
-                                            (org-end-of-subtree t)
-                                            (point)) t)))
-                (read-from-minibuffer
-                 "Date shift per clone (e.g. +1w, empty to copy unchanged): ")
-              ""))) ;; No time shift
-       (n-no-remove -1)
-       (drawer-re org-drawer-regexp)
-       beg end template task idprop
-       shift-n shift-what doshift nmin nmax)
-    (if (not (and (integerp n) (> n 0)))
-       (error "Invalid number of replications %s" n))
-    (if (and (setq doshift (and (stringp shift) (string-match "\\S-" shift)))
-            (not (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([hdwmy]\\)[ 
\t]*\\'"
-                               shift)))
-       (error "Invalid shift specification %s" shift))
-    (when doshift
-      (setq shift-n (string-to-number (match-string 1 shift))
-           shift-what (cdr (assoc (match-string 2 shift)
-                                  '(("d" . day) ("w" . week)
-                                    ("m" . month) ("y" . year))))))
-    (if (eq shift-what 'week) (setq shift-n (* 7 shift-n) shift-what 'day))
-    (setq nmin 1 nmax n)
-    (org-back-to-heading t)
-    (setq beg (point))
-    (setq idprop (org-entry-get nil "ID"))
-    (org-end-of-subtree t t)
-    (or (bolp) (insert "\n"))
-    (setq end (point))
-    (setq template (buffer-substring beg end))
-    (when (and doshift
-              (string-match "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>" 
template))
-      (delete-region beg end)
-      (setq end beg)
-      (setq nmin 0 nmax (1+ nmax) n-no-remove nmax))
-    (goto-char end)
-    (loop for n from nmin to nmax do
-         ;; prepare clone
-         (with-temp-buffer
-           (insert template)
-           (org-mode)
-           (goto-char (point-min))
-           (org-show-subtree)
-           (and idprop (if org-clone-delete-id
-                           (org-entry-delete nil "ID")
-                         (org-id-get-create t)))
-           (unless (= n 0)
-             (while (re-search-forward "^[ \t]*CLOCK:.*$" nil t)
-               (kill-whole-line))
-             (goto-char (point-min))
-             (while (re-search-forward drawer-re nil t)
-               (mapc (lambda (d)
-                       (org-remove-empty-drawer-at d (point)))
-                      org-drawers)))
-           (goto-char (point-min))
-           (when doshift
-             (while (re-search-forward org-ts-regexp-both nil t)
-               (org-timestamp-change (* n shift-n) shift-what))
-             (unless (= n n-no-remove)
-               (goto-char (point-min))
-               (while (re-search-forward org-ts-regexp nil t)
-                 (save-excursion
-                   (goto-char (match-beginning 0))
-                   (if (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
-                       (delete-region (match-beginning 1) (match-end 1)))))))
-           (setq task (buffer-string)))
-         (insert task))
+  (unless (wholenump n) (user-error "Invalid number of replications %s" n))
+  (when (org-before-first-heading-p) (user-error "No subtree to clone"))
+  (let* ((beg (save-excursion (org-back-to-heading t) (point)))
+        (end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
+        (shift
+         (or shift
+             (if (and (not (equal current-prefix-arg '(4)))
+                      (save-excursion
+                        (goto-char beg)
+                        (re-search-forward org-ts-regexp-both end-of-tree t)))
+                 (read-from-minibuffer
+                  "Date shift per clone (e.g. +1w, empty to copy unchanged): ")
+               "")))                   ;No time shift
+        (doshift
+         (and (org-string-nw-p shift)
+              (or (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([dwmy]\\)[ 
\t]*\\'"
+                                shift)
+                  (user-error "Invalid shift specification %s" shift)))))
+    (goto-char end-of-tree)
+    (unless (bolp) (insert "\n"))
+    (let* ((end (point))
+          (template (buffer-substring beg end))
+          (shift-n (and doshift (string-to-number (match-string 1 shift))))
+          (shift-what (pcase (and doshift (match-string 2 shift))
+                        (`nil nil)
+                        ("d" 'day)
+                        ("w" (setq shift-n (* 7 shift-n)) 'day)
+                        ("m" 'month)
+                        ("y" 'year)
+                        (_ (error "Unsupported time unit"))))
+          (nmin 1)
+          (nmax n)
+          (n-no-remove -1)
+          (idprop (org-entry-get nil "ID")))
+      (when (and doshift
+                (string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
+                                template))
+       (delete-region beg end)
+       (setq end beg)
+       (setq nmin 0)
+       (setq nmax (1+ nmax))
+       (setq n-no-remove nmax))
+      (goto-char end)
+      (cl-loop for n from nmin to nmax do
+              (insert
+               ;; Prepare clone.
+               (with-temp-buffer
+                 (insert template)
+                 (org-mode)
+                 (goto-char (point-min))
+                 (org-show-subtree)
+                 (and idprop (if org-clone-delete-id
+                                 (org-entry-delete nil "ID")
+                               (org-id-get-create t)))
+                 (unless (= n 0)
+                   (while (re-search-forward org-clock-line-re nil t)
+                     (delete-region (line-beginning-position)
+                                    (line-beginning-position 2)))
+                   (goto-char (point-min))
+                   (while (re-search-forward org-drawer-regexp nil t)
+                     (org-remove-empty-drawer-at (point))))
+                 (goto-char (point-min))
+                 (when doshift
+                   (while (re-search-forward org-ts-regexp-both nil t)
+                     (org-timestamp-change (* n shift-n) shift-what))
+                   (unless (= n n-no-remove)
+                     (goto-char (point-min))
+                     (while (re-search-forward org-ts-regexp nil t)
+                       (save-excursion
+                         (goto-char (match-beginning 0))
+                         (when (looking-at "<[^<>\n]+\\( 
+[.+]?\\+[0-9]+[hdwmy]\\)")
+                           (delete-region (match-beginning 1) (match-end 
1)))))))
+                 (buffer-string)))))
     (goto-char beg)))
 
 ;;; Outline Sorting
@@ -8621,7 +9002,8 @@ hook gets called.  When a region or a plain list is 
sorted, the cursor
 will be in the first entry of the sorted region/list.")
 
 (defun org-sort-entries
-  (&optional with-case sorting-type getkey-func compare-func property)
+    (&optional with-case sorting-type getkey-func compare-func property
+              interactive?)
   "Sort entries on a certain level of an outline tree.
 If there is an active region, the entries in the region are sorted.
 Else, if the cursor is before the first entry, sort the top-level items.
@@ -8632,33 +9014,40 @@ a time stamp, by a property, by priority order, or by a 
custom function.
 
 The command prompts for the sorting type unless it has been given to the
 function through the SORTING-TYPE argument, which needs to be a character,
-\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?o ?O ?r ?R ?f ?F).  Here is the
-precise meaning of each character:
+\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?o ?O ?r ?R ?f ?F ?k ?K).  Here is
+the precise meaning of each character:
 
-n   Numerically, by converting the beginning of the entry/item to a number.
 a   Alphabetically, ignoring the TODO keyword and the priority, if any.
-o   By order of TODO keywords.
-t   By date/time, either the first active time stamp in the entry, or, if
-    none exist, by the first inactive one.
-s   By the scheduled date/time.
-d   By deadline date/time.
 c   By creation time, which is assumed to be the first inactive time stamp
     at the beginning of a line.
+d   By deadline date/time.
+k   By clocking time.
+n   Numerically, by converting the beginning of the entry/item to a number.
+o   By order of TODO keywords.
 p   By priority according to the cookie.
 r   By the value of a property.
+s   By scheduled date/time.
+t   By date/time, either the first active time stamp in the entry, or, if
+    none exist, by the first inactive one.
 
 Capital letters will reverse the sort order.
 
 If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be
-called with point at the beginning of the record.  It must return either
-a string or a number that should serve as the sorting key for that record.
+called with point at the beginning of the record.  It must return a
+value that is compatible with COMPARE-FUNC, the function used to
+compare entries.
 
 Comparing entries ignores case by default.  However, with an optional argument
 WITH-CASE, the sorting considers case as well.
 
 Sorting is done against the visible part of the headlines, it ignores hidden
-links."
-  (interactive "P")
+links.
+
+When sorting is done, call `org-after-sorting-entries-or-items-hook'.
+
+A non-nil value for INTERACTIVE? is used to signal that this
+function is being called interactively."
+  (interactive (list current-prefix-arg nil nil nil nil t))
   (let ((case-func (if with-case 'identity 'downcase))
        (cmstr
         ;; The clock marker is lost when using `sort-subr', let's
@@ -8677,10 +9066,10 @@ links."
       (setq end (region-end)
             what "region")
       (goto-char (region-beginning))
-      (if (not (org-at-heading-p)) (outline-next-heading))
+      (unless (org-at-heading-p) (outline-next-heading))
       (setq start (point)))
      ((or (org-at-heading-p)
-          (condition-case nil (progn (org-back-to-heading) t) (error nil)))
+          (ignore-errors (progn (org-back-to-heading) t)))
       ;; we will sort the children of the current headline
       (org-back-to-heading)
       (setq start (point)
@@ -8691,7 +9080,7 @@ links."
                       (point))
            what "children")
       (goto-char start)
-      (show-subtree)
+      (outline-show-subtree)
       (outline-next-heading))
      (t
       ;; we will sort the top-level entries in this file
@@ -8707,7 +9096,7 @@ links."
       (setq end (point-max))
       (setq what "top-level")
       (goto-char start)
-      (show-all)))
+      (outline-show-all)))
 
     (setq beg (point))
     (when (>= beg end) (goto-char start) (user-error "Nothing to sort"))
@@ -8717,32 +9106,34 @@ links."
          re (concat "^" (regexp-quote stars) " +")
          re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[ \t\n]")
          txt (buffer-substring beg end))
-    (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
-    (if (and (not (equal stars "*")) (string-match re2 txt))
-       (user-error "Region to sort contains a level above the first entry"))
+    (unless (equal (substring txt -1) "\n") (setq txt (concat txt "\n")))
+    (when (and (not (equal stars "*")) (string-match re2 txt))
+      (user-error "Region to sort contains a level above the first entry"))
 
     (unless sorting-type
       (message
        "Sort %s: [a]lpha  [n]umeric  [p]riority  p[r]operty  todo[o]rder  
[f]unc
-               [t]ime [s]cheduled  [d]eadline  [c]reated
-               A/N/P/R/O/F/T/S/D/C means reversed:"
+               [t]ime [s]cheduled  [d]eadline  [c]reated  cloc[k]ing
+               A/N/P/R/O/F/T/S/D/C/K means reversed:"
        what)
-      (setq sorting-type (read-char-exclusive))
-
-      (unless getkey-func
-       (and (= (downcase sorting-type) ?f)
-            (setq getkey-func
-                  (org-icompleting-read "Sort using function: "
-                                        obarray 'fboundp t nil nil))
-            (setq getkey-func (intern getkey-func))))
-
-      (and (= (downcase sorting-type) ?r)
-          (not property)
-           (setq property
-                 (org-icompleting-read "Property: "
-                                      (mapcar 'list (org-buffer-property-keys 
t))
-                                      nil t))))
-
+      (setq sorting-type (read-char-exclusive)))
+
+    (unless getkey-func
+      (and (= (downcase sorting-type) ?f)
+          (setq getkey-func
+                (or (and interactive?
+                         (org-read-function
+                          "Function for extracting keys: "))
+                    (error "Missing key extractor")))))
+
+    (and (= (downcase sorting-type) ?r)
+        (not property)
+        (setq property
+              (completing-read "Property: "
+                               (mapcar #'list (org-buffer-property-keys t))
+                               nil t)))
+
+    (when (member sorting-type '(?k ?K)) (org-clock-sum))
     (message "Sorting entries...")
 
     (save-restriction
@@ -8777,6 +9168,8 @@ links."
             (if (looking-at org-complex-heading-regexp)
                 (funcall case-func (org-sort-remove-invisible (match-string 
4)))
               nil))
+           ((= dcst ?k)
+            (or (get-text-property (point) :org-clock-minutes) 0))
            ((= dcst ?t)
             (let ((end (save-excursion (outline-next-heading) (point))))
               (if (or (re-search-forward org-ts-regexp end t)
@@ -8807,22 +9200,29 @@ links."
            ((= dcst ?r)
             (or (org-entry-get nil property) ""))
            ((= dcst ?o)
-            (if (looking-at org-complex-heading-regexp)
-                (- 9999 (length (member (match-string 2)
-                                        org-todo-keywords-1)))))
+            (when (looking-at org-complex-heading-regexp)
+              (let* ((m (match-string 2))
+                     (s (if (member m org-done-keywords) '- '+)))
+                (- 99 (funcall s (length (member m org-todo-keywords-1)))))))
            ((= dcst ?f)
             (if getkey-func
                 (progn
                   (setq tmp (funcall getkey-func))
-                  (if (stringp tmp) (setq tmp (funcall case-func tmp)))
+                  (when (stringp tmp) (setq tmp (funcall case-func tmp)))
                   tmp)
               (error "Invalid key function `%s'" getkey-func)))
            (t (error "Invalid sorting type `%c'" sorting-type))))
          nil
          (cond
           ((= dcst ?a) 'string<)
-          ((= dcst ?f) compare-func)
-          ((member dcst '(?p ?t ?s ?d ?c)) '<)))))
+          ((= dcst ?f)
+          (or compare-func
+              (and interactive?
+                   (org-read-function
+                    (concat "Function for comparing keys "
+                            "(empty for default `sort-subr' predicate): ")
+                    'allow-empty))))
+          ((member dcst '(?p ?t ?s ?d ?c ?k)) '<)))))
     (run-hooks 'org-after-sorting-entries-or-items-hook)
     ;; Reset the clock marker if needed
     (when cmstr
@@ -8832,60 +9232,18 @@ links."
        (move-marker org-clock-marker (point))))
     (message "Sorting entries...done")))
 
-(defun org-do-sort (table what &optional with-case sorting-type)
-  "Sort TABLE of WHAT according to SORTING-TYPE.
-The user will be prompted for the SORTING-TYPE if the call to this
-function does not specify it.  WHAT is only for the prompt, to indicate
-what is being sorted.  The sorting key will be extracted from
-the car of the elements of the table.
-If WITH-CASE is non-nil, the sorting will be case-sensitive."
-  (unless sorting-type
-    (message
-     "Sort %s: [a]lphabetic, [n]umeric, [t]ime.  A/N/T means reversed:"
-     what)
-    (setq sorting-type (read-char-exclusive)))
-  (let ((dcst (downcase sorting-type))
-       extractfun comparefun)
-    ;; Define the appropriate functions
-    (cond
-     ((= dcst ?n)
-      (setq extractfun 'string-to-number
-           comparefun (if (= dcst sorting-type) '< '>)))
-     ((= dcst ?a)
-      (setq extractfun (if with-case (lambda(x) (org-sort-remove-invisible x))
-                        (lambda(x) (downcase (org-sort-remove-invisible x))))
-           comparefun (if (= dcst sorting-type)
-                          'string<
-                        (lambda (a b) (and (not (string< a b))
-                                           (not (string= a b)))))))
-     ((= dcst ?t)
-      (setq extractfun
-           (lambda (x)
-             (if (or (string-match org-ts-regexp x)
-                     (string-match org-ts-regexp-both x))
-                 (float-time
-                  (org-time-string-to-time (match-string 0 x)))
-               0))
-           comparefun (if (= dcst sorting-type) '< '>)))
-     (t (error "Invalid sorting type `%c'" sorting-type)))
-
-    (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
-                 table)
-         (lambda (a b) (funcall comparefun (car a) (car b))))))
-
-
 ;;; The orgstruct minor mode
 
 ;; Define a minor mode which can be used in other modes in order to
-;; integrate the org-mode structure editing commands.
+;; integrate the Org mode structure editing commands.
 
-;; This is really a hack, because the org-mode structure commands use
+;; This is really a hack, because the Org mode structure commands use
 ;; keys which normally belong to the major mode.  Here is how it
 ;; works: The minor mode defines all the keys necessary to operate the
 ;; structure commands, but wraps the commands into a function which
 ;; tests if the cursor is currently at a headline or a plain list
 ;; item.  If that is the case, the structure command is used,
-;; temporarily setting many Org-mode variables like regular
+;; temporarily setting many Org mode variables like regular
 ;; expressions for filling etc.  However, when any of those keys is
 ;; used at a different location, function uses `key-binding' to look
 ;; up if the key has an associated command in another currently active
@@ -8917,10 +9275,10 @@ orgstruct(++)-mode."
 ;;;###autoload
 (define-minor-mode orgstruct-mode
   "Toggle the minor mode `orgstruct-mode'.
-This mode is for using Org-mode structure commands in other
-modes.  The following keys behave as if Org-mode were active, if
+This mode is for using Org mode structure commands in other
+modes.  The following keys behave as if Org mode were active, if
 the cursor is on a headline, or on a plain list item (both as
-defined by Org-mode)."
+defined by Org mode)."
   nil " OrgStruct" (make-sparse-keymap)
   (funcall (if orgstruct-mode
               'add-to-invisibility-spec
@@ -8937,40 +9295,38 @@ defined by Org-mode)."
   "Unconditionally turn on `orgstruct-mode'."
   (orgstruct-mode 1))
 
-(defvar org-fb-vars nil)
-(make-variable-buffer-local 'org-fb-vars)
+(defvar-local orgstruct-is-++ nil
+  "Is `orgstruct-mode' in ++ version in the current-buffer?")
+(defvar-local org-fb-vars nil)
 (defun orgstruct++-mode (&optional arg)
   "Toggle `orgstruct-mode', the enhanced version of it.
 In addition to setting orgstruct-mode, this also exports all
-indentation and autofilling variables from org-mode into the
+indentation and autofilling variables from Org mode into the
 buffer.  It will also recognize item context in multiline items."
   (interactive "P")
   (setq arg (prefix-numeric-value (or arg (if orgstruct-mode -1 1))))
   (if (< arg 1)
       (progn (orgstruct-mode -1)
-            (mapc (lambda(v)
-                    (org-set-local (car v)
-                                   (if (eq (car-safe (cadr v)) 'quote) (cadadr 
v) (cadr v))))
-                  org-fb-vars))
+            (dolist (v org-fb-vars)
+              (set (make-local-variable (car v))
+                   (if (eq (car-safe (cadr v)) 'quote)
+                       (cl-cadadr v)
+                     (nth 1 v)))))
     (orgstruct-mode 1)
     (setq org-fb-vars nil)
     (unless org-local-vars
       (setq org-local-vars (org-get-local-variables)))
     (let (var val)
-      (mapc
-       (lambda (x)
-        (when (string-match
-               
"^\\(paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\\|fill-prefix\\|indent-\\)"
-               (symbol-name (car x)))
-          (setq var (car x) val (nth 1 x))
-          (push (list var `(quote ,(eval var))) org-fb-vars)
-          (org-set-local var (if (eq (car-safe val) 'quote) (nth 1 val) val))))
-       org-local-vars)
-      (org-set-local 'orgstruct-is-++ t))))
-
-(defvar orgstruct-is-++ nil
-  "Is `orgstruct-mode' in ++ version in the current-buffer?")
-(make-variable-buffer-local 'orgstruct-is-++)
+      (dolist (x org-local-vars)
+       (when (string-match
+              "^\\(paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\
+\\|fill-prefix\\|indent-\\)"
+              (symbol-name (car x)))
+         (setq var (car x) val (nth 1 x))
+         (push (list var `(quote ,(eval var))) org-fb-vars)
+         (set (make-local-variable var)
+              (if (eq (car-safe val) 'quote) (nth 1 val) val))))
+      (setq-local orgstruct-is-++ t))))
 
 ;;;###autoload
 (defun turn-on-orgstruct++ ()
@@ -8999,6 +9355,7 @@ buffer.  It will also recognize item context in multiline 
items."
                  org-ctrl-c-minus
                  org-ctrl-c-star
                  org-cycle
+                 org-force-cycle-archived
                  org-forward-heading-same-level
                  org-insert-heading
                  org-insert-heading-respect-content
@@ -9018,6 +9375,7 @@ buffer.  It will also recognize item context in multiline 
items."
                  org-shifttab
                  org-shifttab
                  org-shiftup
+                 org-show-children
                  org-show-subtree
                  org-sort
                  org-up-element
@@ -9025,8 +9383,7 @@ buffer.  It will also recognize item context in multiline 
items."
                  outline-next-visible-heading
                  outline-previous-visible-heading
                  outline-promote
-                 outline-up-heading
-                 show-children))
+                 outline-up-heading))
     (let ((f (or (car-safe cell) cell))
          (disable-when-heading-prefix (cdr-safe cell)))
       (when (fboundp f)
@@ -9045,15 +9402,15 @@ buffer.  It will also recognize item context in 
multiline items."
                                (regexp-quote (cdr rep))
                                (car rep)
                                (key-description binding)))))
-             (pushnew binding new-bindings :test 'equal)))
+             (cl-pushnew binding new-bindings :test 'equal)))
          (dolist (binding new-bindings)
            (let ((key (lookup-key orgstruct-mode-map binding)))
              (when (or (not key) (numberp key))
-               (condition-case nil
-                   (org-defkey orgstruct-mode-map
-                               binding
-                               (orgstruct-make-binding f binding 
disable-when-heading-prefix))
-                 (error nil)))))))))
+               (ignore-errors
+                 (org-defkey orgstruct-mode-map
+                             binding
+                             (orgstruct-make-binding
+                              f binding disable-when-heading-prefix))))))))))
   (run-hooks 'orgstruct-setup-hook))
 
 (defun orgstruct-make-binding (fun key disable-when-heading-prefix)
@@ -9152,9 +9509,9 @@ definitions."
         ;; normalize contexts
         (mapcar
          (lambda(c) (cond ((listp (cadr c))
-                           (list (car c) (car c) (cadr c)))
+                           (list (car c) (car c) (nth 1 c)))
                           ((string= "" (cadr c))
-                           (list (car c) (car c) (caddr c)))
+                           (list (car c) (car c) (nth 2 c)))
                           (t c)))
           contexts))
        (a alist) r s)
@@ -9168,7 +9525,7 @@ definitions."
               (setq vrules (org-contextualize-validate-key
                             (car c) contexts)))
          (mapc (lambda (vr)
-                 (when (not (equal (car vr) (cadr vr)))
+                 (unless (equal (car vr) (cadr vr))
                    (setq repl vr)))
                 vrules)
          (if (not repl) (push c r)
@@ -9185,39 +9542,37 @@ definitions."
      (delete-dups
       (mapcar (lambda (x)
                (let ((tpl (car x)))
-                 (when (not (delq
-                             nil
-                             (mapcar (lambda (y)
-                                       (equal y tpl))
-                                      s)))
+                 (unless (delq
+                          nil
+                          (mapcar (lambda (y)
+                                    (equal y tpl))
+                                  s))
                     x)))
              (reverse r))))))
 
 (defun org-contextualize-validate-key (key contexts)
   "Check CONTEXTS for agenda or capture KEY."
-  (let (rr res)
+  (let (res)
     (dolist (r contexts)
-      (mapc
-       (lambda (rr)
-        (when
-         (and (equal key (car r))
-              (if (functionp rr) (funcall rr)
-                (or (and (eq (car rr) 'in-file)
-                         (buffer-file-name)
-                         (string-match (cdr rr) (buffer-file-name)))
-                    (and (eq (car rr) 'in-mode)
-                         (string-match (cdr rr) (symbol-name major-mode)))
-                    (and (eq (car rr) 'in-buffer)
-                         (string-match (cdr rr) (buffer-name)))
-                    (when (and (eq (car rr) 'not-in-file)
-                               (buffer-file-name))
-                      (not (string-match (cdr rr) (buffer-file-name))))
-                    (when (eq (car rr) 'not-in-mode)
-                      (not (string-match (cdr rr) (symbol-name major-mode))))
-                    (when (eq (car rr) 'not-in-buffer)
-                      (not (string-match (cdr rr) (buffer-name)))))))
-         (push r res)))
-       (car (last r))))
+      (dolist (rr (car (last r)))
+       (when
+           (and (equal key (car r))
+                (if (functionp rr) (funcall rr)
+                  (or (and (eq (car rr) 'in-file)
+                           (buffer-file-name)
+                           (string-match (cdr rr) (buffer-file-name)))
+                      (and (eq (car rr) 'in-mode)
+                           (string-match (cdr rr) (symbol-name major-mode)))
+                      (and (eq (car rr) 'in-buffer)
+                           (string-match (cdr rr) (buffer-name)))
+                      (when (and (eq (car rr) 'not-in-file)
+                                 (buffer-file-name))
+                        (not (string-match (cdr rr) (buffer-file-name))))
+                      (when (eq (car rr) 'not-in-mode)
+                        (not (string-match (cdr rr) (symbol-name major-mode))))
+                      (when (eq (car rr) 'not-in-buffer)
+                        (not (string-match (cdr rr) (buffer-name)))))))
+         (push r res))))
     (delete-dups (delq nil res))))
 
 (defun org-context-p (&rest contexts)
@@ -9235,45 +9590,47 @@ Possible values in the list of contexts are `table', 
`headline', and `item'."
                    (org-in-item-p)))
       (goto-char pos))))
 
+(defconst org-unique-local-variables
+  '(org-element--cache
+    org-element--cache-objects
+    org-element--cache-sync-keys
+    org-element--cache-sync-requests
+    org-element--cache-sync-timer)
+  "List of local variables that cannot be transferred to another buffer.")
+
 (defun org-get-local-variables ()
   "Return a list of all local variables in an Org mode buffer."
-  (let (varlist)
-    (with-current-buffer (get-buffer-create "*Org tmp*")
-      (erase-buffer)
-      (org-mode)
-      (setq varlist (buffer-local-variables)))
-    (kill-buffer "*Org tmp*")
-    (delq nil
-          (mapcar
-           (lambda (x)
-             (setq x
-                   (if (symbolp x)
-                       (list x)
-                     (list (car x) (cdr x))))
-             (if (and (not (get (car x) 'org-state))
-                      (string-match
-                       
"^\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)"
-                       (symbol-name (car x))))
-                 x nil))
-           varlist))))
+  (delq nil
+       (mapcar
+        (lambda (x)
+          (let* ((binding (if (symbolp x) (list x) (list (car x) (cdr x))))
+                 (name (car binding)))
+            (and (not (get name 'org-state))
+                 (not (memq name org-unique-local-variables))
+                 (string-match-p
+                  "\\`\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|\
+auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)"
+                  (symbol-name name))
+                 binding)))
+        (with-temp-buffer
+          (org-mode)
+          (buffer-local-variables)))))
 
 (defun org-clone-local-variables (from-buffer &optional regexp)
   "Clone local variables from FROM-BUFFER.
 Optional argument REGEXP selects variables to clone."
-  (mapc
-   (lambda (pair)
-     (and (symbolp (car pair))
-         (or (null regexp)
-             (string-match regexp (symbol-name (car pair))))
-         (set (make-local-variable (car pair))
-              (cdr pair))))
-   (buffer-local-variables from-buffer)))
+  (dolist (pair (buffer-local-variables from-buffer))
+    (pcase pair
+      (`(,name . ,value)               ;ignore unbound variables
+       (when (and (not (memq name org-unique-local-variables))
+                 (or (null regexp) (string-match-p regexp (symbol-name name))))
+        (set (make-local-variable name) value))))))
 
 ;;;###autoload
 (defun org-run-like-in-org-mode (cmd)
-  "Run a command, pretending that the current buffer is in Org-mode.
+  "Run a command, pretending that the current buffer is in Org mode.
 This will temporarily bind local variables that are typically bound in
-Org-mode to the values they have in Org-mode, and then interactively
+Org mode to the values they have in Org mode, and then interactively
 call CMD."
   (org-load-modules-maybe)
   (unless org-local-vars
@@ -9287,67 +9644,119 @@ call CMD."
     (eval `(let ,binds
             (call-interactively (quote ,cmd))))))
 
-;;;; Archiving
-
 (defun org-get-category (&optional pos force-refresh)
   "Get the category applying to position POS."
   (save-match-data
-    (if force-refresh (org-refresh-category-properties))
+    (when force-refresh (org-refresh-category-properties))
     (let ((pos (or pos (point))))
       (or (get-text-property pos 'org-category)
          (progn (org-refresh-category-properties)
                 (get-text-property pos 'org-category))))))
 
-(defun org-refresh-category-properties ()
-  "Refresh category text properties in the buffer."
-  (let ((case-fold-search t)
-       (inhibit-read-only t)
-       (def-cat (cond
-                 ((null org-category)
-                  (if buffer-file-name
-                      (file-name-sans-extension
-                       (file-name-nondirectory buffer-file-name))
-                    "???"))
-                 ((symbolp org-category) (symbol-name org-category))
-                 (t org-category)))
-       beg end cat pos optionp)
-    (org-with-silent-modifications
-     (save-excursion
-       (save-restriction
-        (widen)
-        (goto-char (point-min))
-        (put-text-property (point) (point-max) 'org-category def-cat)
-        (while (re-search-forward
-                "^\\(#\\+CATEGORY:\\|[ \t]*:CATEGORY:\\)\\(.*\\)" nil t)
-          (setq pos (match-end 0)
-                optionp (equal (char-after (match-beginning 0)) ?#)
-                cat (org-trim (match-string 2)))
-          (if optionp
-              (setq beg (point-at-bol) end (point-max))
-            (org-back-to-heading t)
-            (setq beg (point) end (org-end-of-subtree t t)))
-          (put-text-property beg end 'org-category cat)
-          (put-text-property beg end 'org-category-position beg)
-          (goto-char pos)))))))
+;;; Refresh properties
 
 (defun org-refresh-properties (dprop tprop)
   "Refresh buffer text properties.
-DPROP is the drawer property and TPROP is the corresponding text
-property to set."
-  (let ((case-fold-search t)
-       (inhibit-read-only t) p)
+DPROP is the drawer property and TPROP is either the
+corresponding text property to set, or an alist with each element
+being a text property (as a symbol) and a function to apply to
+the value of the drawer property."
+  (let* ((case-fold-search t)
+        (inhibit-read-only t)
+        (inherit? (org-property-inherit-p dprop))
+        (property-re (org-re-property (concat (regexp-quote dprop) "\\+?") t))
+        (global (and inherit? (org--property-global-value dprop nil))))
     (org-with-silent-modifications
-     (save-excursion
-       (save-restriction
-        (widen)
-        (goto-char (point-min))
-        (while (re-search-forward (concat "^[ \t]*:" dprop ": +\\(.*\\)[ 
\t]*$") nil t)
-          (setq p (org-match-string-no-properties 1))
-          (save-excursion
-            (org-back-to-heading t)
-            (put-text-property
-             (point-at-bol) (or (outline-next-heading) (point-max)) tprop 
p))))))))
+     (org-with-point-at 1
+       ;; Set global values (e.g., values defined through
+       ;; "#+PROPERTY:" keywords) to the whole buffer.
+       (when global (put-text-property (point-min) (point-max) tprop global))
+       ;; Set local values.
+       (while (re-search-forward property-re nil t)
+        (when (org-at-property-p)
+          (org-refresh-property tprop (org-entry-get (point) dprop) inherit?))
+        (outline-next-heading))))))
+
+(defun org-refresh-property (tprop p &optional inherit)
+  "Refresh the buffer text property TPROP from the drawer property P.
+The refresh happens only for the current headline, or the whole
+sub-tree if optional argument INHERIT is non-nil."
+  (unless (org-before-first-heading-p)
+    (save-excursion
+      (org-back-to-heading t)
+      (let ((start (point))
+           (end (save-excursion
+                  (if inherit (org-end-of-subtree t t)
+                    (or (outline-next-heading) (point-max))))))
+       (if (symbolp tprop)
+           ;; TPROP is a text property symbol.
+           (put-text-property start end tprop p)
+         ;; TPROP is an alist with (property . function) elements.
+         (pcase-dolist (`(,prop . ,f) tprop)
+           (put-text-property start end prop (funcall f p))))))))
 
+(defun org-refresh-category-properties ()
+  "Refresh category text properties in the buffer."
+  (let ((case-fold-search t)
+       (inhibit-read-only t)
+       (default-category
+         (cond ((null org-category)
+                (if buffer-file-name
+                    (file-name-sans-extension
+                     (file-name-nondirectory buffer-file-name))
+                  "???"))
+               ((symbolp org-category) (symbol-name org-category))
+               (t org-category))))
+    (org-with-silent-modifications
+     (org-with-wide-buffer
+      ;; Set buffer-wide category.  Search last #+CATEGORY keyword.
+      ;; This is the default category for the buffer.  If none is
+      ;; found, fall-back to `org-category' or buffer file name.
+      (put-text-property
+       (point-min) (point-max)
+       'org-category
+       (catch 'buffer-category
+        (goto-char (point-max))
+        (while (re-search-backward "^[ \t]*#\\+CATEGORY:" (point-min) t)
+          (let ((element (org-element-at-point)))
+            (when (eq (org-element-type element) 'keyword)
+              (throw 'buffer-category
+                     (org-element-property :value element)))))
+        default-category))
+      ;; Set sub-tree specific categories.
+      (goto-char (point-min))
+      (let ((regexp (org-re-property "CATEGORY")))
+       (while (re-search-forward regexp nil t)
+         (let ((value (match-string-no-properties 3)))
+           (when (org-at-property-p)
+             (put-text-property
+              (save-excursion (org-back-to-heading t) (point))
+              (save-excursion (org-end-of-subtree t t) (point))
+              'org-category
+              value)))))))))
+
+(defun org-refresh-stats-properties ()
+  "Refresh stats text properties in the buffer."
+  (org-with-silent-modifications
+   (org-with-point-at 1
+     (let ((regexp (concat org-outline-regexp-bol
+                          ".*\\[\\([0-9]*\\)\\(?:%\\|/\\([0-9]*\\)\\)\\]")))
+       (while (re-search-forward regexp nil t)
+        (let* ((numerator (string-to-number (match-string 1)))
+               (denominator (and (match-end 2)
+                                 (string-to-number (match-string 2))))
+               (stats (cond ((not denominator) numerator) ;percent
+                            ((= denominator 0) 0)
+                            (t (/ (* numerator 100) denominator)))))
+          (put-text-property (point) (progn (org-end-of-subtree t t) (point))
+                             'org-stats stats)))))))
+
+(defun org-refresh-effort-properties ()
+  "Refresh effort properties"
+  (org-refresh-properties
+   org-effort-property
+   '((effort . identity)
+     (effort-minutes . org-duration-string-to-minutes))))
 
 ;;;; Link Stuff
 
@@ -9387,78 +9796,54 @@ property to set."
 (defvar org-store-link-plist nil
   "Plist with info about the most recently link created with 
`org-store-link'.")
 
-(defvar org-link-protocols nil
-  "Link protocols added to Org-mode using `org-add-link-type'.")
+(defun org-store-link-functions ()
+  "Return a list of functions that are called to create and store a link.
+The functions defined in the :store property of
+`org-link-parameters'.
 
-(defvar org-store-link-functions nil
-  "List of functions that are called to create and store a link.
 Each function will be called in turn until one returns a non-nil
-value.  Each function should check if it is responsible for creating
-this link (for example by looking at the major mode).
-If not, it must exit and return nil.
-If yes, it should return a non-nil value after a calling
-`org-store-link-props' with a list of properties and values.
-Special properties are:
+value.  Each function should check if it is responsible for
+creating this link (for example by looking at the major mode).
+If not, it must exit and return nil.  If yes, it should return
+a non-nil value after calling `org-store-link-props' with a list
+of properties and values.  Special properties are:
 
 :type         The link prefix, like \"http\".  This must be given.
 :link         The link, like \"http://www.astro.uva.nl/~dominik\";.
               This is obligatory as well.
 :description  Optional default description for the second pair
-              of brackets in an Org-mode link.  The user can still change
-              this when inserting this link into an Org-mode buffer.
+              of brackets in an Org mode link.  The user can still change
+              this when inserting this link into an Org mode buffer.
 
 In addition to these, any additional properties can be specified
-and then used in capture templates.")
-
-(defun org-add-link-type (type &optional follow export)
-  "Add TYPE to the list of `org-link-types'.
-Re-compute all regular expressions depending on `org-link-types'
-
-FOLLOW and EXPORT are two functions.
-
-FOLLOW should take the link path as the single argument and do whatever
-is necessary to follow the link, for example find a file or display
-a mail message.
-
-EXPORT should format the link path for export to one of the export formats.
-It should be a function accepting three arguments:
-
-  path    the path of the link, the text after the prefix (like \"http:\")
-  desc    the description of the link, if any, or a description added by
-          org-export-normalize-links if there is none
-  format  the export format, a symbol like `html' or `latex' or `ascii'..
-
-The function may use the FORMAT information to return different values
-depending on the format.  The return value will be put literally into
-the exported file.  If the return value is nil, this means Org should
-do what it normally does with links which do not have EXPORT defined.
-
-Org-mode has a built-in default for exporting links.  If you are happy with
-this default, there is no need to define an export function for the link
-type.  For a simple example of an export function, see `org-bbdb.el'."
-  (add-to-list 'org-link-types type t)
-  (org-make-link-regexps)
-  (if (assoc type org-link-protocols)
-      (setcdr (assoc type org-link-protocols) (list follow export))
-    (push (list type follow export) org-link-protocols)))
+and then used in capture templates."
+  (cl-loop for link in org-link-parameters
+          with store-func
+          do (setq store-func (org-link-get-parameter (car link) :store))
+          if store-func
+          collect store-func))
 
 (defvar org-agenda-buffer-name) ; Defined in org-agenda.el
 (defvar org-id-link-to-org-use-id) ; Defined in org-id.el
 
 ;;;###autoload
 (defun org-store-link (arg)
-  "\\<org-mode-map>Store an org-link to the current location.
+  "Store an org-link to the current location.
+\\<org-mode-map>
 This link is added to `org-stored-links' and can later be inserted
-into an org-buffer with \\[org-insert-link].
+into an Org buffer with `org-insert-link' (`\\[org-insert-link]').
 
-For some link types, a prefix arg is interpreted.
-For links to Usenet articles, arg negates `org-gnus-prefer-web-links'.
-For file links, arg negates `org-context-in-file-links'.
+For some link types, a `\\[universal-argument]' prefix ARG is interpreted.  \
+A single
+`\\[universal-argument]' negates `org-context-in-file-links' for file links or
+`org-gnus-prefer-web-links' for links to Usenet articles.
 
-A double prefix arg force skipping storing functions that are not
-part of Org's core.
+A `\\[universal-argument] \\[universal-argument]' prefix ARG forces \
+skipping storing functions that are not
+part of Org core.
 
-A triple prefix arg force storing a link for each line in the
+A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \
+prefix ARG forces storing a link for each line in the
 active region."
   (interactive "P")
   (org-load-modules-maybe)
@@ -9473,111 +9858,111 @@ active region."
              (call-interactively 'org-store-link))
            (move-beginning-of-line 2)
            (set-mark (point)))))
-    (org-with-limited-levels
-     (setq org-store-link-plist nil)
-     (let (link cpltxt desc description search
-               txt custom-id agenda-link sfuns sfunsn)
-       (cond
+    (setq org-store-link-plist nil)
+    (let (link cpltxt desc description search
+              txt custom-id agenda-link sfuns sfunsn)
+      (cond
 
-       ;; Store a link using an external link type
-       ((and (not (equal arg '(16)))
-             (setq sfuns
-                   (delq
-                    nil (mapcar (lambda (f)
-                                  (let (fs) (if (funcall f) (push f fs))))
-                                org-store-link-functions))
-                   sfunsn (mapcar (lambda (fu) (symbol-name (car fu))) sfuns))
-             (or (and (cdr sfuns)
-                      (funcall (intern
-                                (completing-read
-                                 "Which function for creating the link? "
-                                 sfunsn nil t (car sfunsn)))))
-                 (funcall (caar sfuns)))
-             (setq link (plist-get org-store-link-plist :link)
-                   desc (or (plist-get org-store-link-plist
-                                       :description)
-                             link))))
-
-       ;; Store a link from a source code buffer
-       ((org-src-edit-buffer-p)
-        (let (label gc)
-          (while (or (not label)
-                     (save-excursion
-                       (save-restriction
-                         (widen)
-                         (goto-char (point-min))
-                         (re-search-forward
-                          (regexp-quote (format org-coderef-label-format 
label))
-                          nil t))))
-            (when label (message "Label exists already") (sit-for 2))
-            (setq label (read-string "Code line label: " label)))
-          (end-of-line 1)
-          (setq link (format org-coderef-label-format label))
-          (setq gc (- 79 (length link)))
-          (if (< (current-column) gc) (org-move-to-column gc t) (insert " "))
-          (insert link)
-          (setq link (concat "(" label ")") desc nil)))
-
-       ;; We are in the agenda, link to referenced location
-       ((equal (org-bound-and-true-p org-agenda-buffer-name) (buffer-name))
-        (let ((m (or (get-text-property (point) 'org-hd-marker)
-                     (get-text-property (point) 'org-marker))))
-          (when m
-            (org-with-point-at m
-              (setq agenda-link
-                    (if (org-called-interactively-p 'any)
-                        (call-interactively 'org-store-link)
-                      (org-store-link nil)))))))
-
-       ((eq major-mode 'calendar-mode)
-        (let ((cd (calendar-cursor-to-date)))
-          (setq link
-                (format-time-string
-                 (car org-time-stamp-formats)
-                 (apply 'encode-time
-                        (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
-                              nil nil nil))))
-          (org-store-link-props :type "calendar" :date cd)))
-
-       ((eq major-mode 'help-mode)
-        (setq link (concat "help:" (save-excursion
-                                     (goto-char (point-min))
-                                     (looking-at "^[^ ]+")
-                                     (match-string 0))))
-        (org-store-link-props :type "help"))
-
-       ((eq major-mode 'w3-mode)
-        (setq cpltxt (if (and (buffer-name)
-                              (not (string-match "Untitled" (buffer-name))))
-                         (buffer-name)
-                       (url-view-url t))
-              link (url-view-url t))
-        (org-store-link-props :type "w3" :url (url-view-url t)))
-
-       ((eq major-mode 'image-mode)
-        (setq cpltxt (concat "file:"
-                             (abbreviate-file-name buffer-file-name))
-              link cpltxt)
-        (org-store-link-props :type "image" :file buffer-file-name))
-
-       ;; In dired, store a link to the file of the current line
-       ((eq major-mode 'dired-mode)
-        (let ((file (dired-get-filename nil t)))
-          (setq file (if file
-                         (abbreviate-file-name
-                          (expand-file-name (dired-get-filename nil t)))
-                       ;; otherwise, no file so use current directory.
-                       default-directory))
-          (setq cpltxt (concat "file:" file)
-                link cpltxt)))
-
-       ((setq search (run-hook-with-args-until-success
-                      'org-create-file-search-functions))
-        (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
-                           "::" search))
-        (setq cpltxt (or description link)))
-
-       ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 
'org-mode))
+       ;; Store a link using an external link type
+       ((and (not (equal arg '(16)))
+            (setq sfuns
+                  (delq
+                   nil (mapcar (lambda (f)
+                                 (let (fs) (if (funcall f) (push f fs))))
+                               (org-store-link-functions)))
+                  sfunsn (mapcar (lambda (fu) (symbol-name (car fu))) sfuns))
+            (or (and (cdr sfuns)
+                     (funcall (intern
+                               (completing-read
+                                "Which function for creating the link? "
+                                sfunsn nil t (car sfunsn)))))
+                (funcall (caar sfuns)))
+            (setq link (plist-get org-store-link-plist :link)
+                  desc (or (plist-get org-store-link-plist
+                                      :description)
+                           link))))
+
+       ;; Store a link from a source code buffer.
+       ((org-src-edit-buffer-p)
+       (let ((coderef-format (org-src-coderef-format)))
+         (cond ((save-excursion
+                  (beginning-of-line)
+                  (looking-at (org-src-coderef-regexp coderef-format)))
+                (setq link (format "(%s)" (match-string-no-properties 3))))
+               ((called-interactively-p 'any)
+                (let ((label (read-string "Code line label: ")))
+                  (end-of-line)
+                  (setq link (format coderef-format label))
+                  (let ((gc (- 79 (length link))))
+                    (if (< (current-column) gc)
+                        (org-move-to-column gc t)
+                      (insert " ")))
+                  (insert link)
+                  (setq link (concat "(" label ")"))
+                  (setq desc nil)))
+               (t (setq link nil)))))
+
+       ;; We are in the agenda, link to referenced location
+       ((equal (bound-and-true-p org-agenda-buffer-name) (buffer-name))
+       (let ((m (or (get-text-property (point) 'org-hd-marker)
+                    (get-text-property (point) 'org-marker))))
+         (when m
+           (org-with-point-at m
+             (setq agenda-link
+                   (if (called-interactively-p 'any)
+                       (call-interactively 'org-store-link)
+                     (org-store-link nil)))))))
+
+       ((eq major-mode 'calendar-mode)
+       (let ((cd (calendar-cursor-to-date)))
+         (setq link
+               (format-time-string
+                (car org-time-stamp-formats)
+                (apply 'encode-time
+                       (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
+                             nil nil nil))))
+         (org-store-link-props :type "calendar" :date cd)))
+
+       ((eq major-mode 'help-mode)
+       (setq link (concat "help:" (save-excursion
+                                    (goto-char (point-min))
+                                    (looking-at "^[^ ]+")
+                                    (match-string 0))))
+       (org-store-link-props :type "help"))
+
+       ((eq major-mode 'w3-mode)
+       (setq cpltxt (if (and (buffer-name)
+                             (not (string-match "Untitled" (buffer-name))))
+                        (buffer-name)
+                      (url-view-url t))
+             link (url-view-url t))
+       (org-store-link-props :type "w3" :url (url-view-url t)))
+
+       ((eq major-mode 'image-mode)
+       (setq cpltxt (concat "file:"
+                            (abbreviate-file-name buffer-file-name))
+             link cpltxt)
+       (org-store-link-props :type "image" :file buffer-file-name))
+
+       ;; In dired, store a link to the file of the current line
+       ((derived-mode-p 'dired-mode)
+       (let ((file (dired-get-filename nil t)))
+         (setq file (if file
+                        (abbreviate-file-name
+                         (expand-file-name (dired-get-filename nil t)))
+                      ;; otherwise, no file so use current directory.
+                      default-directory))
+         (setq cpltxt (concat "file:" file)
+               link cpltxt)))
+
+       ((setq search (run-hook-with-args-until-success
+                     'org-create-file-search-functions))
+       (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
+                          "::" search))
+       (setq cpltxt (or description link)))
+
+       ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 
'org-mode))
+       (org-with-limited-levels
         (setq custom-id (org-entry-get nil "CUSTOM_ID"))
         (cond
          ;; Store a link using the target at point
@@ -9590,7 +9975,7 @@ active region."
                 link cpltxt))
          ((and (featurep 'org-id)
                (or (eq org-id-link-to-org-use-id t)
-                   (and (org-called-interactively-p 'any)
+                   (and (called-interactively-p 'any)
                         (or (eq org-id-link-to-org-use-id 
'create-if-interactive)
                             (and (eq org-id-link-to-org-use-id
                                      'create-if-interactive-and-no-custom-id)
@@ -9613,15 +9998,13 @@ active region."
                                (abbreviate-file-name
                                 (buffer-file-name (buffer-base-buffer)))))
           ;; Add a context search string
-          (when (org-xor org-context-in-file-links arg)
-            (let* ((ee (org-element-at-point))
-                   (et (org-element-type ee))
-                   (ev (plist-get (cadr ee) :value))
-                   (ek (plist-get (cadr ee) :key))
-                   (eok (and (stringp ek) (string-match "name" ek))))
+          (when (org-xor org-context-in-file-links
+                         (equal arg '(4)))
+            (let* ((element (org-element-at-point))
+                   (name (org-element-property :name element)))
               (setq txt (cond
                          ((org-at-heading-p) nil)
-                         ((and (eq et 'keyword) eok) ev)
+                         (name)
                          ((org-region-active-p)
                           (buffer-substring (region-beginning) (region-end)))))
               (when (or (null txt) (string-match "\\S-" txt))
@@ -9630,74 +10013,80 @@ active region."
                               (condition-case nil
                                   (org-make-org-heading-search-string txt)
                                 (error "")))
-                      desc (or (and (eq et 'keyword) eok ev)
+                      desc (or name
                                (nth 4 (ignore-errors (org-heading-components)))
                                "NONE")))))
-          (if (string-match "::\\'" cpltxt)
-              (setq cpltxt (substring cpltxt 0 -2)))
-          (setq link cpltxt))))
-
-       ((buffer-file-name (buffer-base-buffer))
-        ;; Just link to this file here.
-        (setq cpltxt (concat "file:"
-                             (abbreviate-file-name
-                              (buffer-file-name (buffer-base-buffer)))))
-        ;; Add a context string.
-        (when (org-xor org-context-in-file-links arg)
-          (setq txt (if (org-region-active-p)
-                        (buffer-substring (region-beginning) (region-end))
-                      (buffer-substring (point-at-bol) (point-at-eol))))
-          ;; Only use search option if there is some text.
-          (when (string-match "\\S-" txt)
-            (setq cpltxt
-                  (concat cpltxt "::" (org-make-org-heading-search-string txt))
-                  desc "NONE")))
-        (setq link cpltxt))
-
-       ((org-called-interactively-p 'interactive)
-        (user-error "No method for storing a link from this buffer"))
-
-       (t (setq link nil)))
-
-       ;; We're done setting link and desc, clean up
-       (if (consp link) (setq cpltxt (car link) link (cdr link)))
-       (setq link (or link cpltxt)
-            desc (or desc cpltxt))
-       (cond ((equal desc "NONE") (setq desc nil))
-            ((and desc (string-match org-bracket-link-analytic-regexp desc))
-             (let ((d0 (match-string 3 desc))
-                   (p0 (match-string 5 desc)))
-               (setq desc
-                     (replace-regexp-in-string
-                      org-bracket-link-regexp
-                      (concat (or p0 d0)
-                              (if (equal (length (match-string 0 desc))
-                                         (length desc)) "*" "")) desc)))))
-
-       ;; Return the link
-       (if (not (and (or (org-called-interactively-p 'any)
-                        executing-kbd-macro)
-                     link))
-          (or agenda-link (and link (org-make-link-string link desc)))
-        (push (list link desc) org-stored-links)
-        (message "Stored: %s" (or desc link))
-        (when custom-id
-          (setq link (concat "file:" (abbreviate-file-name
-                                      (buffer-file-name)) "::#" custom-id))
-          (push (list link desc) org-stored-links))
-        (car org-stored-links))))))
+          (when (string-match "::\\'" cpltxt)
+            (setq cpltxt (substring cpltxt 0 -2)))
+          (setq link cpltxt)))))
+
+       ((buffer-file-name (buffer-base-buffer))
+       ;; Just link to this file here.
+       (setq cpltxt (concat "file:"
+                            (abbreviate-file-name
+                             (buffer-file-name (buffer-base-buffer)))))
+       ;; Add a context string.
+       (when (org-xor org-context-in-file-links
+                      (equal arg '(4)))
+         (setq txt (if (org-region-active-p)
+                       (buffer-substring (region-beginning) (region-end))
+                     (buffer-substring (point-at-bol) (point-at-eol))))
+         ;; Only use search option if there is some text.
+         (when (string-match "\\S-" txt)
+           (setq cpltxt
+                 (concat cpltxt "::" (org-make-org-heading-search-string txt))
+                 desc "NONE")))
+       (setq link cpltxt))
+
+       ((called-interactively-p 'interactive)
+       (user-error "No method for storing a link from this buffer"))
+
+       (t (setq link nil)))
+
+      ;; We're done setting link and desc, clean up
+      (when (consp link) (setq cpltxt (car link) link (cdr link)))
+      (setq link (or link cpltxt)
+           desc (or desc cpltxt))
+      (cond ((not desc))
+           ((equal desc "NONE") (setq desc nil))
+           (t (setq desc
+                    (replace-regexp-in-string
+                     org-bracket-link-analytic-regexp
+                     (lambda (m) (or (match-string 5 m) (match-string 3 m)))
+                     desc))))
+      ;; Return the link
+      (if (not (and (or (called-interactively-p 'any)
+                       executing-kbd-macro)
+                   link))
+         (or agenda-link (and link (org-make-link-string link desc)))
+       (push (list link desc) org-stored-links)
+       (message "Stored: %s" (or desc link))
+       (when custom-id
+         (setq link (concat "file:" (abbreviate-file-name
+                                     (buffer-file-name)) "::#" custom-id))
+         (push (list link desc) org-stored-links))
+       (car org-stored-links)))))
 
 (defun org-store-link-props (&rest plist)
-  "Store link properties, extract names and addresses."
-  (let (x adr)
-    (when (setq x (plist-get plist :from))
-      (setq adr (mail-extract-address-components x))
-      (setq plist (plist-put plist :fromname (car adr)))
-      (setq plist (plist-put plist :fromaddress (nth 1 adr))))
-    (when (setq x (plist-get plist :to))
-      (setq adr (mail-extract-address-components x))
-      (setq plist (plist-put plist :toname (car adr)))
-      (setq plist (plist-put plist :toaddress (nth 1 adr)))))
+  "Store link properties, extract names, addresses and dates."
+  (let ((x (plist-get plist :from)))
+    (when x
+      (let ((adr (mail-extract-address-components x)))
+       (setq plist (plist-put plist :fromname (car adr)))
+       (setq plist (plist-put plist :fromaddress (nth 1 adr))))))
+  (let ((x (plist-get plist :to)))
+    (when x
+      (let ((adr (mail-extract-address-components x)))
+       (setq plist (plist-put plist :toname (car adr)))
+       (setq plist (plist-put plist :toaddress (nth 1 adr))))))
+  (let ((x (ignore-errors (date-to-time (plist-get plist :date)))))
+    (when x
+      (setq plist (plist-put plist :date-timestamp
+                            (format-time-string
+                             (org-time-stamp-format t) x)))
+      (setq plist (plist-put plist :date-timestamp-inactive
+                            (format-time-string
+                             (org-time-stamp-format t t) x)))))
   (let ((from (plist-get plist :from))
        (to (plist-get plist :to)))
     (when (and from to org-from-is-user-regexp)
@@ -9763,45 +10152,34 @@ according to FMT (default from 
`org-email-link-description-format')."
 
 (defun org-make-link-string (link &optional description)
   "Make a link with brackets, consisting of LINK and DESCRIPTION."
-  (unless (string-match "\\S-" link)
-    (error "Empty link"))
-  (when (and description
-            (stringp description)
-            (not (string-match "\\S-" description)))
-    (setq description nil))
-  (when (stringp description)
-    ;; Remove brackets from the description, they are fatal.
-    (while (string-match "\\[" description)
-      (setq description (replace-match "{" t t description)))
-    (while (string-match "\\]" description)
-      (setq description (replace-match "}" t t description))))
-  (when (equal link description)
-    ;; No description needed, it is identical
-    (setq description nil))
-  (when (and (not description)
-            (not (string-match (org-image-file-name-regexp) link))
-            (not (equal link (org-link-escape link))))
-    (setq description (org-extract-attributes link)))
-  (setq link
-       (cond ((string-match (org-image-file-name-regexp) link) link)
-             ((string-match org-link-types-re link)
-              (concat (match-string 1 link)
-                      (org-link-escape (substring link (match-end 1)))))
-             (t (org-link-escape link))))
-  (concat "[[" link "]"
-         (if description (concat "[" description "]") "")
-         "]"))
+  (unless (org-string-nw-p link) (error "Empty link"))
+  (let ((uri (cond ((string-match org-link-types-re link)
+                   (concat (match-string 1 link)
+                           (org-link-escape (substring link (match-end 1)))))
+                  ;; For readability, url-encode internal links only
+                  ;; when absolutely needed (i.e, when they contain
+                  ;; square brackets).  File links however, are
+                  ;; encoded since, e.g., spaces are significant.
+                  ((or (file-name-absolute-p link)
+                       (string-match-p "\\`\\.\\.?/\\|[][]" link))
+                   (org-link-escape link))
+                  (t link)))
+       (description
+        (and (org-string-nw-p description)
+             ;; Remove brackets from description, as they are fatal.
+             (replace-regexp-in-string
+              "[][]" (lambda (m) (if (equal "[" m) "{" "}"))
+              (org-trim description)))))
+    (format "[[%s]%s]"
+           uri
+           (if description (format "[%s]" description) ""))))
 
 (defconst org-link-escape-chars
-  '(?\ ?\[ ?\] ?\; ?\= ?\+)
-  "List of characters that should be escaped in link.
+  ;;%20 %5B %5D %25
+  '(?\s ?\[ ?\] ?%)
+  "List of characters that should be escaped in a link when stored to Org.
 This is the list that is used for internal purposes.")
 
-(defconst org-link-escape-chars-browser
-  '(?\  ?\")
-  "List of escapes for characters that are problematic in links.
-This is the list that is used before handing over to the browser.")
-
 (defun org-link-escape (text &optional table merge)
   "Return percent escaped representation of TEXT.
 TEXT is a string with the text to escape.
@@ -9809,35 +10187,29 @@ Optional argument TABLE is a list with characters that 
should be
 escaped.  When nil, `org-link-escape-chars' is used.
 If optional argument MERGE is set, merge TABLE into
 `org-link-escape-chars'."
-  (cond
-   ((and table merge)
-    (mapc (lambda (defchr)
-           (unless (member defchr table)
-             (setq table (cons defchr table)))) org-link-escape-chars))
-   ((null table)
-    (setq table org-link-escape-chars)))
-  (mapconcat
-   (lambda (char)
-     (if (or (member char table)
-            (and (or (< char 32) (= char 37) (> char 126))
-                 org-url-hexify-p))
-        (mapconcat (lambda (sequence-element)
-                     (format "%%%.2X" sequence-element))
-                   (or (encode-coding-char char 'utf-8)
-                       (error "Unable to percent escape character: %s"
-                              (char-to-string char))) "")
-       (char-to-string char))) text ""))
+  (let ((characters-to-encode
+        (cond ((null table) org-link-escape-chars)
+              (merge (append org-link-escape-chars table))
+              (t table))))
+    (mapconcat
+     (lambda (c)
+       (if (or (memq c characters-to-encode)
+              (and org-url-hexify-p (or (< c 32) (> c 126))))
+          (mapconcat (lambda (e) (format "%%%.2X" e))
+                     (or (encode-coding-char c 'utf-8)
+                         (error "Unable to percent escape character: %c" c))
+                     "")
+        (char-to-string c)))
+     text "")))
 
 (defun org-link-unescape (str)
-  "Unhex hexified Unicode strings as returned from the JavaScript function
-encodeURIComponent.  E.g. `%C3%B6' is the german o-Umlaut."
-  (unless (and (null str) (string= "" str))
-    (let ((pos 0) (case-fold-search t) unhexed)
-      (while (setq pos (string-match "\\(%[0-9a-f][0-9a-f]\\)+" str pos))
-       (setq unhexed (org-link-unescape-compound (match-string 0 str)))
-       (setq str (replace-match unhexed t t str))
-       (setq pos (+ pos (length unhexed))))))
-  str)
+  "Unhex hexified Unicode parts in string STR.
+E.g. `%C3%B6' becomes the german o-Umlaut.  This is the
+reciprocal of `org-link-escape', which see."
+  (if (org-string-nw-p str)
+      (replace-regexp-in-string
+       "\\(%[0-9A-Za-z]\\{2\\}\\)+" #'org-link-unescape-compound str t t)
+    str))
 
 (defun org-link-unescape-compound (hex)
   "Unhexify Unicode hex-chars.  E.g. `%C3%B6' is the German o-Umlaut.
@@ -9860,18 +10232,17 @@ Note: this function also decodes single byte encodings 
like
                     ((>= val 192) (cons 2 192))
                     (t (cons 0 0)))
                  (cons 6 128))))
-         (if (>= val 192) (setq eat (car shift-xor)))
+         (when (>= val 192) (setq eat (car shift-xor)))
          (setq val (logxor val (cdr shift-xor)))
          (setq sum (+ (lsh sum (car shift-xor)) val))
-         (if (> eat 0) (setq eat (- eat 1)))
+         (when (> eat 0) (setq eat (- eat 1)))
          (cond
           ((= 0 eat)                   ;multi byte
-           (setq ret (concat ret (org-char-to-string sum)))
+           (setq ret (concat ret (char-to-string sum)))
            (setq sum 0))
           ((not bytes)                 ; single byte(s)
-           (setq ret (org-link-unescape-single-byte-sequence hex))))
-         )) ;; end (while bytes
-      ret )))
+           (setq ret (org-link-unescape-single-byte-sequence hex))))))
+      ret)))
 
 (defun org-link-unescape-single-byte-sequence (hex)
   "Unhexify hex-encoded single byte character sequences."
@@ -9901,28 +10272,47 @@ Note: this function also decodes single byte encodings 
like
 
 (defun org-link-prettify (link)
   "Return a human-readable representation of LINK.
-The car of LINK must be a raw link the cdr of LINK must be either
-a link description or nil."
+The car of LINK must be a raw link.
+The cdr of LINK must be either a link description or nil."
   (let ((desc (or (cadr link) "<no description>")))
     (concat (format "%-45s" (substring desc 0 (min (length desc) 40)))
            "<" (car link) ">")))
 
 ;;;###autoload
 (defun org-insert-link-global ()
-  "Insert a link like Org-mode does.
-This command can be called in any mode to insert a link in Org-mode syntax."
+  "Insert a link like Org mode does.
+This command can be called in any mode to insert a link in Org syntax."
   (interactive)
   (org-load-modules-maybe)
   (org-run-like-in-org-mode 'org-insert-link))
 
-(defun org-insert-all-links (&optional keep)
-  "Insert all links in `org-stored-links'."
+(defun org-insert-all-links (arg &optional pre post)
+  "Insert all links in `org-stored-links'.
+When a universal prefix, do not delete the links from `org-stored-links'.
+When `ARG' is a number, insert the last N link(s).
+`PRE' and `POST' are optional arguments to define a string to
+prepend or to append."
   (interactive "P")
-  (let ((links (copy-sequence org-stored-links)) l)
-    (while (setq l (if keep (pop links) (pop org-stored-links)))
-      (insert "- ")
-      (org-insert-link nil (car l) (or (cadr l) "<no description>"))
-      (insert "\n"))))
+  (let ((org-keep-stored-link-after-insertion (equal arg '(4)))
+       (links (copy-sequence org-stored-links))
+       (pr (or pre "- "))
+       (po (or post "\n"))
+       (cnt 1) l)
+    (if (null org-stored-links)
+       (message "No link to insert")
+      (while (and (or (listp arg) (>= arg cnt))
+                 (setq l (if (listp arg)
+                             (pop links)
+                           (pop org-stored-links))))
+       (setq cnt (1+ cnt))
+       (insert pr)
+       (org-insert-link nil (car l) (or (cadr l) "<no description>"))
+       (insert po)))))
+
+(defun org-insert-last-stored-link (arg)
+  "Insert the last link stored in `org-stored-links'."
+  (interactive "p")
+  (org-insert-all-links arg "" "\n"))
 
 (defun org-link-fontify-links-to-this-file ()
   "Fontify links to the current file in `org-stored-links'."
@@ -9946,73 +10336,73 @@ This command can be called in any mode to insert a 
link in Org-mode syntax."
              (put-text-property 0 (length l) 'face 'font-lock-comment-face l))
            (delq nil (append a b)))))
 
-(defvar org-link-links-in-this-file nil)
+(defvar org--links-history nil)
 (defun org-insert-link (&optional complete-file link-location 
default-description)
   "Insert a link.  At the prompt, enter the link.
 
-Completion can be used to insert any of the link protocol prefixes like
-http or ftp in use.
+Completion can be used to insert any of the link protocol prefixes in use.
 
 The history can be used to select a link previously stored with
 `org-store-link'.  When the empty string is entered (i.e. if you just
-press RET at the prompt), the link defaults to the most recently
-stored link.  As SPC triggers completion in the minibuffer, you need to
-use M-SPC or C-q SPC to force the insertion of a space character.
+press `RET' at the prompt), the link defaults to the most recently
+stored link.  As `SPC' triggers completion in the minibuffer, you need to
+use `M-SPC' or `C-q SPC' to force the insertion of a space character.
 
 You will also be prompted for a description, and if one is given, it will
 be displayed in the buffer instead of the link.
 
-If there is already a link at point, this command will allow you to edit link
-and description parts.
+If there is already a link at point, this command will allow you to edit
+link and description parts.
 
-With a \\[universal-argument] prefix, prompts for a file to link to.  The file 
name can
-be selected using completion.  The path to the file will be relative to the
+With a `\\[universal-argument]' prefix, prompts for a file to link to.  The \
+file name can be
+selected using completion.  The path to the file will be relative to the
 current directory if the file is in the current directory or a subdirectory.
 Otherwise, the link will be the absolute path as completed in the minibuffer
 \(i.e. normally ~/path/to/file).  You can configure this behavior using the
 option `org-link-file-path-type'.
 
-With two \\[universal-argument] prefixes, enforce an absolute path even if the 
file is in
+With a `\\[universal-argument] \\[universal-argument]' prefix, enforce an \
+absolute path even if the file is in
 the current directory or below.
 
-With three \\[universal-argument] prefixes, negate the meaning of
-`org-keep-stored-link-after-insertion'.
+A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \
+prefix negates `org-keep-stored-link-after-insertion'.
 
 If `org-make-link-description-function' is non-nil, this function will be
 called with the link target, and the result will be the default
 link description.
 
-If the LINK-LOCATION parameter is non-nil, this value will be
-used as the link location instead of reading one interactively.
+If the LINK-LOCATION parameter is non-nil, this value will be used as
+the link location instead of reading one interactively.
 
-If the DEFAULT-DESCRIPTION parameter is non-nil, this value will
-be used as the default description."
+If the DEFAULT-DESCRIPTION parameter is non-nil, this value will be used
+as the default description."
   (interactive "P")
   (let* ((wcf (current-window-configuration))
         (origbuf (current-buffer))
-        (region (if (org-region-active-p)
-                    (buffer-substring (region-beginning) (region-end))))
+        (region (when (org-region-active-p)
+                  (buffer-substring (region-beginning) (region-end))))
         (remove (and region (list (region-beginning) (region-end))))
         (desc region)
-        tmphist ; byte-compile incorrectly complains about this
         (link link-location)
         (abbrevs org-link-abbrev-alist-local)
-        entry file all-prefixes auto-desc)
+        entry all-prefixes auto-desc)
     (cond
-     (link-location) ; specified by arg, just use it.
+     (link-location)                 ; specified by arg, just use it.
      ((org-in-regexp org-bracket-link-regexp 1)
       ;; We do have a link at point, and we are going to edit it.
       (setq remove (list (match-beginning 0) (match-end 0)))
-      (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
+      (setq desc (when (match-end 3) (match-string-no-properties 3)))
       (setq link (read-string "Link: "
                              (org-link-unescape
-                              (org-match-string-no-properties 1)))))
+                              (match-string-no-properties 1)))))
      ((or (org-in-regexp org-angle-link-re)
          (org-in-regexp org-plain-link-re))
       ;; Convert to bracket link
       (setq remove (list (match-beginning 0) (match-end 0))
            link (read-string "Link: "
-                             (org-remove-angle-brackets (match-string 0)))))
+                             (org-unbracket-string "<" ">" (match-string 0)))))
      ((member complete-file '((4) (16)))
       ;; Completing read for file names.
       (setq link (org-file-complete-link complete-file)))
@@ -10035,92 +10425,91 @@ Use TAB to complete link prefixes, then RET for 
type-specific completion support
        (unless (pos-visible-in-window-p (point-max))
          (org-fit-window-to-buffer))
        (and (window-live-p cw) (select-window cw)))
-      ;; Fake a link history, containing the stored links.
-      (setq tmphist (append (mapcar 'car org-stored-links)
-                           org-insert-link-history))
       (setq all-prefixes (append (mapcar 'car abbrevs)
                                 (mapcar 'car org-link-abbrev-alist)
-                                org-link-types))
+                                (org-link-types)))
       (unwind-protect
-         (progn
+         ;; Fake a link history, containing the stored links.
+         (let ((org--links-history
+                (append (mapcar #'car org-stored-links)
+                        org-insert-link-history)))
            (setq link
                  (org-completing-read
                   "Link: "
                   (append
-                   (mapcar (lambda (x) (concat x ":"))
-                           all-prefixes)
-                   (mapcar 'car org-stored-links))
+                   (mapcar (lambda (x) (concat x ":")) all-prefixes)
+                   (mapcar #'car org-stored-links))
                   nil nil nil
-                  'tmphist
+                  'org--links-history
                   (caar org-stored-links)))
-           (if (not (string-match "\\S-" link))
-               (user-error "No link selected"))
-           (mapc (lambda(l)
-                   (when (equal link (cadr l)) (setq link (car l) auto-desc 
t)))
-                 org-stored-links)
-           (if (or (member link all-prefixes)
-                   (and (equal ":" (substring link -1))
-                        (member (substring link 0 -1) all-prefixes)
-                        (setq link (substring link 0 -1))))
-               (setq link (with-current-buffer origbuf
-                            (org-link-try-special-completion link)))))
+           (unless (org-string-nw-p link) (user-error "No link selected"))
+           (dolist (l org-stored-links)
+             (when (equal link (cadr l))
+               (setq link (car l))
+               (setq auto-desc t)))
+           (when (or (member link all-prefixes)
+                     (and (equal ":" (substring link -1))
+                          (member (substring link 0 -1) all-prefixes)
+                          (setq link (substring link 0 -1))))
+             (setq link (with-current-buffer origbuf
+                          (org-link-try-special-completion link)))))
        (set-window-configuration wcf)
        (kill-buffer "*Org Links*"))
       (setq entry (assoc link org-stored-links))
       (or entry (push link org-insert-link-history))
       (setq desc (or desc (nth 1 entry)))))
 
-    (if (funcall (if (equal complete-file '(64)) 'not 'identity)
-                (not org-keep-stored-link-after-insertion))
-       (setq org-stored-links (delq (assoc link org-stored-links)
-                                    org-stored-links)))
+    (when (funcall (if (equal complete-file '(64)) 'not 'identity)
+                  (not org-keep-stored-link-after-insertion))
+      (setq org-stored-links (delq (assoc link org-stored-links)
+                                  org-stored-links)))
 
-    (if (and (string-match org-plain-link-re link)
-            (not (string-match org-ts-regexp link)))
-       ;; URL-like link, normalize the use of angular brackets.
-       (setq link (org-remove-angle-brackets link)))
+    (when (and (string-match org-plain-link-re link)
+              (not (string-match org-ts-regexp link)))
+      ;; URL-like link, normalize the use of angular brackets.
+      (setq link (org-unbracket-string "<" ">" link)))
 
     ;; Check if we are linking to the current file with a search
     ;; option If yes, simplify the link by using only the search
     ;; option.
     (when (and buffer-file-name
-              (string-match "^file:\\(.+?\\)::\\(.+\\)" link))
-      (let* ((path (match-string 1 link))
-            (case-fold-search nil)
-            (search (match-string 2 link)))
+              (let ((case-fold-search nil))
+                (string-match "\\`file:\\(.+?\\)::" link)))
+      (let ((path (match-string-no-properties 1 link))
+           (search (substring-no-properties link (match-end 0))))
        (save-match-data
-         (if (equal (file-truename buffer-file-name) (file-truename path))
-             ;; We are linking to this same file, with a search option
-             (setq link search)))))
+         (when (equal (file-truename buffer-file-name) (file-truename path))
+           ;; We are linking to this same file, with a search option
+           (setq link search)))))
 
     ;; Check if we can/should use a relative path.  If yes, simplify the link
-    (when (string-match "^\\(file:\\|docview:\\)\\(.*\\)" link)
-      (let* ((type (match-string 1 link))
-            (path (match-string 2 link))
-            (origpath path)
-            (case-fold-search nil))
-       (cond
-        ((or (eq org-link-file-path-type 'absolute)
-             (equal complete-file '(16)))
-         (setq path (abbreviate-file-name (expand-file-name path))))
-        ((eq org-link-file-path-type 'noabbrev)
-         (setq path (expand-file-name path)))
-        ((eq org-link-file-path-type 'relative)
-         (setq path (file-relative-name path)))
-        (t
-         (save-match-data
-           (if (string-match (concat "^" (regexp-quote
-                                          (expand-file-name
-                                           (file-name-as-directory
-                                            default-directory))))
-                             (expand-file-name path))
-               ;; We are linking a file with relative path name.
-               (setq path (substring (expand-file-name path)
-                                     (match-end 0)))
-             (setq path (abbreviate-file-name (expand-file-name path)))))))
-       (setq link (concat type path))
-       (if (equal desc origpath)
-           (setq desc path))))
+    (let ((case-fold-search nil))
+      (when (string-match "\\`\\(file\\|docview\\):" link)
+       (let* ((type (match-string-no-properties 0 link))
+              (path (substring-no-properties link (match-end 0)))
+              (origpath path))
+         (cond
+          ((or (eq org-link-file-path-type 'absolute)
+               (equal complete-file '(16)))
+           (setq path (abbreviate-file-name (expand-file-name path))))
+          ((eq org-link-file-path-type 'noabbrev)
+           (setq path (expand-file-name path)))
+          ((eq org-link-file-path-type 'relative)
+           (setq path (file-relative-name path)))
+          (t
+           (save-match-data
+             (if (string-match (concat "^" (regexp-quote
+                                            (expand-file-name
+                                             (file-name-as-directory
+                                              default-directory))))
+                               (expand-file-name path))
+                 ;; We are linking a file with relative path name.
+                 (setq path (substring (expand-file-name path)
+                                       (match-end 0)))
+               (setq path (abbreviate-file-name (expand-file-name path)))))))
+         (setq link (concat type path))
+         (when (equal desc origpath)
+           (setq desc path)))))
 
     (if org-make-link-description-function
        (setq desc
@@ -10135,49 +10524,36 @@ Use TAB to complete link prefixes, then RET for 
type-specific completion support
                       (read-string "Description: " desc)))))
 
     (unless (string-match "\\S-" desc) (setq desc nil))
-    (if remove (apply 'delete-region remove))
-    (insert (org-make-link-string link desc))))
+    (when remove (apply 'delete-region remove))
+    (insert (org-make-link-string link desc))
+    ;; Redisplay so as the new link has proper invisible characters.
+    (sit-for 0)))
 
 (defun org-link-try-special-completion (type)
   "If there is completion support for link type TYPE, offer it."
-  (let ((fun (intern (concat "org-" type "-complete-link"))))
+  (let ((fun (org-link-get-parameter type :complete)))
     (if (functionp fun)
        (funcall fun)
       (read-string "Link (no completion support): " (concat type ":")))))
 
 (defun org-file-complete-link (&optional arg)
   "Create a file link using completion."
-  (let (file link)
-    (setq file (org-iread-file-name "File: "))
-    (let ((pwd (file-name-as-directory (expand-file-name ".")))
-         (pwd1 (file-name-as-directory (abbreviate-file-name
-                                        (expand-file-name ".")))))
-      (cond
-       ((equal arg '(16))
-       (setq link (concat
-                   "file:"
-                   (abbreviate-file-name (expand-file-name file)))))
-       ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
-       (setq link  (concat "file:" (match-string 1 file))))
-       ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
-                     (expand-file-name file))
-       (setq link  (concat
-                    "file:" (match-string 1 (expand-file-name file)))))
-       (t (setq link (concat "file:" file)))))
-    link))
-
-(defun org-iread-file-name (&rest args)
-  "Read-file-name using `ido-mode' speedup if available.
-ARGS are arguments that may be passed to `ido-read-file-name' or 
`read-file-name'.
-See `read-file-name' for a description of parameters."
-  (org-without-partial-completion
-   (if (and org-completion-use-ido
-            (fboundp 'ido-read-file-name)
-            (boundp 'ido-mode) ido-mode
-            (listp (second args)))
-       (let ((ido-enter-matching-directory nil))
-         (apply 'ido-read-file-name args))
-     (apply 'read-file-name args))))
+  (let ((file (read-file-name "File: "))
+       (pwd (file-name-as-directory (expand-file-name ".")))
+       (pwd1 (file-name-as-directory (abbreviate-file-name
+                                      (expand-file-name ".")))))
+    (cond ((equal arg '(16))
+          (concat "file:"
+                  (abbreviate-file-name (expand-file-name file))))
+         ((string-match
+           (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
+          (concat "file:" (match-string 1 file)))
+         ((string-match
+           (concat "^" (regexp-quote pwd) "\\(.+\\)")
+           (expand-file-name file))
+          (concat "file:"
+                  (match-string 1 (expand-file-name file))))
+         (t (concat "file:" file)))))
 
 (defun org-completing-read (&rest args)
   "Completing-read with SPACE being a normal character."
@@ -10186,58 +10562,9 @@ See `read-file-name' for a description of parameters."
         (copy-keymap minibuffer-local-completion-map)))
     (org-defkey minibuffer-local-completion-map " " 'self-insert-command)
     (org-defkey minibuffer-local-completion-map "?" 'self-insert-command)
-    (org-defkey minibuffer-local-completion-map (kbd "C-c !") 
'org-time-stamp-inactive)
-    (apply 'org-icompleting-read args)))
-
-(defun org-completing-read-no-i (&rest args)
-  (let (org-completion-use-ido org-completion-use-iswitchb)
-    (apply 'org-completing-read args)))
-
-(defun org-iswitchb-completing-read (prompt choices &rest args)
-  "Use iswitch as a completing-read replacement to choose from choices.
-PROMPT is a string to prompt with.  CHOICES is a list of strings to choose
-from."
-  (let* ((iswitchb-use-virtual-buffers nil)
-        (iswitchb-make-buflist-hook
-         (lambda ()
-           (setq iswitchb-temp-buflist choices))))
-    (iswitchb-read-buffer prompt)))
-
-(defun org-icompleting-read (&rest args)
-  "Completing-read using `ido-mode' or `iswitchb' speedups if available."
-  (org-without-partial-completion
-   (if (and org-completion-use-ido
-           (fboundp 'ido-completing-read)
-           (boundp 'ido-mode) ido-mode
-           (listp (second args)))
-       (let ((ido-enter-matching-directory nil))
-        (apply 'ido-completing-read (concat (car args))
-               (if (consp (car (nth 1 args)))
-                   (mapcar 'car (nth 1 args))
-                 (nth 1 args))
-               (cddr args)))
-     (if (and org-completion-use-iswitchb
-             (boundp 'iswitchb-mode) iswitchb-mode
-             (listp (second args)))
-        (apply 'org-iswitchb-completing-read (concat (car args))
-               (if (consp (car (nth 1 args)))
-                   (mapcar 'car (nth 1 args))
-                 (nth 1 args))
-               (cddr args))
-       (apply 'completing-read args)))))
-
-(defun org-extract-attributes (s)
-  "Extract the attributes cookie from a string and set as text property."
-  (let (a attr (start 0) key value)
-    (save-match-data
-      (when (string-match "{{\\([^}]+\\)}}$" s)
-       (setq a (match-string 1 s) s (substring s 0 (match-beginning 0)))
-       (while (string-match "\\([a-zA-Z]+\\)=\"\\([^\"]*\\)\"" a start)
-         (setq key (match-string 1 a) value (match-string 2 a)
-               start (match-end 0)
-               attr (plist-put attr (intern key) value))))
-      (org-add-props s nil 'org-attr attr))
-    s))
+    (org-defkey minibuffer-local-completion-map (kbd "C-c !")
+               'org-time-stamp-inactive)
+    (apply #'completing-read args)))
 
 ;;; Opening/following a link
 
@@ -10257,8 +10584,8 @@ handle this as a special case.
 
 When the function does handle the link, it must return a non-nil value.
 If it decides that it is not responsible for this link, it must return
-nil to indicate that that Org-mode can continue with other options
-like exact and fuzzy text search.")
+nil to indicate that that Org can continue with other options like
+exact and fuzzy text search.")
 
 (defun org-next-link (&optional search-backward)
   "Move forward to the next link.
@@ -10270,7 +10597,7 @@ If the link is in hidden text, expose it."
   (setq org-link-search-failed nil)
   (let* ((pos (point))
         (ct (org-context))
-        (a (assoc :link ct))
+        (a (assq :link ct))
         (srch-fun (if search-backward 're-search-backward 're-search-forward)))
     (cond (a (goto-char (nth (if search-backward 1 2) a)))
          ((looking-at org-any-link-re)
@@ -10279,7 +10606,7 @@ If the link is in hidden text, expose it."
     (if (funcall srch-fun org-any-link-re nil t)
        (progn
          (goto-char (match-beginning 0))
-         (if (outline-invisible-p) (org-show-context)))
+         (when (org-invisible-p) (org-show-context)))
       (goto-char pos)
       (setq org-link-search-failed t)
       (message "No further link found"))))
@@ -10292,14 +10619,9 @@ If the link is in hidden text, expose it."
 
 (defun org-translate-link (s)
   "Translate a link string if a translation function has been defined."
-  (if (and org-link-translation-function
-          (fboundp org-link-translation-function)
-          (string-match "\\([a-zA-Z0-9]+\\):\\(.*\\)" s))
-      (progn
-       (setq s (funcall org-link-translation-function
-                        (match-string 1 s) (match-string 2 s)))
-       (concat (car s) ":" (cdr s)))
-    s))
+  (with-temp-buffer
+    (insert (org-trim s))
+    (org-trim (org-element-interpret-data (org-element-context)))))
 
 (defun org-translate-link-from-planner (type path)
   "Translate a link from Emacs Planner syntax so that Org can follow it.
@@ -10319,7 +10641,7 @@ This is still an experimental function, your mileage 
may vary."
     ;; A typical message link.  Planner has the id after the final slash,
     ;; we separate it with a hash mark
     (setq path (concat (match-string 1 path) "#"
-                      (org-remove-angle-brackets (match-string 2 path))))))
+                      (org-unbracket-string "<" ">" (match-string 2 path))))))
   (cons type path))
 
 (defun org-find-file-at-mouse (ev)
@@ -10333,28 +10655,32 @@ This is still an experimental function, your mileage 
may vary."
 See the docstring of `org-open-file' for details."
   (interactive "e")
   (mouse-set-point ev)
-  (if (eq major-mode 'org-agenda-mode)
-      (org-agenda-copy-local-variable 'org-link-abbrev-alist-local))
+  (when (eq major-mode 'org-agenda-mode)
+    (org-agenda-copy-local-variable 'org-link-abbrev-alist-local))
   (org-open-at-point))
 
 (defvar org-window-config-before-follow-link nil
   "The window configuration before following a link.
 This is saved in case the need arises to restore it.")
 
-(defvar org-open-link-marker (make-marker)
-  "Marker pointing to the location where `org-open-at-point' was called.")
-
 ;;;###autoload
 (defun org-open-at-point-global ()
-  "Follow a link like Org-mode does.
-This command can be called in any mode to follow a link that has
-Org-mode syntax."
+  "Follow a link or time-stamp like Org mode does.
+This command can be called in any mode to follow an external link
+or a time-stamp that has Org mode syntax.  Its behavior is
+undefined when called on internal links (e.g., fuzzy links).
+Raise an error when there is nothing to follow.  "
   (interactive)
-  (org-run-like-in-org-mode 'org-open-at-point))
+  (cond ((org-in-regexp org-any-link-re)
+        (org-open-link-from-string (match-string-no-properties 0)))
+       ((or (org-in-regexp org-ts-regexp-both nil t)
+            (org-in-regexp org-tsr-regexp-both nil t))
+        (org-follow-timestamp-link))
+       (t (user-error "No link found"))))
 
 ;;;###autoload
 (defun org-open-link-from-string (s &optional arg reference-buffer)
-  "Open a link in the string S, as if it was in Org-mode."
+  "Open a link in the string S, as if it was in Org mode."
   (interactive "sLink: \nP")
   (let ((reference-buffer (or reference-buffer (current-buffer))))
     (with-temp-buffer
@@ -10375,267 +10701,240 @@ Functions in this hook must return t if they 
identify and follow
 a link at point.  If they don't find anything interesting at point,
 they must return nil.")
 
-(defvar org-link-search-inhibit-query nil) ;; dynamically scoped
-(defvar clean-buffer-list-kill-buffer-names) ; Defined in midnight.el
+(defvar org-link-search-inhibit-query nil)
+(defvar clean-buffer-list-kill-buffer-names) ;Defined in midnight.el
+(defun org--open-doi-link (path)
+  "Open a \"doi\" type link.
+PATH is a the path to search for, as a string."
+  (browse-url (url-encode-url (concat org-doi-server-url path))))
+
+(defun org--open-elisp-link (path)
+  "Open a \"elisp\" type link.
+PATH is the sexp to evaluate, as a string."
+  (let ((cmd path))
+    (if (or (and (org-string-nw-p
+                 org-confirm-elisp-link-not-regexp)
+                (string-match-p org-confirm-elisp-link-not-regexp cmd))
+           (not org-confirm-elisp-link-function)
+           (funcall org-confirm-elisp-link-function
+                    (format "Execute \"%s\" as elisp? "
+                            (org-add-props cmd nil 'face 'org-warning))))
+       (message "%s => %s" cmd
+                (if (eq (string-to-char cmd) ?\()
+                    (eval (read cmd))
+                  (call-interactively (read cmd))))
+      (user-error "Abort"))))
+
+(defun org--open-help-link (path)
+  "Open a \"help\" type link.
+PATH is a symbol name, as a string."
+  (pcase (intern path)
+    ((and (pred fboundp) variable) (describe-function variable))
+    ((and (pred boundp) function) (describe-variable function))
+    (name (user-error "Unknown function or variable: %s" name))))
+
+(defun org--open-shell-link (path)
+  "Open a \"shell\" type link.
+PATH is the command to execute, as a string."
+  (let ((buf (generate-new-buffer "*Org Shell Output*"))
+       (cmd path))
+    (if (or (and (org-string-nw-p
+                 org-confirm-shell-link-not-regexp)
+                (string-match
+                 org-confirm-shell-link-not-regexp cmd))
+           (not org-confirm-shell-link-function)
+           (funcall org-confirm-shell-link-function
+                    (format "Execute \"%s\" in shell? "
+                            (org-add-props cmd nil
+                              'face 'org-warning))))
+       (progn
+         (message "Executing %s" cmd)
+         (shell-command cmd buf)
+         (when (featurep 'midnight)
+           (setq clean-buffer-list-kill-buffer-names
+                 (cons (buffer-name buf)
+                       clean-buffer-list-kill-buffer-names))))
+      (user-error "Abort"))))
+
 (defun org-open-at-point (&optional arg reference-buffer)
-  "Open link at or after point.
-If there is no link at point, this function will search forward up to
-the end of the current line.
-Normally, files will be opened by an appropriate application.  If the
-optional prefix argument ARG is non-nil, Emacs will visit the file.
-With a double prefix argument, try to open outside of Emacs, in the
-application the system uses for this file type."
-  (interactive "P")
-  ;; if in a code block, then open the block's results
-  (unless (call-interactively #'org-babel-open-src-block-result)
-    (org-load-modules-maybe)
-    (move-marker org-open-link-marker (point))
-    (setq org-window-config-before-follow-link (current-window-configuration))
-    (org-remove-occur-highlights nil nil t)
-    (cond
-     ((and (org-at-heading-p)
-          (not (org-at-timestamp-p t))
-          (not (org-in-regexp
-                (concat org-plain-link-re "\\|"
-                        org-bracket-link-regexp "\\|"
-                        org-angle-link-re "\\|"
-                        "[ \t]:[^ \t\n]+:[ \t]*$")))
-          (not (get-text-property (point) 'org-linked-text)))
-      (or (let* ((lkall (org-offer-links-in-entry (current-buffer) (point) 
arg))
-                (lk0 (car lkall))
-                (lk (if (stringp lk0) (list lk0) lk0))
-                (lkend (cdr lkall)))
-           (mapcar (lambda(l)
-                     (search-forward l nil lkend)
-                     (goto-char (match-beginning 0))
-                     (org-open-at-point))
-                   lk))
-         (progn (require 'org-attach) (org-attach-reveal 'if-exists))))
-     ((run-hook-with-args-until-success 'org-open-at-point-functions))
-     ((and (org-at-timestamp-p t)
-          (not (org-in-regexp org-bracket-link-regexp)))
-      (org-follow-timestamp-link))
-     ((and (or (org-footnote-at-reference-p) (org-footnote-at-definition-p))
-          (not (org-in-regexp org-any-link-re)))
-      (org-footnote-action))
-     (t
-      (let (type path link line search (pos (point)))
-       (catch 'match
-         (save-excursion
-           (or (org-in-regexp org-plain-link-re)
-               (skip-chars-forward "^]\n\r"))
-           (when (org-in-regexp org-bracket-link-regexp 1)
-             (setq link (org-extract-attributes
-                         (org-link-unescape (org-match-string-no-properties 
1))))
-             (while (string-match " *\n *" link)
-               (setq link (replace-match " " t t link)))
-             (setq link (org-link-expand-abbrev link))
-             (cond
-              ((or (file-name-absolute-p link)
-                   (string-match "^\\.\\.?/" link))
-               (setq type "file" path link))
-              ((string-match org-link-re-with-space3 link)
-               (setq type (match-string 1 link) path (match-string 2 link)))
-              ((string-match "^help:+\\(.+\\)" link)
-               (setq type "help" path (match-string 1 link)))
-              (t (setq type "thisfile" path link)))
-             (throw 'match t)))
-
-         (when (get-text-property (point) 'org-linked-text)
-           (setq type "thisfile"
-                 pos (if (get-text-property (1+ (point)) 'org-linked-text)
-                         (1+ (point)) (point))
-                 path (buffer-substring
-                       (or (previous-single-property-change pos 
'org-linked-text)
-                           (point-min))
-                       (or (next-single-property-change pos 'org-linked-text)
-                           (point-max)))
-                 ;; Ensure we will search for a <<<radio>>> link, not
-                 ;; a simple reference like <<ref>>
-                 path (concat "<" path))
-           (throw 'match t))
+  "Open link, timestamp, footnote or tags at point.
 
-         (save-excursion
-           (when (or (org-in-regexp org-angle-link-re)
-                     (let ((match (org-in-regexp org-plain-link-re)))
-                       ;; Check a plain link is not within a bracket link
-                       (and match
-                            (save-excursion
-                              (save-match-data
-                                (progn
-                                  (goto-char (car match))
-                                  (not (org-in-regexp 
org-bracket-link-regexp)))))))
-                     (let ((line_ending (save-excursion (end-of-line) 
(point))))
-                       ;; We are in a line before a plain or bracket link
-                       (or (re-search-forward org-plain-link-re line_ending t)
-                           (re-search-forward org-bracket-link-regexp 
line_ending t))))
-             (setq type (match-string 1)
-                   path (org-link-unescape (match-string 2)))
-               (throw 'match t)))
-         (save-excursion
-           (when (org-in-regexp (org-re "\\(:[[:alnum:address@hidden:]+\\):[ 
\t]*$"))
-             (setq type "tags"
-                   path (match-string 1))
-             (while (string-match ":" path)
-               (setq path (replace-match "+" t t path)))
-             (throw 'match t)))
-         (when (org-in-regexp "<\\([^><\n]+\\)>")
-           (setq type "tree-match"
-                 path (match-string 1))
-           (throw 'match t)))
-       (unless path
-         (user-error "No link found"))
+When point is on a link, follow it.  Normally, files will be
+opened by an appropriate application.  If the optional prefix
+argument ARG is non-nil, Emacs will visit the file.  With
+a double prefix argument, try to open outside of Emacs, in the
+application the system uses for this file type.
 
-       ;; switch back to reference buffer
-       ;; needed when if called in a temporary buffer through
-       ;; org-open-link-from-string
-       (with-current-buffer (or reference-buffer (current-buffer))
+When point is on a timestamp, open the agenda at the day
+specified.
 
-         ;; Remove any trailing spaces in path
-         (if (string-match " +\\'" path)
-             (setq path (replace-match "" t t path)))
-         (if (and org-link-translation-function
-                  (fboundp org-link-translation-function))
-             ;; Check if we need to translate the link
-             (let ((tmp (funcall org-link-translation-function type path)))
-               (setq type (car tmp) path (cdr tmp))))
+When point is a footnote definition, move to the first reference
+found.  If it is on a reference, move to the associated
+definition.
 
-         (cond
+When point is on a headline, display a list of every link in the
+entry, so it is possible to pick one, or all, of them.  If point
+is on a tag, call `org-tags-view' instead.
 
-          ((assoc type org-link-protocols)
-           (funcall (nth 1 (assoc type org-link-protocols)) path))
-
-          ((equal type "help")
-           (let ((f-or-v (intern path)))
-             (cond ((fboundp f-or-v)
-                    (describe-function f-or-v))
-                   ((boundp f-or-v)
-                    (describe-variable f-or-v))
-                   (t (error "Not a known function or variable")))))
-
-          ((equal type "mailto")
-           (let ((cmd (car org-link-mailto-program))
-                 (args (cdr org-link-mailto-program)) args1
-                 (address path) (subject "") a)
-             (if (string-match "\\(.*\\)::\\(.*\\)" path)
-                 (setq address (match-string 1 path)
-                       subject (org-link-escape (match-string 2 path))))
-             (while args
-               (cond
-                ((not (stringp (car args))) (push (pop args) args1))
-                (t (setq a (pop args))
-                   (if (string-match "%a" a)
-                       (setq a (replace-match address t t a)))
-                   (if (string-match "%s" a)
-                       (setq a (replace-match subject t t a)))
-                   (push a args1))))
-             (apply cmd (nreverse args1))))
-
-          ((member type '("http" "https" "ftp" "news"))
-           (browse-url
-            (concat type ":"
-                    (if (org-string-match-p
-                         (concat "[[:nonascii:]"
-                                 org-link-escape-chars-browser "]")
-                         path)
-                        (org-link-escape path org-link-escape-chars-browser)
-                      path))))
-
-          ((string= type "doi")
-           (browse-url
-            (concat org-doi-server-url
-                    (if (org-string-match-p
-                         (concat "[[:nonascii:]"
-                                 org-link-escape-chars-browser "]")
-                         path)
-                        (org-link-escape path org-link-escape-chars-browser)
-                      path))))
-
-          ((member type '("message"))
-           (browse-url (concat type ":" path)))
-
-          ((string= type "tags")
-           (org-tags-view arg path))
-
-          ((string= type "tree-match")
-           (org-occur (concat "\\[" (regexp-quote path) "\\]")))
-
-          ((string= type "file")
-           (if (string-match "::\\([0-9]+\\)\\'" path)
-               (setq line (string-to-number (match-string 1 path))
-                     path (substring path 0 (match-beginning 0)))
-             (if (string-match "::\\(.+\\)\\'" path)
-                 (setq search (match-string 1 path)
-                       path (substring path 0 (match-beginning 0)))))
-           (if (string-match "[*?{]" (file-name-nondirectory path))
-               (dired path)
-             (org-open-file path arg line search)))
-
-          ((string= type "shell")
-           (let ((buf (generate-new-buffer "*Org Shell Output"))
-                 (cmd path))
-             (if (or (and (not (string= org-confirm-shell-link-not-regexp ""))
-                          (string-match org-confirm-shell-link-not-regexp cmd))
-                     (not org-confirm-shell-link-function)
-                     (funcall org-confirm-shell-link-function
-                              (format "Execute \"%s\" in shell? "
-                                      (org-add-props cmd nil
-                                        'face 'org-warning))))
-                 (progn
-                   (message "Executing %s" cmd)
-                   (shell-command cmd buf)
-                   (if (featurep 'midnight)
-                       (setq clean-buffer-list-kill-buffer-names
-                             (cons buf clean-buffer-list-kill-buffer-names))))
-               (error "Abort"))))
-
-          ((string= type "elisp")
-           (let ((cmd path))
-             (if (or (and (not (string= org-confirm-elisp-link-not-regexp ""))
-                          (string-match org-confirm-elisp-link-not-regexp cmd))
-                     (not org-confirm-elisp-link-function)
-                     (funcall org-confirm-elisp-link-function
-                              (format "Execute \"%s\" as elisp? "
-                                      (org-add-props cmd nil
-                                        'face 'org-warning))))
-                 (message "%s => %s" cmd
-                          (if (equal (string-to-char cmd) ?\()
-                              (eval (read cmd))
-                            (call-interactively (read cmd))))
-               (error "Abort"))))
-
-          ((and (string= type "thisfile")
-                (or (run-hook-with-args-until-success
-                     'org-open-link-functions path)
-                    (and link
-                         (string-match "^id:" link)
-                         (or (featurep 'org-id) (require 'org-id))
-                         (progn
-                           (funcall (nth 1 (assoc "id" org-link-protocols))
-                                    (substring path 3))
-                           t)))))
-
-          ((string= type "thisfile")
-           (if arg
-               (switch-to-buffer-other-window
-                (org-get-buffer-for-internal-link (current-buffer)))
-             (org-mark-ring-push))
-           (let ((cmd `(org-link-search
-                        ,path
-                        ,(cond ((equal arg '(4)) ''occur)
-                               ((equal arg '(16)) ''org-occur))
-                        ,pos)))
-             (condition-case nil (let ((org-link-search-inhibit-query t))
-                                   (eval cmd))
-               (error (progn (widen) (eval cmd))))))
-
-          (t (browse-url-at-point)))))))
-    (move-marker org-open-link-marker nil)
-    (run-hook-with-args 'org-follow-link-hook)))
+When optional argument REFERENCE-BUFFER is non-nil, it should
+specify a buffer from where the link search should happen.  This
+is used internally by `org-open-link-from-string'.
 
-(defsubst org-uniquify (list)
-  "Non-destructively remove duplicate elements from LIST."
-  (let ((res (copy-sequence list))) (delete-dups res)))
+On top of syntactically correct links, this function will open
+the link at point in comments or comment blocks and the first
+link in a property drawer line."
+  (interactive "P")
+  ;; On a code block, open block's results.
+  (unless (call-interactively 'org-babel-open-src-block-result)
+    (org-load-modules-maybe)
+    (setq org-window-config-before-follow-link (current-window-configuration))
+    (org-remove-occur-highlights nil nil t)
+    (unless (run-hook-with-args-until-success 'org-open-at-point-functions)
+      (let* ((context
+             ;; Only consider supported types, even if they are not
+             ;; the closest one.
+             (org-element-lineage
+              (org-element-context)
+              '(clock comment comment-block footnote-definition
+                      footnote-reference headline inlinetask keyword link
+                      node-property timestamp)
+              t))
+            (type (org-element-type context))
+            (value (org-element-property :value context)))
+       (cond
+        ((not context) (user-error "No link found"))
+        ;; Exception: open timestamps and links in properties
+        ;; drawers, keywords and comments.
+        ((memq type '(comment comment-block keyword node-property))
+         (call-interactively #'org-open-at-point-global))
+        ;; On a headline or an inlinetask, but not on a timestamp,
+        ;; a link, a footnote reference or on tags.
+        ((and (memq type '(headline inlinetask))
+              ;; Not on tags.
+              (let ((case-fold-search nil))
+                (save-excursion
+                  (beginning-of-line)
+                  (looking-at org-complex-heading-regexp))
+                (or (not (match-beginning 5))
+                    (< (point) (match-beginning 5)))))
+         (let* ((data (org-offer-links-in-entry (current-buffer) (point) arg))
+                (links (car data))
+                (links-end (cdr data)))
+           (if links
+               (dolist (link (if (stringp links) (list links) links))
+                 (search-forward link nil links-end)
+                 (goto-char (match-beginning 0))
+                 (org-open-at-point))
+             (require 'org-attach)
+             (org-attach-reveal 'if-exists))))
+        ;; On a clock line, make sure point is on the timestamp
+        ;; before opening it.
+        ((and (eq type 'clock)
+              value
+              (>= (point) (org-element-property :begin value))
+              (<= (point) (org-element-property :end value)))
+         (org-follow-timestamp-link))
+        ;; Do nothing on white spaces after an object.
+        ((>= (point)
+             (save-excursion
+               (goto-char (org-element-property :end context))
+               (skip-chars-backward " \t")
+               (point)))
+         (user-error "No link found"))
+        ((eq type 'timestamp) (org-follow-timestamp-link))
+        ;; On tags within a headline or an inlinetask.
+        ((and (memq type '(headline inlinetask))
+              (let ((case-fold-search nil))
+                (save-excursion (beginning-of-line)
+                                (looking-at org-complex-heading-regexp))
+                (and (match-beginning 5)
+                     (>= (point) (match-beginning 5)))))
+         (org-tags-view arg (substring (match-string 5) 0 -1)))
+        ((eq type 'link)
+         ;; When link is located within the description of another
+         ;; link (e.g., an inline image), always open the parent
+         ;; link.
+         (let* ((link (let ((up (org-element-property :parent context)))
+                        (if (eq (org-element-type up) 'link) up context)))
+                (type (org-element-property :type link))
+                (path (org-link-unescape (org-element-property :path link))))
+           ;; Switch back to REFERENCE-BUFFER needed when called in
+           ;; a temporary buffer through `org-open-link-from-string'.
+           (with-current-buffer (or reference-buffer (current-buffer))
+             (cond
+              ((equal type "file")
+               (if (string-match "[*?{]" (file-name-nondirectory path))
+                   (dired path)
+                 ;; Look into `org-link-parameters' in order to find
+                 ;; a DEDICATED-FUNCTION to open file.  The function
+                 ;; will be applied on raw link instead of parsed
+                 ;; link due to the limitation in `org-add-link-type'
+                 ;; ("open" function called with a single argument).
+                 ;; If no such function is found, fallback to
+                 ;; `org-open-file'.
+                 (let* ((option (org-element-property :search-option link))
+                        (app (org-element-property :application link))
+                        (dedicated-function
+                         (org-link-get-parameter
+                          (if app (concat type "+" app) type)
+                          :follow)))
+                   (if dedicated-function
+                       (funcall dedicated-function
+                                (concat path
+                                        (and option (concat "::" option))))
+                     (apply #'org-open-file
+                            path
+                            (cond (arg)
+                                  ((equal app "emacs") 'emacs)
+                                  ((equal app "sys") 'system))
+                            (cond ((not option) nil)
+                                  ((string-match-p "\\`[0-9]+\\'" option)
+                                   (list (string-to-number option)))
+                                  (t (list nil
+                                           (org-link-unescape option)))))))))
+              ((functionp (org-link-get-parameter type :follow))
+               (funcall (org-link-get-parameter type :follow) path))
+              ((member type '("coderef" "custom-id" "fuzzy" "radio"))
+               (unless (run-hook-with-args-until-success
+                        'org-open-link-functions path)
+                 (if (not arg) (org-mark-ring-push)
+                   (switch-to-buffer-other-window
+                    (org-get-buffer-for-internal-link (current-buffer))))
+                 (let ((destination
+                        (org-with-wide-buffer
+                         (if (equal type "radio")
+                             (org-search-radio-target
+                              (org-element-property :path link))
+                           (org-link-search
+                            (if (member type '("custom-id" "coderef"))
+                                (org-element-property :raw-link link)
+                              path)
+                            ;; Prevent fuzzy links from matching
+                            ;; themselves.
+                            (and (equal type "fuzzy")
+                                 (+ 2 (org-element-property :begin link)))))
+                         (point))))
+                   (unless (and (<= (point-min) destination)
+                                (>= (point-max) destination))
+                     (widen))
+                   (goto-char destination))))
+              (t (browse-url-at-point))))))
+        ;; On a footnote reference or at a footnote definition's label.
+        ((or (eq type 'footnote-reference)
+             (and (eq type 'footnote-definition)
+                  (save-excursion
+                    ;; Do not validate action when point is on the
+                    ;; spaces right after the footnote label, in
+                    ;; order to be on par with behaviour on links.
+                    (skip-chars-forward " \t")
+                    (let ((begin
+                           (org-element-property :contents-begin context)))
+                      (if begin (< (point) begin)
+                        (= (org-element-property :post-affiliated context)
+                           (line-beginning-position)))))))
+         (org-footnote-action))
+        (t (user-error "No link found")))))
+    (run-hook-with-args 'org-follow-link-hook)))
 
 (defun org-offer-links-in-entry (buffer marker &optional nth zero)
   "Offer links in the current entry and return the selected link.
@@ -10644,65 +10943,57 @@ If NTH is an integer, return the NTH link found.
 If ZERO is a string, check also this string for a link, and if
 there is one, return it."
   (with-current-buffer buffer
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char marker)
-       (let ((re (concat "\\(" org-bracket-link-regexp "\\)\\|"
-                         "\\(" org-angle-link-re "\\)\\|"
-                         "\\(" org-plain-link-re "\\)"))
-             (cnt ?0)
-             (in-emacs (if (integerp nth) nil nth))
-             have-zero end links link c)
-         (when (and (stringp zero) (string-match org-bracket-link-regexp zero))
-           (push (match-string 0 zero) links)
-           (setq cnt (1- cnt) have-zero t))
-         (save-excursion
-           (org-back-to-heading t)
-           (setq end (save-excursion (outline-next-heading) (point)))
-           (while (re-search-forward re end t)
-             (push (match-string 0) links))
-           (setq links (org-uniquify (reverse links))))
-         (cond
-          ((null links)
-           (message "No links"))
-          ((equal (length links) 1)
-           (setq link (car links)))
-          ((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth)))
-           (setq link (nth (if have-zero nth (1- nth)) links)))
-          (t ; we have to select a link
-           (save-excursion
-             (save-window-excursion
-               (delete-other-windows)
-               (with-output-to-temp-buffer "*Select Link*"
-                 (mapc (lambda (l)
-                         (if (not (string-match org-bracket-link-regexp l))
-                             (princ (format "[%c]  %s\n" (incf cnt)
-                                            (org-remove-angle-brackets l)))
-                           (if (match-end 3)
-                               (princ (format "[%c]  %s (%s)\n" (incf cnt)
-                                              (match-string 3 l) (match-string 
1 l)))
-                             (princ (format "[%c]  %s\n" (incf cnt)
-                                            (match-string 1 l))))))
-                       links))
-               (org-fit-window-to-buffer (get-buffer-window "*Select Link*"))
-               (message "Select link to open, RET to open all:")
-               (setq c (read-char-exclusive))
-               (and (get-buffer "*Select Link*") (kill-buffer "*Select 
Link*"))))
-           (when (equal c ?q) (error "Abort"))
-           (if (equal c ?\C-m)
-               (setq link links)
-             (setq nth (- c ?0))
-             (if have-zero (setq nth (1+ nth)))
-             (unless (and (integerp nth) (>= (length links) nth))
-               (user-error "Invalid link selection"))
-             (setq link (nth (1- nth) links)))))
-         (cons link end))))))
-
-;; Add special file links that specify the way of opening
-
-(org-add-link-type "file+sys" 'org-open-file-with-system)
-(org-add-link-type "file+emacs" 'org-open-file-with-emacs)
+    (org-with-wide-buffer
+     (goto-char marker)
+     (let ((cnt ?0)
+          have-zero end links link c)
+       (when (and (stringp zero) (string-match org-bracket-link-regexp zero))
+        (push (match-string 0 zero) links)
+        (setq cnt (1- cnt) have-zero t))
+       (save-excursion
+        (org-back-to-heading t)
+        (setq end (save-excursion (outline-next-heading) (point)))
+        (while (re-search-forward org-any-link-re end t)
+          (push (match-string 0) links))
+        (setq links (org-uniquify (reverse links))))
+       (cond
+       ((null links)
+        (message "No links"))
+       ((equal (length links) 1)
+        (setq link (car links)))
+       ((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth)))
+        (setq link (nth (if have-zero nth (1- nth)) links)))
+       (t                              ; we have to select a link
+        (save-excursion
+          (save-window-excursion
+            (delete-other-windows)
+            (with-output-to-temp-buffer "*Select Link*"
+              (dolist (l links)
+                (cond
+                 ((not (string-match org-bracket-link-regexp l))
+                  (princ (format "[%c]  %s\n" (cl-incf cnt)
+                                 (org-unbracket-string "<" ">" l))))
+                 ((match-end 3)
+                  (princ (format "[%c]  %s (%s)\n" (cl-incf cnt)
+                                 (match-string 3 l) (match-string 1 l))))
+                 (t (princ (format "[%c]  %s\n" (cl-incf cnt)
+                                   (match-string 1 l)))))))
+            (org-fit-window-to-buffer (get-buffer-window "*Select Link*"))
+            (message "Select link to open, RET to open all:")
+            (setq c (read-char-exclusive))
+            (and (get-buffer "*Select Link*") (kill-buffer "*Select Link*"))))
+        (when (equal c ?q) (user-error "Abort"))
+        (if (equal c ?\C-m)
+            (setq link links)
+          (setq nth (- c ?0))
+          (when have-zero (setq nth (1+ nth)))
+          (unless (and (integerp nth) (>= (length links) nth))
+            (user-error "Invalid link selection"))
+          (setq link (nth (1- nth) links)))))
+       (cons link end)))))
+
+;; TODO: These functions are deprecated since `org-open-at-point'
+;; hard-codes behaviour for "file+emacs" and "file+sys" types.
 (defun org-open-file-with-system (path)
   "Open file at PATH using the system way of opening it."
   (org-open-file path 'system))
@@ -10732,8 +11023,8 @@ which see.
 
 A function in this hook may also use `setq' to set the variable
 `description' to provide a suggestion for the descriptive text to
-be used for this link when it gets inserted into an Org-mode
-buffer with \\[org-insert-link].")
+be used for this link when it gets inserted into an Org buffer
+with \\[org-insert-link].")
 
 (defvar org-execute-file-search-functions nil
   "List of functions to execute a file search triggered by a link.
@@ -10757,179 +11048,201 @@ the window configuration before `org-open-at-point' 
was called using:
 
     (set-window-configuration org-window-config-before-follow-link)")
 
-(defun org-link-search (s &optional type avoid-pos stealth)
-  "Search for a link search option.
-If S is surrounded by forward slashes, it is interpreted as a
-regular expression.  In org-mode files, this will create an `org-occur'
-sparse tree.  In ordinary files, `occur' will be used to list matches.
-If the current buffer is in `dired-mode', grep will be used to search
-in all files.  If AVOID-POS is given, ignore matches near that position.
+(defun org-search-radio-target (target)
+  "Search a radio target matching TARGET in current buffer.
+White spaces are not significant."
+  (let ((re (format "<<<%s>>>"
+                   (mapconcat #'regexp-quote
+                              (org-split-string target "[ \t\n]+")
+                              "[ \t]+\\(?:\n[ \t]*\\)?")))
+       (origin (point)))
+    (goto-char (point-min))
+    (catch :radio-match
+      (while (re-search-forward re nil t)
+       (backward-char)
+       (let ((object (org-element-context)))
+         (when (eq (org-element-type object) 'radio-target)
+           (goto-char (org-element-property :begin object))
+           (org-show-context 'link-search)
+           (throw :radio-match nil))))
+      (goto-char origin)
+      (user-error "No match for radio target: %s" target))))
+
+(defun org-link-search (s &optional avoid-pos stealth)
+  "Search for a search string S.
+
+If S starts with \"#\", it triggers a custom ID search.
+
+If S is enclosed within parenthesis, it initiates a coderef
+search.
+
+If S is surrounded by forward slashes, it is interpreted as
+a regular expression.  In Org mode files, this will create an
+`org-occur' sparse tree.  In ordinary files, `occur' will be used
+to list matches.  If the current buffer is in `dired-mode', grep
+will be used to search in all files.
+
+When AVOID-POS is given, ignore matches near that position.
 
 When optional argument STEALTH is non-nil, do not modify
-visibility around point, thus ignoring
-`org-show-hierarchy-above', `org-show-following-heading' and
-`org-show-siblings' variables."
-  (let ((case-fold-search t)
-       (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
-       (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
-                                           (append '(("") (" ") ("\t") ("\n"))
-                                                   org-emphasis-alist)
-                                           "\\|") "\\)"))
-       (pos (point))
-       (pre nil) (post nil)
-       words re0 re1 re2 re3 re4_ re4 re5 re2a re2a_ reall)
+visibility around point, thus ignoring `org-show-context-detail'
+variable.
+
+Search is case-insensitive and ignores white spaces.  Return type
+of matched result, which is either `dedicated' or `fuzzy'."
+  (unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s))
+  (let* ((case-fold-search t)
+        (origin (point))
+        (normalized (replace-regexp-in-string "\n[ \t]*" " " s))
+        (starred (eq (string-to-char normalized) ?*))
+        (words (split-string (if starred (substring s 1) s)))
+        (s-multi-re (mapconcat #'regexp-quote words "\\(?:[ \t\n]+\\)"))
+        (s-single-re (mapconcat #'regexp-quote words "[ \t]+"))
+        type)
     (cond
-     ;; First check if there are any special search functions
+     ;; Check if there are any special search functions.
      ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
-     ;; Now try the builtin stuff
-     ((and (equal (string-to-char s0) ?#)
-          (> (length s0) 1)
-          (save-excursion
-            (goto-char (point-min))
-            (and
-             (re-search-forward
-              (concat "^[ \t]*:CUSTOM_ID:[ \t]+"
-                      (regexp-quote (substring s0 1)) "[ \t]*$") nil t)
-             (setq type 'dedicated
-                   pos (match-beginning 0))))
-          ;; There is an exact target for this
-          (goto-char pos)
-          (org-back-to-heading t)))
-     ((save-excursion
+     ((eq (string-to-char s) ?#)
+      ;; Look for a custom ID S if S starts with "#".
+      (let* ((id (substring normalized 1))
+            (match (org-find-property "CUSTOM_ID" id)))
+       (if match (progn (goto-char match) (setf type 'dedicated))
+         (error "No match for custom ID: %s" id))))
+     ((string-match "\\`(\\(.*\\))\\'" normalized)
+      ;; Look for coderef targets if S is enclosed within parenthesis.
+      (let ((coderef (match-string-no-properties 1 normalized))
+           (re (substring s-single-re 1 -1)))
        (goto-char (point-min))
-       (and
-        (re-search-forward
-         (concat "<<" (regexp-quote s0) ">>") nil t)
-        (setq type 'dedicated
-              pos (match-beginning 0))))
-      ;; There is an exact target for this
-      (goto-char pos))
-     ((save-excursion
-       (goto-char (point-min))
-       (and
-        (re-search-forward
-         (format "^[ \t]*#\\+NAME: %s" (regexp-quote s0)) nil t)
-        (setq type 'dedicated pos (match-beginning 0))))
-      ;; Found an element with a matching #+name affiliated keyword.
-      (goto-char pos))
-     ((and (string-match "^(\\(.*\\))$" s0)
-          (save-excursion
+       (catch :coderef-match
+         (while (re-search-forward re nil t)
+           (let ((element (org-element-at-point)))
+             (when (and (memq (org-element-type element)
+                              '(example-block src-block))
+                        ;; Build proper regexp according to current
+                        ;; block's label format.
+                        (let ((label-fmt
+                               (regexp-quote
+                                (or (org-element-property :label-fmt element)
+                                    org-coderef-label-format))))
+                          (save-excursion
+                            (beginning-of-line)
+                            (looking-at (format ".*?\\(%s\\)[ \t]*$"
+                                                (format label-fmt coderef))))))
+               (setq type 'dedicated)
+               (goto-char (match-beginning 1))
+               (throw :coderef-match nil))))
+         (goto-char origin)
+         (error "No match for coderef: %s" coderef))))
+     ((string-match "\\`/\\(.*\\)/\\'" normalized)
+      ;; Look for a regular expression.
+      (funcall (if (derived-mode-p 'org-mode) #'org-occur #'org-do-occur)
+              (match-string 1 s)))
+     ;; From here, we handle fuzzy links.
+     ;;
+     ;; Look for targets, only if not in a headline search.
+     ((and (not starred)
+          (let ((target (format "<<%s>>" s-multi-re)))
+            (catch :target-match
+              (goto-char (point-min))
+              (while (re-search-forward target nil t)
+                (backward-char)
+                (let ((context (org-element-context)))
+                  (when (eq (org-element-type context) 'target)
+                    (setq type 'dedicated)
+                    (goto-char (org-element-property :begin context))
+                    (throw :target-match t))))
+              nil))))
+     ;; Look for elements named after S, only if not in a headline
+     ;; search.
+     ((and (not starred)
+          (let ((name (format "^[ \t]*#\\+NAME: +%s[ \t]*$" s-single-re)))
+            (catch :name-match
+              (goto-char (point-min))
+              (while (re-search-forward name nil t)
+                (let ((element (org-element-at-point)))
+                  (when (equal words
+                               (split-string
+                                (org-element-property :name element)))
+                    (setq type 'dedicated)
+                    (beginning-of-line)
+                    (throw :name-match t))))
+              nil))))
+     ;; Regular text search.  Prefer headlines in Org mode buffers.
+     ;; Ignore COMMENT keyword, TODO keywords, priority cookies,
+     ;; statistics cookies and tags.
+     ((and (derived-mode-p 'org-mode)
+          (let ((title-re
+                 (format "%s.*\\(?:%s[ \t]\\)?.*%s"
+                         org-outline-regexp-bol
+                         org-comment-string
+                         (mapconcat #'regexp-quote words ".+")))
+                (cookie-re "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]")
+                (comment-re (format "\\`%s[ \t]+" org-comment-string)))
             (goto-char (point-min))
-            (and
-             (re-search-forward
-              (concat "[^[]" (regexp-quote
-                              (format org-coderef-label-format
-                                      (match-string 1 s0))))
-              nil t)
-             (setq type 'dedicated
-                   pos (1+ (match-beginning 0))))))
-      ;; There is a coderef target for this
-      (goto-char pos))
-     ((string-match "^/\\(.*\\)/$" s)
-      ;; A regular expression
-      (cond
-       ((derived-mode-p 'org-mode)
-       (org-occur (match-string 1 s)))
-       (t (org-do-occur (match-string 1 s)))))
-     ((and (derived-mode-p 'org-mode) 
org-link-search-must-match-exact-headline)
-      (and (equal (string-to-char s) ?*) (setq s (substring s 1)))
-      (goto-char (point-min))
-      (cond
-       ((let (case-fold-search)
-         (re-search-forward (format org-complex-heading-regexp-format
-                                    (regexp-quote s))
-                            nil t))
-       ;; OK, found a match
-       (setq type 'dedicated)
-       (goto-char (match-beginning 0)))
-       ((and (not org-link-search-inhibit-query)
-            (eq org-link-search-must-match-exact-headline 'query-to-create)
-            (y-or-n-p "No match - create this as a new heading? "))
-       (goto-char (point-max))
-       (or (bolp) (newline))
-       (insert "* " s "\n")
-       (beginning-of-line 0))
-       (t
-       (goto-char pos)
-       (error "No match"))))
-     (t
-      ;; A normal search string
-      (when (equal (string-to-char s) ?*)
-       ;; Anchor on headlines, post may include tags.
-       (setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
-             post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:address@hidden:+]:[ 
\t]*\\)?$")
-             s (substring s 1)))
-      (remove-text-properties
-       0 (length s)
-       '(face nil mouse-face nil keymap nil fontified nil) s)
-      ;; Make a series of regular expressions to find a match
-      (setq words (org-split-string s "[ \n\r\t]+")
-
-           re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
-           re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
-                       "\\)" markers)
-           re2a_ (concat "\\(" (mapconcat 'downcase words
-                                          "[ \t\r\n]+") "\\)[ \t\r\n]")
-           re2a (concat "[ \t\r\n]" re2a_)
-           re4_ (concat "\\(" (mapconcat 'downcase words
-                                         "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
-           re4 (concat "[^a-zA-Z_]" re4_)
-
-           re1 (concat pre re2 post)
-           re3 (concat pre (if pre re4_ re4) post)
-           re5 (concat pre ".*" re4)
-           re2 (concat pre re2)
-           re2a (concat pre (if pre re2a_ re2a))
-           re4 (concat pre (if pre re4_ re4))
-           reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
-                         "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
-                         re5 "\\)"))
-      (cond
-       ((eq type 'org-occur) (org-occur reall))
-       ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
-       (t (goto-char (point-min))
-         (setq type 'fuzzy)
-         (if (or (and (org-search-not-self 1 re0 nil t)
-                      (setq type 'dedicated))
-                 (org-search-not-self 1 re1 nil t)
-                 (org-search-not-self 1 re2 nil t)
-                 (org-search-not-self 1 re2a nil t)
-                 (org-search-not-self 1 re3 nil t)
-                 (org-search-not-self 1 re4 nil t)
-                 (org-search-not-self 1 re5 nil t))
-             (goto-char (match-beginning 1))
-           (goto-char pos)
-           (error "No match"))))))
-    (and (derived-mode-p 'org-mode)
-        (not stealth)
-        (org-show-context 'link-search))
+            (catch :found
+              (while (re-search-forward title-re nil t)
+                (when (equal words
+                             (split-string
+                              (replace-regexp-in-string
+                               cookie-re ""
+                               (replace-regexp-in-string
+                                comment-re "" (org-get-heading t t)))))
+                  (throw :found t)))
+              nil)))
+      (beginning-of-line)
+      (setq type 'dedicated))
+     ;; Offer to create non-existent headline depending on
+     ;; `org-link-search-must-match-exact-headline'.
+     ((and (derived-mode-p 'org-mode)
+          (not org-link-search-inhibit-query)
+          (eq org-link-search-must-match-exact-headline 'query-to-create)
+          (yes-or-no-p "No match - create this as a new heading? "))
+      (goto-char (point-max))
+      (unless (bolp) (newline))
+      (org-insert-heading nil t t)
+      (insert s "\n")
+      (beginning-of-line 0))
+     ;; Only headlines are looked after.  No need to process
+     ;; further: throw an error.
+     ((and (derived-mode-p 'org-mode)
+          (or starred org-link-search-must-match-exact-headline))
+      (goto-char origin)
+      (error "No match for fuzzy expression: %s" normalized))
+     ;; Regular text search.
+     ((catch :fuzzy-match
+       (goto-char (point-min))
+       (while (re-search-forward s-multi-re nil t)
+         ;; Skip match if it contains AVOID-POS or it is included in
+         ;; a link with a description but outside the description.
+         (unless (or (and avoid-pos
+                          (<= (match-beginning 0) avoid-pos)
+                          (> (match-end 0) avoid-pos))
+                     (and (save-match-data
+                            (org-in-regexp org-bracket-link-regexp))
+                          (match-beginning 3)
+                          (or (> (match-beginning 3) (point))
+                              (<= (match-end 3) (point)))
+                          (org-element-lineage
+                           (save-match-data (org-element-context))
+                           '(link) t)))
+           (goto-char (match-beginning 0))
+           (setq type 'fuzzy)
+           (throw :fuzzy-match t)))
+       nil))
+     ;; All failed.  Throw an error.
+     (t (goto-char origin)
+       (error "No match for fuzzy expression: %s" normalized)))
+    ;; Disclose surroundings of match, if appropriate.
+    (when (and (derived-mode-p 'org-mode) (not stealth))
+      (org-show-context 'link-search))
     type))
 
-(defun org-search-not-self (group &rest args)
-  "Execute `re-search-forward', but only accept matches that do not
-enclose the position of `org-open-link-marker'."
-  (let ((m org-open-link-marker))
-    (catch 'exit
-      (while (apply #'re-search-forward args)
-       (unless (get-text-property (match-end group) 'intangible) ; Emacs 21
-         (goto-char (match-end group))
-         (if (and (or (not (eq (marker-buffer m) (current-buffer)))
-                      (> (match-beginning 0) (marker-position m))
-                      (< (match-end 0) (marker-position m)))
-                  (save-match-data
-                    (or (not (org-in-regexp
-                              org-bracket-link-analytic-regexp 1))
-                        (not (match-end 4))  ; no description
-                        (and (<= (match-beginning 4) (point))
-                             (>= (match-end 4) (point))))))
-             (throw 'exit (point))))))))
-
 (defun org-get-buffer-for-internal-link (buffer)
   "Return a buffer to be used for displaying the link target of internal 
links."
   (cond
    ((not org-display-internal-link-with-indirect-buffer)
     buffer)
-   ((string-match "(Clone)$" (buffer-name buffer))
+   ((string-suffix-p "(Clone)" (buffer-name buffer))
     (message "Buffer is already a clone, not making another one")
     ;; we also do not modify visibility in this case
     buffer)
@@ -10953,8 +11266,8 @@ to read."
       (goto-char (point-min))
       (when (re-search-forward "match[a-z]+" nil t)
        (setq beg (match-end 0))
-       (if (re-search-forward "^[ \t]*[0-9]+" nil t)
-           (setq end (1- (match-beginning 0)))))
+       (when (re-search-forward "^[ \t]*[0-9]+" nil t)
+         (setq end (1- (match-beginning 0)))))
       (and beg end (let ((inhibit-read-only t)) (delete-region beg end)))
       (goto-char (point-min))
       (select-window cwin))))
@@ -10962,13 +11275,13 @@ to read."
 ;;; The mark ring for links jumps
 
 (defvar org-mark-ring nil
-  "Mark ring for positions before jumps in Org-mode.")
+  "Mark ring for positions before jumps in Org mode.")
 (defvar org-mark-ring-last-goto nil
   "Last position in the mark ring used to go back.")
 ;; Fill and close the ring
 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is 
reloaded
-(loop for i from 1 to org-mark-ring-length do
-      (push (make-marker) org-mark-ring))
+(dotimes (_ org-mark-ring-length)
+  (push (make-marker) org-mark-ring))
 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
        org-mark-ring)
 
@@ -10982,15 +11295,15 @@ to read."
               (or buffer (current-buffer)))
   (message "%s"
           (substitute-command-keys
-           "Position saved to mark ring, go back with 
\\[org-mark-ring-goto].")))
+           "Position saved to mark ring, go back with \
+`\\[org-mark-ring-goto]'.")))
 
 (defun org-mark-ring-goto (&optional n)
   "Jump to the previous position in the mark ring.
 With prefix arg N, jump back that many stored positions.  When
 called several times in succession, walk through the entire ring.
-Org-mode commands jumping to a different position in the current file,
-or to another Org-mode file, automatically push the old position
-onto the ring."
+Org mode commands jumping to a different position in the current file,
+or to another Org file, automatically push the old position onto the ring."
   (interactive "p")
   (let (p m)
     (if (eq last-command this-command)
@@ -10998,25 +11311,19 @@ onto the ring."
       (setq p org-mark-ring))
     (setq org-mark-ring-last-goto p)
     (setq m (car p))
-    (org-pop-to-buffer-same-window (marker-buffer m))
+    (pop-to-buffer-same-window (marker-buffer m))
     (goto-char m)
-    (if (or (outline-invisible-p) (org-invisible-p2)) (org-show-context 
'mark-goto))))
+    (when (or (org-invisible-p) (org-invisible-p2)) (org-show-context 
'mark-goto))))
 
-(defun org-remove-angle-brackets (s)
-  (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
-  (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
-  s)
 (defun org-add-angle-brackets (s)
-  (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
-  (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
-  s)
-(defun org-remove-double-quotes (s)
-  (if (equal (substring s 0 1) "\"") (setq s (substring s 1)))
-  (if (equal (substring s -1) "\"") (setq s (substring s 0 -1)))
+  (unless (equal (substring s 0 1) "<") (setq s (concat "<" s)))
+  (unless (equal (substring s -1) ">") (setq s (concat s ">")))
   s)
 
 ;;; Following specific links
 
+(defvar org-agenda-buffer-tmp-name)
+(defvar org-agenda-start-on-weekday)
 (defun org-follow-timestamp-link ()
   "Open an agenda view for the time-stamp date/range at point."
   (cond
@@ -11071,43 +11378,40 @@ If the file does not exist, an error is thrown."
                   buffer-file-name
                 (substitute-in-file-name (expand-file-name path))))
         (file-apps (append org-file-apps (org-default-apps)))
-        (apps (org-remove-if
+        (apps (cl-remove-if
                'org-file-apps-entry-match-against-dlink-p file-apps))
-        (apps-dlink (org-remove-if-not
+        (apps-dlink (cl-remove-if-not
                      'org-file-apps-entry-match-against-dlink-p file-apps))
         (remp (and (assq 'remote apps) (org-file-remote-p file)))
-        (dirp (if remp nil (file-directory-p file)))
+        (dirp (unless remp (file-directory-p file)))
         (file (if (and dirp org-open-directory-means-index-dot-org)
                   (concat (file-name-as-directory file) "index.org")
                 file))
         (a-m-a-p (assq 'auto-mode apps))
         (dfile (downcase file))
-        ;; reconstruct the original file: link from the PATH, LINE and SEARCH 
args
-        (link (cond ((and (eq line nil)
-                          (eq search nil))
-                     file)
-                    (line
-                     (concat file "::" (number-to-string line)))
-                    (search
-                     (concat file "::" search))))
+        ;; Reconstruct the original link from the PATH, LINE and
+        ;; SEARCH args.
+        (link (cond (line (concat file "::" (number-to-string line)))
+                    (search (concat file "::" search))
+                    (t file)))
         (dlink (downcase link))
         (old-buffer (current-buffer))
         (old-pos (point))
         (old-mode major-mode)
-        ext cmd link-match-data)
-    (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
-       (setq ext (match-string 1 dfile))
-      (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
-         (setq ext (match-string 1 dfile))))
+        (ext
+         (and (string-match "\\`.*?\\.\\([a-zA-Z0-9]+\\(\\.gz\\)?\\)\\'" dfile)
+              (match-string 1 dfile)))
+        cmd link-match-data)
     (cond
      ((member in-emacs '((16) system))
-      (setq cmd (cdr (assoc 'system apps))))
+      (setq cmd (cdr (assq 'system apps))))
      (in-emacs (setq cmd 'emacs))
      (t
-      (setq cmd (or (and remp (cdr (assoc 'remote apps)))
-                   (and dirp (cdr (assoc 'directory apps)))
-                                       ; first, try matching against apps-dlink
-                                       ; if we get a match here, store the 
match data for later
+      (setq cmd (or (and remp (cdr (assq 'remote apps)))
+                   (and dirp (cdr (assq 'directory apps)))
+                   ;; First, try matching against apps-dlink if we
+                   ;; get a match here, store the match data for
+                   ;; later.
                    (let ((match (assoc-default dlink apps-dlink
                                                'string-match)))
                      (if match
@@ -11120,9 +11424,9 @@ If the file does not exist, an error is thrown."
                    (assoc-default dfile (org-apps-regexp-alist apps a-m-a-p)
                                   'string-match)
                    (cdr (assoc ext apps))
-                   (cdr (assoc t apps))))))
+                   (cdr (assq t apps))))))
     (when (eq cmd 'system)
-      (setq cmd (cdr (assoc 'system apps))))
+      (setq cmd (cdr (assq 'system apps))))
     (when (eq cmd 'default)
       (setq cmd (cdr (assoc t apps))))
     (when (eq cmd 'mailcap)
@@ -11133,21 +11437,20 @@ If the file does not exist, an error is thrown."
        (if (stringp command)
            (setq cmd command)
          (setq cmd 'emacs))))
-    (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
-            (not (file-exists-p file))
-            (not org-open-non-existing-files))
-       (user-error "No such file: %s" file))
+    (when (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
+              (not (file-exists-p file))
+              (not org-open-non-existing-files))
+      (user-error "No such file: %s" file))
     (cond
      ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
       ;; Remove quotes around the file name - we'll use shell-quote-argument.
       (while (string-match "['\"]%s['\"]" cmd)
        (setq cmd (replace-match "%s" t t cmd)))
-      (while (string-match "%s" cmd)
-       (setq cmd (replace-match
-                  (save-match-data
-                    (shell-quote-argument
-                     (convert-standard-filename file)))
-                  t t cmd)))
+      (setq cmd (replace-regexp-in-string
+                "%s"
+                (shell-quote-argument (convert-standard-filename file))
+                cmd
+                nil t))
 
       ;; Replace "%1", "%2" etc. in command with group matches from regex
       (save-match-data
@@ -11169,17 +11472,33 @@ If the file does not exist, an error is thrown."
          (eq cmd 'emacs))
       (funcall (cdr (assq 'file org-link-frame-setup)) file)
       (widen)
-      (if line (org-goto-line line)
-       (if search (org-link-search search))))
+      (cond (line (org-goto-line line)
+                 (when (derived-mode-p 'org-mode) (org-reveal)))
+           (search (org-link-search search))))
+     ((functionp cmd)
+      (save-match-data
+       (set-match-data link-match-data)
+       (condition-case nil
+           (funcall cmd file link)
+         ;; FIXME: Remove this check when most default installations
+         ;; of Emacs have at least Org 9.0.
+         ((debug wrong-number-of-arguments wrong-type-argument
+           invalid-function)
+          (user-error "Please see Org News for version 9.0 about \
+`org-file-apps'--Lisp error: %S" cmd)))))
      ((consp cmd)
-      (let ((file (convert-standard-filename file)))
-       (save-match-data
-         (set-match-data link-match-data)
-         (eval cmd))))
+      ;; FIXME: Remove this check when most default installations of
+      ;; Emacs have at least Org 9.0.
+      ;; Heads-up instead of silently fall back to
+      ;; `org-link-frame-setup' for an old usage of `org-file-apps'
+      ;; with sexp instead of a function for `cmd'.
+      (user-error "Please see Org News for version 9.0 about \
+`org-file-apps'--Error: Deprecated usage of %S" cmd))
      (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
-    (and (derived-mode-p 'org-mode) (eq old-mode 'org-mode)
-        (or (not (equal old-buffer (current-buffer)))
-            (not (equal old-pos (point))))
+    (and (derived-mode-p 'org-mode)
+        (eq old-mode 'org-mode)
+        (or (not (eq old-buffer (current-buffer)))
+            (not (eq old-pos (point))))
         (org-mark-ring-push old-pos old-buffer))))
 
 (defun org-file-apps-entry-match-against-dlink-p (entry)
@@ -11220,16 +11539,15 @@ be opened in Emacs."
   (append
    (delq nil
         (mapcar (lambda (x)
-                  (if (not (stringp (car x)))
-                      nil
+                  (unless (not (stringp (car x)))
                     (if (string-match "\\W" (car x))
                         x
                       (cons (concat "\\." (car x) "\\'") (cdr x)))))
                 list))
-   (if add-auto-mode
-       (mapcar (lambda (x) (cons (car x) 'emacs)) auto-mode-alist))))
+   (when add-auto-mode
+     (mapcar (lambda (x) (cons (car x) 'emacs)) auto-mode-alist))))
 
-(defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
+(defvar ange-ftp-name-format)
 (defun org-file-remote-p (file)
   "Test whether FILE specifies a location on a remote system.
 Return non-nil if the location is indeed remote.
@@ -11262,8 +11580,8 @@ on the system \"/address@hidden:\"."
    ((not (listp org-reverse-note-order)) nil)
    (t (catch 'exit
         (dolist (entry org-reverse-note-order)
-          (if (string-match (car entry) buffer-file-name)
-              (throw 'exit (cdr entry))))))))
+          (when (string-match (car entry) buffer-file-name)
+           (throw 'exit (cdr entry))))))))
 
 (defvar org-refile-target-table nil
   "The list of refile targets, created by `org-refile'.")
@@ -11288,7 +11606,7 @@ on the system \"/address@hidden:\"."
 
 (defun org-refile-cache-clear ()
   "Clear the refile cache and disable all the markers."
-  (mapc (lambda (m) (move-marker m nil)) org-refile-markers)
+  (dolist (m org-refile-markers) (move-marker m nil))
   (setq org-refile-markers nil)
   (setq org-refile-cache nil)
   (message "Refile cache has been cleared"))
@@ -11323,17 +11641,23 @@ on the system \"/address@hidden:\"."
                           org-refile-cache))))
       (and set (org-refile-cache-check-set set) set)))))
 
-(defun org-refile-get-targets (&optional default-buffer excluded-entries)
+(defvar org-outline-path-cache nil
+  "Alist between buffer positions and outline paths.
+It value is an alist (POSITION . PATH) where POSITION is the
+buffer position at the beginning of an entry and PATH is a list
+of strings describing the outline path for that entry, in reverse
+order.")
+
+(defun org-refile-get-targets (&optional default-buffer)
   "Produce a table with refile targets."
   (let ((case-fold-search nil)
        ;; otherwise org confuses "TODO" as a kw and "Todo" as a word
        (entries (or org-refile-targets '((nil . (:level . 1)))))
-       targets tgs txt re files desc descre fast-path-p level pos0)
+       targets tgs files desc descre)
     (message "Getting targets...")
     (with-current-buffer (or default-buffer (current-buffer))
       (dolist (entry entries)
        (setq files (car entry) desc (cdr entry))
-       (setq fast-path-p nil)
        (cond
         ((null files) (setq files (list (current-buffer))))
         ((eq files 'org-agenda-files)
@@ -11342,7 +11666,7 @@ on the system \"/address@hidden:\"."
          (setq files (funcall files)))
         ((and (symbolp files) (boundp files))
          (setq files (symbol-value files))))
-       (if (stringp files) (setq files (list files)))
+       (when (stringp files) (setq files (list files)))
        (cond
         ((eq (car desc) :tag)
          (setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) 
":")))
@@ -11357,7 +11681,6 @@ on the system \"/address@hidden:\"."
                                            (cdr desc)))
                               "\\}[ \t]")))
         ((eq (car desc) :maxlevel)
-         (setq fast-path-p t)
          (setq descre (concat "^\\*\\{1," (number-to-string
                                            (if org-odd-levels-only
                                                (1- (* 2 (cdr desc)))
@@ -11365,99 +11688,113 @@ on the system \"/address@hidden:\"."
                               "\\}[ \t]")))
         (t (error "Bad refiling target description %s" desc)))
        (dolist (f files)
-         (with-current-buffer
-             (if (bufferp f) f (org-get-agenda-file-buffer f))
+         (with-current-buffer (if (bufferp f) f (org-get-agenda-file-buffer f))
            (or
             (setq tgs (org-refile-cache-get (buffer-file-name) descre))
             (progn
-              (if (bufferp f) (setq f (buffer-file-name
-                                       (buffer-base-buffer f))))
+              (when (bufferp f)
+                (setq f (buffer-file-name (buffer-base-buffer f))))
               (setq f (and f (expand-file-name f)))
-              (if (eq org-refile-use-outline-path 'file)
-                  (push (list (file-name-nondirectory f) f nil nil) tgs))
-              (save-excursion
-                (save-restriction
-                  (widen)
-                  (goto-char (point-min))
-                  (while (re-search-forward descre nil t)
-                    (goto-char (setq pos0 (point-at-bol)))
-                    (catch 'next
-                      (when org-refile-target-verify-function
-                        (save-match-data
-                          (or (funcall org-refile-target-verify-function)
-                              (throw 'next t))))
-                      (when (and (looking-at org-complex-heading-regexp)
-                                 (not (member (match-string 4) 
excluded-entries))
-                                 (match-string 4))
-                        (setq level (org-reduced-level
-                                     (- (match-end 1) (match-beginning 1)))
-                              txt (org-link-display-format (match-string 4))
-                              txt (replace-regexp-in-string "\\( 
*[[0-9]+/?[0-9]*%?]\\)+$" "" txt)
-                              re (format org-complex-heading-regexp-format
-                                         (regexp-quote (match-string 4))))
-                        (when org-refile-use-outline-path
-                          (setq txt (mapconcat
-                                     'org-protect-slash
-                                     (append
-                                      (if (eq org-refile-use-outline-path
-                                              'file)
-                                          (list (file-name-nondirectory
-                                                 (buffer-file-name
-                                                  (buffer-base-buffer))))
-                                        (if (eq org-refile-use-outline-path
-                                                'full-file-path)
-                                            (list (buffer-file-name
-                                                   (buffer-base-buffer)))))
-                                      (org-get-outline-path fast-path-p
-                                                            level txt)
-                                      (list txt))
-                                     "/")))
-                        (push (list txt f re (org-refile-marker (point)))
-                              tgs)))
-                    (when (= (point) pos0)
-                      ;; verification function has not moved point
-                      (goto-char (point-at-eol))))))))
+              (when (eq org-refile-use-outline-path 'file)
+                (push (list (file-name-nondirectory f) f nil nil) tgs))
+              (org-with-wide-buffer
+               (goto-char (point-min))
+               (setq org-outline-path-cache nil)
+               (while (re-search-forward descre nil t)
+                 (beginning-of-line)
+                 (let ((case-fold-search nil))
+                   (looking-at org-complex-heading-regexp))
+                 (let ((begin (point))
+                       (heading (match-string-no-properties 4)))
+                   (unless (or (and
+                                org-refile-target-verify-function
+                                (not
+                                 (funcall org-refile-target-verify-function)))
+                               (not heading))
+                     (let ((re (format org-complex-heading-regexp-format
+                                       (regexp-quote heading)))
+                           (target
+                            (if (not org-refile-use-outline-path) heading
+                              (mapconcat
+                               #'org-protect-slash
+                               (append
+                                (pcase org-refile-use-outline-path
+                                  (`file (list (file-name-nondirectory
+                                                (buffer-file-name
+                                                 (buffer-base-buffer)))))
+                                  (`full-file-path
+                                   (list (buffer-file-name
+                                          (buffer-base-buffer))))
+                                  (_ nil))
+                                (org-get-outline-path t t))
+                               "/"))))
+                       (push (list target f re (org-refile-marker (point)))
+                             tgs)))
+                   (when (= (point) begin)
+                     ;; Verification function has not moved point.
+                     (end-of-line)))))))
            (when org-refile-use-cache
              (org-refile-cache-put tgs (buffer-file-name) descre))
            (setq targets (append tgs targets))))))
     (message "Getting targets...done")
-    (nreverse targets)))
+    (delete-dups (nreverse targets))))
 
 (defun org-protect-slash (s)
-  (while (string-match "/" s)
-    (setq s (replace-match "\\" t t s)))
-  s)
-
-(defvar org-olpa (make-vector 20 nil))
-
-(defun org-get-outline-path (&optional fastp level heading)
-  "Return the outline path to the current entry, as a list.
-
-The parameters FASTP, LEVEL, and HEADING are for use by a scanner
-routine which makes outline path derivations for an entire file,
-avoiding backtracing.  Refile target collection makes use of that."
-  (if fastp
-      (progn
-       (if (> level 19)
-           (error "Outline path failure, more than 19 levels"))
-       (loop for i from level upto 19 do
-             (aset org-olpa i nil))
-       (prog1
-           (delq nil (append org-olpa nil))
-         (aset org-olpa level heading)))
-    (let (rtn case-fold-search)
-      (save-excursion
-       (save-restriction
-         (widen)
-         (while (org-up-heading-safe)
-           (when (looking-at org-complex-heading-regexp)
-             (push (org-trim
-                    (replace-regexp-in-string
-                     ;; Remove statistical/checkboxes cookies
-                     "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
-                     (org-match-string-no-properties 4)))
-                   rtn)))
-         rtn)))))
+  (replace-regexp-in-string "/" "\\/" s nil t))
+
+(defun org--get-outline-path-1 (&optional use-cache)
+  "Return outline path to current headline.
+
+Outline path is a list of strings, in reverse order.  When
+optional argument USE-CACHE is non-nil, make use of a cache.  See
+`org-get-outline-path' for details.
+
+Assume buffer is widened and point is on a headline."
+  (or (and use-cache (cdr (assq (point) org-outline-path-cache)))
+      (let ((p (point))
+           (heading (let ((case-fold-search nil))
+                      (looking-at org-complex-heading-regexp)
+                      (if (not (match-end 4)) ""
+                        ;; Remove statistics cookies.
+                        (org-trim
+                         (org-link-display-format
+                          (replace-regexp-in-string
+                           "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
+                           (match-string-no-properties 4))))))))
+       (if (org-up-heading-safe)
+           (let ((path (cons heading (org--get-outline-path-1 use-cache))))
+             (when use-cache
+               (push (cons p path) org-outline-path-cache))
+             path)
+         ;; This is a new root node.  Since we assume we are moving
+         ;; forward, we can drop previous cache so as to limit number
+         ;; of associations there.
+         (let ((path (list heading)))
+           (when use-cache (setq org-outline-path-cache (list (cons p path))))
+           path)))))
+
+(defun org-get-outline-path (&optional with-self use-cache)
+  "Return the outline path to the current entry.
+
+An outline path is a list of ancestors for current headline, as
+a list of strings.  Statistics cookies are removed and links are
+replaced with their description, if any, or their path otherwise.
+
+When optional argument WITH-SELF is non-nil, the path also
+includes the current headline.
+
+When optional argument USE-CACHE is non-nil, cache outline paths
+between calls to this function so as to avoid backtracking.  This
+argument is useful when planning to find more than one outline
+path in the same document.  In that case, there are two
+conditions to satisfy:
+  - `org-outline-path-cache' is set to nil before starting the
+    process;
+  - outline paths are computed by increasing buffer positions."
+  (org-with-wide-buffer
+   (and (or (and with-self (org-back-to-heading t))
+           (org-up-heading-safe))
+       (reverse (org--get-outline-path-1 use-cache)))))
 
 (defun org-format-outline-path (path &optional width prefix separator)
   "Format the outline path PATH for display.
@@ -11467,38 +11804,28 @@ such as the file name.
 SEPARATOR is inserted between the different parts of the path,
 the default is \"/\"."
   (setq width (or width 79))
-  (if prefix (setq width (- width (length prefix))))
-  (if (not path)
-      (or prefix "")
-    (let* ((nsteps (length path))
-          (total-width (+ nsteps (apply '+ (mapcar 'length path))))
-          (maxwidth (if (<= total-width width)
-                        10000  ;; everything fits
-                      ;; we need to shorten the level headings
-                      (/ (- width nsteps) nsteps)))
-          (org-odd-levels-only nil)
-          (n 0)
-          (total (1+ (length prefix))))
-      (setq maxwidth (max maxwidth 10))
-      (concat prefix
-             (if prefix (or separator "/"))
-             (mapconcat
-              (lambda (h)
-                (setq n (1+ n))
-                (if (and (= n nsteps) (< maxwidth 10000))
-                    (setq maxwidth (- total-width total)))
-                (if (< (length h) maxwidth)
-                    (progn (setq total (+ total (length h) 1)) h)
-                  (setq h (substring h 0 (- maxwidth 2))
-                        total (+ total maxwidth 1))
-                  (if (string-match "[ \t]+\\'" h)
-                      (setq h (substring h 0 (match-beginning 0))))
-                  (setq h (concat  h "..")))
-                (org-add-props h nil 'face
-                               (nth (% (1- n) org-n-level-faces)
-                                    org-level-faces))
-                h)
-              path (or separator "/"))))))
+  (setq path (delq nil path))
+  (unless (> width 0)
+    (user-error "Argument `width' must be positive"))
+  (setq separator (or separator "/"))
+  (let* ((org-odd-levels-only nil)
+        (fpath (concat
+                prefix (and prefix path separator)
+                (mapconcat
+                 (lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
+                 (cl-loop for head in path
+                          for n from 0
+                          collect (org-add-props
+                                      head nil 'face
+                                      (nth (% n org-n-level-faces) 
org-level-faces)))
+                 separator))))
+    (when (> (length fpath) width)
+      (if (< width 7)
+         ;; It's unlikely that `width' will be this small, but don't
+         ;; waste characters by adding ".." if it is.
+         (setq fpath (substring fpath 0 width))
+       (setf (substring fpath (- width 2)) "..")))
+    fpath))
 
 (defun org-display-outline-path (&optional file current separator 
just-return-string)
   "Display the current outline path in the echo area.
@@ -11513,10 +11840,10 @@ If JUST-RETURN-STRING is non-nil, return a string, 
don't display a message."
         (bfn (buffer-file-name (buffer-base-buffer)))
         (path (and (derived-mode-p 'org-mode) (org-get-outline-path)))
         res)
-    (if current (setq path (append path
-                                  (save-excursion
-                                    (org-back-to-heading t)
-                                    (if (looking-at org-complex-heading-regexp)
+    (when current (setq path (append path
+                                    (save-excursion
+                                      (org-back-to-heading t)
+                                      (when (looking-at 
org-complex-heading-regexp)
                                         (list (match-string 4)))))))
     (setq res
          (org-format-outline-path
@@ -11546,25 +11873,27 @@ the *old* location.")
   (let ((org-refile-keep t))
     (funcall 'org-refile nil nil nil "Copy")))
 
-(defun org-refile (&optional goto default-buffer rfloc msg)
+(defun org-refile (&optional arg default-buffer rfloc msg)
   "Move the entry or entries at point to another heading.
+
 The list of target headings is compiled using the information in
 `org-refile-targets', which see.
 
-At the target location, the entry is filed as a subitem of the target
-heading.  Depending on `org-reverse-note-order', the new subitem will
-either be the first or the last subitem.
+At the target location, the entry is filed as a subitem of the
+target heading.  Depending on `org-reverse-note-order', the new
+subitem will either be the first or the last subitem.
 
-If there is an active region, all entries in that region will be moved.
-However, the region must fulfill the requirement that the first heading
-is the first one sets the top-level of the moved text - at most siblings
-below it are allowed.
+If there is an active region, all entries in that region will be
+refiled.  However, the region must fulfill the requirement that
+the first heading sets the top-level of the moved text.
 
-With prefix arg GOTO, the command will only visit the target location
+With a `\\[universal-argument]' ARG, the command will only visit the target \
+location
 and not actually move anything.
 
-With a double prefix arg \\[universal-argument] \\[universal-argument], \
-go to the location where the last refiling operation has put the subtree.
+With a prefix `\\[universal-argument] \\[universal-argument]', go to the \
+location where the last
+refiling operation has put the subtree.
 
 With a numeric prefix argument of `2', refile to the running clock.
 
@@ -11578,26 +11907,23 @@ RFLOC can be a refile location obtained in a 
different way.
 MSG is a string to replace \"Refile\" in the default prompt with
 another verb.  E.g. `org-copy' sets this parameter to \"Copy\".
 
-See also `org-refile-use-outline-path' and `org-completion-use-ido'.
+See also `org-refile-use-outline-path'.
 
-If you are using target caching (see `org-refile-use-cache'),
-you have to clear the target cache in order to find new targets.
-This can be done with a 0 prefix (`C-0 C-c C-w') or a triple
+If you are using target caching (see `org-refile-use-cache'), you
+have to clear the target cache in order to find new targets.
+This can be done with a `0' prefix (`C-0 C-c C-w') or a triple
 prefix argument (`C-u C-u C-u C-c C-w')."
-
   (interactive "P")
-  (if (member goto '(0 (64)))
+  (if (member arg '(0 (64)))
       (org-refile-cache-clear)
     (let* ((actionmsg (cond (msg msg)
-                           ((equal goto 3) "Refile (and keep)")
+                           ((equal arg 3) "Refile (and keep)")
                            (t "Refile")))
-          (cbuf (current-buffer))
           (regionp (org-region-active-p))
           (region-start (and regionp (region-beginning)))
           (region-end (and regionp (region-end)))
-          (filename (buffer-file-name (buffer-base-buffer cbuf)))
-          (org-refile-keep (if (equal goto 3) t org-refile-keep))
-          pos it nbuf file re level reversed)
+          (org-refile-keep (if (equal arg 3) t org-refile-keep))
+          pos it nbuf file level reversed)
       (setq last-command nil)
       (when regionp
        (goto-char region-start)
@@ -11610,10 +11936,10 @@ prefix argument (`C-u C-u C-u C-c C-w')."
                        (org-toggle-heading)
                        (setq region-end (+ (- (point-at-eol) s) region-end)))))
          (user-error "The region is not a (sequence of) subtree(s)")))
-      (if (equal goto '(16))
+      (if (equal arg '(16))
          (org-refile-goto-last-stored)
        (when (or
-              (and (equal goto 2)
+              (and (equal arg 2)
                    org-clock-hd-marker (marker-buffer org-clock-hd-marker)
                    (prog1
                        (setq it (list (or org-clock-heading "running clock")
@@ -11621,43 +11947,44 @@ prefix argument (`C-u C-u C-u C-c C-w')."
                                        (marker-buffer org-clock-hd-marker))
                                       ""
                                       (marker-position org-clock-hd-marker)))
-                     (setq goto nil)))
-              (setq it (or rfloc
-                           (let (heading-text)
-                             (save-excursion
-                               (unless (and goto (listp goto))
-                                 (org-back-to-heading t)
-                                 (setq heading-text
-                                       (nth 4 (org-heading-components))))
-
-                               (org-refile-get-location
-                                (cond ((and goto (listp goto)) "Goto")
-                                      (regionp (concat actionmsg " region to"))
-                                      (t (concat actionmsg " subtree \""
-                                                 heading-text "\" to")))
-                                default-buffer
-                                (and (not (equal '(4) goto))
-                                     org-refile-allow-creating-parent-nodes)
-                                goto))))))
+                     (setq arg nil)))
+              (setq it
+                    (or rfloc
+                        (let (heading-text)
+                          (save-excursion
+                            (unless (and arg (listp arg))
+                              (org-back-to-heading t)
+                              (setq heading-text
+                                    (replace-regexp-in-string
+                                     org-bracket-link-regexp
+                                     "\\3"
+                                     (or (nth 4 (org-heading-components))
+                                         ""))))
+                            (org-refile-get-location
+                             (cond ((and arg (listp arg)) "Goto")
+                                   (regionp (concat actionmsg " region to"))
+                                   (t (concat actionmsg " subtree \""
+                                              heading-text "\" to")))
+                             default-buffer
+                             (and (not (equal '(4) arg))
+                                  org-refile-allow-creating-parent-nodes)))))))
          (setq file (nth 1 it)
-               re (nth 2 it)
                pos (nth 3 it))
-         (if (and (not goto)
-                  pos
-                  (equal (buffer-file-name) file)
-                  (if regionp
-                      (and (>= pos region-start)
-                           (<= pos region-end))
-                    (and (>= pos (point))
-                         (< pos (save-excursion
-                                  (org-end-of-subtree t t))))))
-             (error "Cannot refile to position inside the tree or region"))
-
+         (when (and (not arg)
+                    pos
+                    (equal (buffer-file-name) file)
+                    (if regionp
+                        (and (>= pos region-start)
+                             (<= pos region-end))
+                      (and (>= pos (point))
+                           (< pos (save-excursion
+                                    (org-end-of-subtree t t))))))
+           (error "Cannot refile to position inside the tree or region"))
          (setq nbuf (or (find-buffer-visiting file)
                         (find-file-noselect file)))
-         (if (and goto (not (equal goto 3)))
+         (if (and arg (not (equal arg 3)))
              (progn
-               (org-pop-to-buffer-same-window nbuf)
+               (pop-to-buffer-same-window nbuf)
                (goto-char pos)
                (org-show-context 'org-goto))
            (if regionp
@@ -11668,50 +11995,48 @@ prefix argument (`C-u C-u C-u C-c C-w')."
            (with-current-buffer (setq nbuf (or (find-buffer-visiting file)
                                                (find-file-noselect file)))
              (setq reversed (org-notes-order-reversed-p))
-             (save-excursion
-               (save-restriction
-                 (widen)
-                 (if pos
-                     (progn
-                       (goto-char pos)
-                       (looking-at org-outline-regexp)
-                       (setq level (org-get-valid-level (funcall 
outline-level) 1))
-                       (goto-char
-                        (if reversed
-                            (or (outline-next-heading) (point-max))
-                          (or (save-excursion (org-get-next-sibling))
-                              (org-end-of-subtree t t)
-                              (point-max)))))
-                   (setq level 1)
-                   (if (not reversed)
-                       (goto-char (point-max))
-                     (goto-char (point-min))
-                     (or (outline-next-heading) (goto-char (point-max)))))
-                 (if (not (bolp)) (newline))
-                 (org-paste-subtree level)
-                 (when org-log-refile
-                   (org-add-log-setup 'refile nil nil 'findpos org-log-refile)
-                   (unless (eq org-log-refile 'note)
-                     (save-excursion (org-add-log-note))))
-                 (and org-auto-align-tags
-                      (let ((org-loop-over-headlines-in-active-region nil))
-                        (org-set-tags nil t)))
-                 (let ((bookmark-name (plist-get org-bookmark-names-plist
-                                                 :last-refile)))
-                   (when bookmark-name
-                     (with-demoted-errors
-                       (bookmark-set bookmark-name))))
-                 ;; If we are refiling for capture, make sure that the
-                 ;; last-capture pointers point here
-                 (when (org-bound-and-true-p org-refile-for-capture)
-                   (let ((bookmark-name (plist-get org-bookmark-names-plist
-                                                   :last-capture-marker)))
-                     (when bookmark-name
-                       (with-demoted-errors
-                         (bookmark-set bookmark-name))))
-                   (move-marker org-capture-last-stored-marker (point)))
-                 (if (fboundp 'deactivate-mark) (deactivate-mark))
-                 (run-hooks 'org-after-refile-insert-hook))))
+             (org-with-wide-buffer
+              (if pos
+                  (progn
+                    (goto-char pos)
+                    (looking-at org-outline-regexp)
+                    (setq level (org-get-valid-level (funcall outline-level) 
1))
+                    (goto-char
+                     (if reversed
+                         (or (outline-next-heading) (point-max))
+                       (or (save-excursion (org-get-next-sibling))
+                           (org-end-of-subtree t t)
+                           (point-max)))))
+                (setq level 1)
+                (if (not reversed)
+                    (goto-char (point-max))
+                  (goto-char (point-min))
+                  (or (outline-next-heading) (goto-char (point-max)))))
+              (unless (bolp) (newline))
+              (org-paste-subtree level nil nil t)
+              (when org-log-refile
+                (org-add-log-setup 'refile nil nil org-log-refile)
+                (unless (eq org-log-refile 'note)
+                  (save-excursion (org-add-log-note))))
+              (and org-auto-align-tags
+                   (let ((org-loop-over-headlines-in-active-region nil))
+                     (org-set-tags nil t)))
+              (let ((bookmark-name (plist-get org-bookmark-names-plist
+                                              :last-refile)))
+                (when bookmark-name
+                  (with-demoted-errors
+                      (bookmark-set bookmark-name))))
+              ;; If we are refiling for capture, make sure that the
+              ;; last-capture pointers point here
+              (when (bound-and-true-p org-capture-is-refiling)
+                (let ((bookmark-name (plist-get org-bookmark-names-plist
+                                                :last-capture-marker)))
+                  (when bookmark-name
+                    (with-demoted-errors
+                        (bookmark-set bookmark-name))))
+                (move-marker org-capture-last-stored-marker (point)))
+              (when (fboundp 'deactivate-mark) (deactivate-mark))
+              (run-hooks 'org-after-refile-insert-hook)))
            (unless org-refile-keep
              (if regionp
                  (delete-region (point) (+ (point) (- region-end 
region-start)))
@@ -11726,7 +12051,7 @@ prefix argument (`C-u C-u C-u C-c C-w')."
 (defun org-refile-goto-last-stored ()
   "Go to the location where the last refile was stored."
   (interactive)
-  (bookmark-jump "org-refile-last-stored")
+  (bookmark-jump (plist-get org-bookmark-names-plist :last-refile))
   (message "This is the location of the last refile"))
 
 (defun org-refile--get-location (refloc tbl)
@@ -11740,35 +12065,22 @@ Also check `org-refile-target-table'."
         (list (replace-regexp-in-string "/$" "" refloc)
               (replace-regexp-in-string "\\([^/]\\)$" "\\1/" refloc))))))
 
-(defun org-refile-get-location (&optional prompt default-buffer new-nodes
-                                         no-exclude)
+(defun org-refile-get-location (&optional prompt default-buffer new-nodes)
   "Prompt the user for a refile location, using PROMPT.
 PROMPT should not be suffixed with a colon and a space, because
 this function appends the default value from
-`org-refile-history' automatically, if that is not empty.
-When NO-EXCLUDE is set, do not exclude headlines in the current subtree,
-this is used for the GOTO interface."
+`org-refile-history' automatically, if that is not empty."
   (let ((org-refile-targets org-refile-targets)
-       (org-refile-use-outline-path org-refile-use-outline-path)
-       excluded-entries)
-    (when (and (derived-mode-p 'org-mode)
-              (not org-refile-use-cache)
-              (not no-exclude))
-      (org-map-tree
-       (lambda()
-        (setq excluded-entries
-              (append excluded-entries (list (org-get-heading t t)))))))
-    (setq org-refile-target-table
-         (org-refile-get-targets default-buffer excluded-entries)))
+       (org-refile-use-outline-path org-refile-use-outline-path))
+    (setq org-refile-target-table (org-refile-get-targets default-buffer)))
   (unless org-refile-target-table
     (user-error "No refile targets"))
   (let* ((cbuf (current-buffer))
-        (partial-completion-mode nil)
         (cfn (buffer-file-name (buffer-base-buffer cbuf)))
         (cfunc (if (and org-refile-use-outline-path
                         org-outline-path-complete-in-steps)
-                   'org-olpath-completing-read
-                 'org-icompleting-read))
+                   #'org-olpath-completing-read
+                 #'completing-read))
         (extra (if org-refile-use-outline-path "/" ""))
         (cbnex (concat (buffer-name) extra))
         (filename (and cfn (expand-file-name cfn)))
@@ -11803,8 +12115,8 @@ this is used for the GOTO interface."
                  (cons (car pa) (if (assoc (car org-refile-history) tbl)
                                     org-refile-history
                                   (cdr org-refile-history))))
-           (if (equal (car org-refile-history) (nth 1 org-refile-history))
-               (pop org-refile-history)))
+           (when (equal (car org-refile-history) (nth 1 org-refile-history))
+             (pop org-refile-history)))
          pa)
       (if (string-match "\\`\\(.*\\)/\\([^/]+\\)\\'" answ)
          (progn
@@ -11827,20 +12139,18 @@ this is used for the GOTO interface."
         (pos (nth 3 refile-pointer))
         buffer)
     (if (and (not (markerp pos)) (not file))
-       (user-error "Please save the buffer to a file before refiling")
+       (user-error "Please indicate a target file in the refile path")
       (when (org-string-nw-p re)
        (setq buffer (if (markerp pos)
                         (marker-buffer pos)
                       (or (find-buffer-visiting file)
                           (find-file-noselect file))))
        (with-current-buffer buffer
-         (save-excursion
-           (save-restriction
-             (widen)
-             (goto-char pos)
-             (beginning-of-line 1)
-             (unless (org-looking-at-p re)
-               (user-error "Invalid refile position, please clear the cache 
with `C-0 C-c C-w' before refiling")))))))))
+         (org-with-wide-buffer
+          (goto-char pos)
+          (beginning-of-line 1)
+          (unless (looking-at-p re)
+            (user-error "Invalid refile position, please clear the cache with 
`C-0 C-c C-w' before refiling"))))))))
 
 (defun org-refile-new-child (parent-target child)
   "Use refile target PARENT-TARGET to add new CHILD below it."
@@ -11851,53 +12161,43 @@ this is used for the GOTO interface."
        level)
     (with-current-buffer (or (find-buffer-visiting file)
                             (find-file-noselect file))
-      (save-excursion
-       (save-restriction
-         (widen)
-         (if pos
-             (goto-char pos)
-           (goto-char (point-max))
-           (if (not (bolp)) (newline)))
-         (when (looking-at org-outline-regexp)
-           (setq level (funcall outline-level))
-           (org-end-of-subtree t t))
-         (org-back-over-empty-lines)
-         (insert "\n" (make-string
-                       (if pos (org-get-valid-level level 1) 1) ?*)
-                 " " child "\n")
-         (beginning-of-line 0)
-         (list (concat (car parent-target) "/" child) file "" (point)))))))
+      (org-with-wide-buffer
+       (if pos
+          (goto-char pos)
+        (goto-char (point-max))
+        (unless (bolp) (newline)))
+       (when (looking-at org-outline-regexp)
+        (setq level (funcall outline-level))
+        (org-end-of-subtree t t))
+       (org-back-over-empty-lines)
+       (insert "\n" (make-string
+                    (if pos (org-get-valid-level level 1) 1) ?*)
+              " " child "\n")
+       (beginning-of-line 0)
+       (list (concat (car parent-target) "/" child) file "" (point))))))
 
 (defun org-olpath-completing-read (prompt collection &rest args)
   "Read an outline path like a file name."
-  (let ((thetable collection)
-       (org-completion-use-ido nil)       ; does not work with ido.
-       (org-completion-use-iswitchb nil)) ; or iswitchb
-    (apply
-     'org-icompleting-read prompt
-     (lambda (string predicate &optional flag)
-       (let (rtn r f (l (length string)))
-        (cond
-         ((eq flag nil)
-          ;; try completion
-          (try-completion string thetable))
-         ((eq flag t)
-          ;; all-completions
-          (setq rtn (all-completions string thetable predicate))
-          (mapcar
-           (lambda (x)
-             (setq r (substring x l))
-             (if (string-match " ([^)]*)$" x)
-                 (setq f (match-string 0 x))
-               (setq f ""))
-             (if (string-match "/" r)
-                 (concat string (substring r 0 (match-end 0)) f)
-               x))
-           rtn))
-         ((eq flag 'lambda)
-          ;; exact match?
-          (assoc string thetable)))))
-     args)))
+  (let ((thetable collection))
+    (apply #'completing-read
+          prompt
+          (lambda (string predicate &optional flag)
+            (cond
+             ((eq flag nil) (try-completion string thetable))
+             ((eq flag t)
+              (let ((l (length string)))
+                (mapcar (lambda (x)
+                          (let ((r (substring x l))
+                                (f (if (string-match " ([^)]*)$" x)
+                                       (match-string 0 x)
+                                     "")))
+                            (if (string-match "/" r)
+                                (concat string (substring r 0 (match-end 0)) f)
+                              x)))
+                        (all-completions string thetable predicate))))
+             ;; Exact match?
+             ((eq flag 'lambda) (assoc string thetable))))
+          args)))
 
 ;;;; Dynamic blocks
 
@@ -11910,19 +12210,12 @@ If not found, stay at current position and return 
nil."
       (setq pos (and (re-search-forward
                      (concat "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+" name 
"\\>") nil t)
                     (match-beginning 0))))
-    (if pos (goto-char pos))
+    (when pos (goto-char pos))
     pos))
 
-(defconst org-dblock-start-re
-  "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
-  "Matches the start line of a dynamic block, with parameters.")
-
-(defconst org-dblock-end-re "^[ \t]*#\\+\\(?:END\\|end\\)\\([: \t\r\n]\\|$\\)"
-  "Matches the end of a dynamic block.")
-
 (defun org-create-dblock (plist)
   "Create a dynamic block section, with parameters taken from PLIST.
-PLIST must contain a :name entry which is used as name of the block."
+PLIST must contain a :name entry which is used as the name of the block."
   (when (string-match "\\S-" (buffer-substring (point-at-bol) (point-at-eol)))
     (end-of-line 1)
     (newline))
@@ -12042,13 +12335,14 @@ This function can be used in a hook."
 
 ;;;; Completion
 
+(declare-function org-export-backend-options "ox" (cl-x) t)
 (defun org-get-export-keywords ()
   "Return a list of all currently understood export keywords.
 Export keywords include options, block names, attributes and
 keywords relative to each registered export back-end."
   (let (keywords)
     (dolist (backend
-            (org-bound-and-true-p org-export--registered-backends)
+            (bound-and-true-p org-export-registered-backends)
             (delq nil keywords))
       ;; Back-end name (for keywords, like #+LATEX:)
       (push (upcase (symbol-name (org-export-backend-name backend))) keywords)
@@ -12064,27 +12358,24 @@ keywords relative to each registered export back-end."
     "TITLE:" "TODO:" "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:"))
 
 (defcustom org-structure-template-alist
-  '(("s" "#+BEGIN_SRC ?\n\n#+END_SRC" "<src lang=\"?\">\n\n</src>")
-    ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE" "<example>\n?\n</example>")
-    ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE" "<quote>\n?\n</quote>")
-    ("v" "#+BEGIN_VERSE\n?\n#+END_VERSE" "<verse>\n?\n</verse>")
-    ("V" "#+BEGIN_VERBATIM\n?\n#+END_VERBATIM" "<verbatim>\n?\n</verbatim>")
-    ("c" "#+BEGIN_CENTER\n?\n#+END_CENTER" "<center>\n?\n</center>")
-    ("l" "#+BEGIN_LaTeX\n?\n#+END_LaTeX"
-     "<literal style=\"latex\">\n?\n</literal>")
-    ("L" "#+LaTeX: " "<literal style=\"latex\">?</literal>")
-    ("h" "#+BEGIN_HTML\n?\n#+END_HTML"
-     "<literal style=\"html\">\n?\n</literal>")
-    ("H" "#+HTML: " "<literal style=\"html\">?</literal>")
-    ("a" "#+BEGIN_ASCII\n?\n#+END_ASCII" "")
-    ("A" "#+ASCII: " "")
-    ("i" "#+INDEX: ?" "#+INDEX: ?")
-    ("I" "#+INCLUDE: %file ?"
-     "<include file=%file markup=\"?\">"))
+  '(("s" "#+BEGIN_SRC ?\n\n#+END_SRC")
+    ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE")
+    ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE")
+    ("v" "#+BEGIN_VERSE\n?\n#+END_VERSE")
+    ("V" "#+BEGIN_VERBATIM\n?\n#+END_VERBATIM")
+    ("c" "#+BEGIN_CENTER\n?\n#+END_CENTER")
+    ("l" "#+BEGIN_EXPORT latex\n?\n#+END_EXPORT")
+    ("L" "#+LaTeX: ")
+    ("h" "#+BEGIN_EXPORT html\n?\n#+END_EXPORT")
+    ("H" "#+HTML: ")
+    ("a" "#+BEGIN_EXPORT ascii\n?\n#+END_EXPORT")
+    ("A" "#+ASCII: ")
+    ("i" "#+INDEX: ?")
+    ("I" "#+INCLUDE: %file ?"))
   "Structure completion elements.
 This is a list of abbreviation keys and values.  The value gets inserted
 if you type `<' followed by the key and then press the completion key,
-usually `M-TAB'.  %file will be replaced by a file name after prompting
+usually `TAB'.  %file will be replaced by a file name after prompting
 for the file using completion.  The cursor will be placed at the position
 of the `?' in the template.
 There are two templates for each key, the first uses the original Org syntax,
@@ -12095,8 +12386,9 @@ variable `org-mtags-prefer-muse-templates'."
   :type '(repeat
          (list
           (string :tag "Key")
-          (string :tag "Template")
-          (string :tag "Muse Template"))))
+          (string :tag "Template")))
+  :version "26.1"
+  :package-version '(Org . "8.3"))
 
 (defun org-try-structure-completion ()
   "Try to complete a structure template before point.
@@ -12113,29 +12405,28 @@ expands them."
 
 (defun org-complete-expand-structure-template (start cell)
   "Expand a structure template."
-  (let* ((musep (org-bound-and-true-p org-mtags-prefer-muse-templates))
-        (rpl (nth (if musep 2 1) cell))
-        (ind ""))
+  (let ((rpl (nth 1 cell))
+       (ind ""))
     (delete-region start (point))
-    (when (string-match "\\`#\\+" rpl)
+    (when (string-match "\\`[ \t]*#\\+" rpl)
       (cond
        ((bolp))
        ((not (string-match "\\S-" (buffer-substring (point-at-bol) (point))))
        (setq ind (buffer-substring (point-at-bol) (point))))
        (t (newline))))
     (setq start (point))
-    (if (string-match "%file" rpl)
-       (setq rpl (replace-match
-                  (concat
-                   "\""
-                   (save-match-data
-                     (abbreviate-file-name (read-file-name "Include file: ")))
-                   "\"")
-                  t t rpl)))
+    (when (string-match "%file" rpl)
+      (setq rpl (replace-match
+                (concat
+                 "\""
+                 (save-match-data
+                   (abbreviate-file-name (read-file-name "Include file: ")))
+                 "\"")
+                t t rpl)))
     (setq rpl (mapconcat 'identity (split-string rpl "\n")
                         (concat "\n" ind)))
     (insert rpl)
-    (if (re-search-backward "\\?" start t) (delete-char 1))))
+    (when (re-search-backward "\\?" start t) (delete-char 1))))
 
 ;;;; TODO, DEADLINE, Comments
 
@@ -12144,17 +12435,18 @@ expands them."
   (interactive)
   (save-excursion
     (org-back-to-heading)
-    (let (case-fold-search)
-      (cond
-       ((looking-at (format org-heading-keyword-regexp-format
-                           org-comment-string))
-       (goto-char (match-end 1))
-       (looking-at (concat " +" org-comment-string))
-       (replace-match "" t t)
-       (when (eolp) (insert " ")))
-       ((looking-at org-outline-regexp)
-       (goto-char (match-end 0))
-       (insert org-comment-string " "))))))
+    (let ((case-fold-search nil))
+      (looking-at org-complex-heading-regexp))
+    (goto-char (or (match-end 3) (match-end 2) (match-end 1)))
+    (skip-chars-forward " \t")
+    (unless (memq (char-before) '(?\s ?\t)) (insert " "))
+    (if (org-in-commented-heading-p t)
+       (delete-region (point)
+                      (progn (search-forward " " (line-end-position) 'move)
+                             (skip-chars-forward " \t")
+                             (point)))
+      (insert org-comment-string)
+      (unless (eolp) (insert " ")))))
 
 (defvar org-last-todo-state-is-todo nil
   "This is non-nil when the last TODO state change led to a TODO state.
@@ -12193,43 +12485,65 @@ nil or a string to be used for the todo mark." )
   (interactive "P")
   (if (eq major-mode 'org-agenda-mode)
       (apply 'org-agenda-todo-yesterday arg)
-    (let* ((hour (third (decode-time
-                        (org-current-time))))
+    (let* ((org-use-effective-time t)
+          (hour (nth 2 (decode-time (org-current-time))))
           (org-extend-today-until (1+ hour)))
       (org-todo arg))))
 
 (defvar org-block-entry-blocking ""
   "First entry preventing the TODO state change.")
 
+(defun org-cancel-repeater ()
+  "Cancel a repeater by setting its numeric value to zero."
+  (interactive)
+  (save-excursion
+    (org-back-to-heading t)
+    (let ((bound1 (point))
+         (bound0 (save-excursion (outline-next-heading) (point))))
+      (when (and (re-search-forward
+                 (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
+                         org-deadline-time-regexp "\\)\\|\\("
+                         org-ts-regexp "\\)")
+                 bound0 t)
+                (re-search-backward "[ \t]+\\(?:[.+]\\)?\\+\\([0-9]+\\)[hdwmy]"
+                                    bound1 t))
+       (replace-match "0" t nil nil 1)))))
+
+(defvar org-state)
+(defvar org-blocked-by-checkboxes)
 (defun org-todo (&optional arg)
   "Change the TODO state of an item.
+
 The state of an item is given by a keyword at the start of the heading,
 like
      *** TODO Write paper
      *** DONE Call mom
 
 The different keywords are specified in the variable `org-todo-keywords'.
-By default the available states are \"TODO\" and \"DONE\".
-So for this example: when the item starts with TODO, it is changed to DONE.
+By default the available states are \"TODO\" and \"DONE\".  So, for this
+example: when the item starts with TODO, it is changed to DONE.
 When it starts with DONE, the DONE is removed.  And when neither TODO nor
 DONE are present, add TODO at the beginning of the heading.
 
-With \\[universal-argument] prefix arg, use completion to determine the new \
+With `\\[universal-argument]' prefix ARG, use completion to determine the new \
 state.
-With numeric prefix arg, switch to that state.
-With a double \\[universal-argument] prefix, switch to the next set of TODO \
+With numeric prefix ARG, switch to that state.
+With a `\\[universal-argument] \\[universal-argument]' prefix, switch to the \
+next set of TODO \
 keywords (nextset).
-With a triple \\[universal-argument] prefix, circumvent any state blocking.
+With a `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \
+prefix, circumvent any state blocking.
 With a numeric prefix arg of 0, inhibit note taking for the change.
-
-For calling through lisp, arg is also interpreted in the following way:
-`none'             -> empty state
-\"\" (empty string)  -> switch to empty state
-`done'             -> switch to DONE
-`nextset'          -> switch to the next set of keywords
-`previousset'      -> switch to the previous set of keywords
-\"WAITING\"          -> switch to the specified keyword, but only if it
-                      really is a member of `org-todo-keywords'."
+With a numeric prefix arg of -1, cancel repeater to allow marking as DONE.
+
+When called through ELisp, arg is also interpreted in the following way:
+`none'        -> empty state
+\"\"            -> switch to empty state
+`done'        -> switch to DONE
+`nextset'     -> switch to the next set of keywords
+`previousset' -> switch to the previous set of keywords
+\"WAITING\"     -> switch to the specified keyword, but only if it
+                 really is a member of `org-todo-keywords'."
   (interactive "P")
   (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
       (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
@@ -12238,8 +12552,9 @@ For calling through lisp, arg is also interpreted in 
the following way:
        (org-map-entries
         `(org-todo ,arg)
         org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
-    (if (equal arg '(16)) (setq arg 'nextset))
+        cl (when (org-invisible-p) (org-end-of-subtree nil t))))
+    (when (equal arg '(16)) (setq arg 'nextset))
+    (when (equal arg -1) (org-cancel-repeater) (setq arg nil))
     (let ((org-blocker-hook org-blocker-hook)
          commentp
          case-fold-search)
@@ -12252,10 +12567,10 @@ For calling through lisp, arg is also interpreted in 
the following way:
       (save-excursion
        (catch 'exit
          (org-back-to-heading t)
-         (when (looking-at (concat "^\\*+ " org-comment-string))
+         (when (org-in-commented-heading-p t)
            (org-toggle-comment)
            (setq commentp t))
-         (if (looking-at org-outline-regexp) (goto-char (1- (match-end 0))))
+         (when (looking-at org-outline-regexp) (goto-char (1- (match-end 0))))
          (or (looking-at (concat " +" org-todo-regexp "\\( +\\|[ \t]*$\\)"))
              (looking-at "\\(?: *\\|[ \t]*$\\)"))
          (let* ((match-data (match-data))
@@ -12285,31 +12600,30 @@ For calling through lisp, arg is also interpreted in 
the following way:
                                       (and (not arg) 
org-use-fast-todo-selection
                                            (not (eq org-use-fast-todo-selection
                                                     'prefix)))))
-                             ;; Use fast selection
+                             ;; Use fast selection.
                              (org-fast-todo-selection))
                             ((and (equal arg '(4))
                                   (or (not org-use-fast-todo-selection)
                                       (not org-todo-key-trigger)))
-                             ;; Read a state with completion
-                             (org-icompleting-read
-                              "State: " (mapcar 'list org-todo-keywords-1)
+                             ;; Read a state with completion.
+                             (completing-read
+                              "State: " (mapcar #'list org-todo-keywords-1)
                               nil t))
                             ((eq arg 'right)
                              (if this
                                  (if tail (car tail) nil)
                                (car org-todo-keywords-1)))
                             ((eq arg 'left)
-                             (if (equal member org-todo-keywords-1)
-                                 nil
+                             (unless (equal member org-todo-keywords-1)
                                (if this
                                    (nth (- (length org-todo-keywords-1)
                                            (length tail) 2)
                                         org-todo-keywords-1)
                                  (org-last org-todo-keywords-1))))
                             ((and (eq org-use-fast-todo-selection t) (equal 
arg '(4))
-                                  (setq arg nil))) ; hack to fall back to 
cycling
+                                  (setq arg nil))) ;hack to fall back to 
cycling
                             (arg
-                             ;; user or caller requests a specific state
+                             ;; User or caller requests a specific state.
                              (cond
                               ((equal arg "") nil)
                               ((eq arg 'none) nil)
@@ -12327,8 +12641,8 @@ For calling through lisp, arg is also interpreted in 
the following way:
                               ((nth (1- (prefix-numeric-value arg))
                                     org-todo-keywords-1))))
                             ((null member) (or head (car org-todo-keywords-1)))
-                            ((equal this final-done-word) nil) ;; -> make empty
-                            ((null tail) nil) ;; -> first entry
+                            ((equal this final-done-word) nil) ;-> make empty
+                            ((null tail) nil) ;-> first entry
                             ((memq interpret '(type priority))
                              (if (eq this-command last-command)
                                  (car tail)
@@ -12346,24 +12660,30 @@ For calling through lisp, arg is also interpreted in 
the following way:
                                     :position startpos))
                 dolog now-done-p)
            (when org-blocker-hook
-             (setq org-last-todo-state-is-todo
-                   (not (member this org-done-keywords)))
-             (unless (save-excursion
-                       (save-match-data
-                         (org-with-wide-buffer
-                          (run-hook-with-args-until-failure
-                           'org-blocker-hook change-plist))))
-               (if (org-called-interactively-p 'interactive)
-                   (user-error "TODO state change from %s to %s blocked (by 
\"%s\")"
-                               this org-state org-block-entry-blocking)
-                 ;; fail silently
-                 (message "TODO state change from %s to %s blocked (by \"%s\")"
-                          this org-state org-block-entry-blocking)
-                 (throw 'exit nil))))
+             (let (org-blocked-by-checkboxes block-reason)
+               (setq org-last-todo-state-is-todo
+                     (not (member this org-done-keywords)))
+               (unless (save-excursion
+                         (save-match-data
+                           (org-with-wide-buffer
+                            (run-hook-with-args-until-failure
+                             'org-blocker-hook change-plist))))
+                 (setq block-reason (if org-blocked-by-checkboxes
+                                        "contained checkboxes"
+                                      (format "\"%s\"" 
org-block-entry-blocking)))
+                 (if (called-interactively-p 'interactive)
+                     (user-error "TODO state change from %s to %s blocked (by 
%s)"
+                                 this org-state block-reason)
+                   ;; Fail silently.
+                   (message "TODO state change from %s to %s blocked (by %s)"
+                            this org-state block-reason)
+                   (throw 'exit nil)))))
            (store-match-data match-data)
            (replace-match next t t)
-           (unless (pos-visible-in-window-p hl-pos)
-             (message "TODO state changed to %s" (org-trim next)))
+           (cond ((equal this org-state)
+                  (message "TODO state was already %s" (org-trim next)))
+                 ((pos-visible-in-window-p hl-pos)
+                  (message "TODO state changed to %s" (org-trim next))))
            (unless head
              (setq head (org-get-todo-sequence-head org-state)
                    ass (assoc head org-todo-kwd-alist)
@@ -12384,11 +12704,11 @@ For calling through lisp, arg is also interpreted in 
the following way:
            (when (and (or org-todo-log-states org-log-done)
                       (not (eq org-inhibit-logging t))
                       (not (memq arg '(nextset previousset))))
-             ;; we need to look at recording a time and note
+             ;; We need to look at recording a time and note.
              (setq dolog (or (nth 1 (assoc org-state org-todo-log-states))
                              (nth 2 (assoc this org-todo-log-states))))
-             (if (and (eq dolog 'note) (eq org-inhibit-logging 'note))
-                 (setq dolog 'time))
+             (when (and (eq dolog 'note) (eq org-inhibit-logging 'note))
+               (setq dolog 'time))
              (when (or (and (not org-state) (not org-closed-keep-when-no-todo))
                        (and org-state
                             (member org-state org-not-done-keywords)
@@ -12397,21 +12717,21 @@ For calling through lisp, arg is also interpreted in 
the following way:
                ;; If there was a CLOSED time stamp, get rid of it.
                (org-add-planning-info nil nil 'closed))
              (when (and now-done-p org-log-done)
-               ;; It is now done, and it was not done before
+               ;; It is now done, and it was not done before.
                (org-add-planning-info 'closed (org-current-effective-time))
-               (if (and (not dolog) (eq 'note org-log-done))
-                   (org-add-log-setup 'done org-state this 'findpos 'note)))
+               (when (and (not dolog) (eq 'note org-log-done))
+                 (org-add-log-setup 'done org-state this 'note)))
              (when (and org-state dolog)
-               ;; This is a non-nil state, and we need to log it
-               (org-add-log-setup 'state org-state this 'findpos dolog)))
-           ;; Fixup tag positioning
+               ;; This is a non-nil state, and we need to log it.
+               (org-add-log-setup 'state org-state this dolog)))
+           ;; Fixup tag positioning.
            (org-todo-trigger-tag-changes org-state)
            (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil 
t))
            (when org-provide-todo-statistics
              (org-update-parent-todo-statistics))
            (run-hooks 'org-after-todo-state-change-hook)
-           (if (and arg (not (member org-state org-done-keywords)))
-               (setq head (org-get-todo-sequence-head org-state)))
+           (when (and arg (not (member org-state org-done-keywords)))
+             (setq head (org-get-todo-sequence-head org-state)))
            (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head 
head)
            ;; Do we need to trigger a repeat?
            (when now-done-p
@@ -12421,15 +12741,14 @@ For calling through lisp, arg is also interpreted in 
the following way:
                  (setq org-agenda-headline-snapshot-before-repeat
                        (org-get-heading))))
              (org-auto-repeat-maybe org-state))
-           ;; Fixup cursor location if close to the keyword
-           (if (and (outline-on-heading-p)
-                    (not (bolp))
-                    (save-excursion (beginning-of-line 1)
-                                    (looking-at org-todo-line-regexp))
-                    (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
-               (progn
-                 (goto-char (or (match-end 2) (match-end 1)))
-                 (and (looking-at " ") (just-one-space))))
+           ;; Fixup cursor location if close to the keyword.
+           (when (and (outline-on-heading-p)
+                      (not (bolp))
+                      (save-excursion (beginning-of-line 1)
+                                      (looking-at org-todo-line-regexp))
+                      (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
+             (goto-char (or (match-end 2) (match-end 1)))
+             (and (looking-at " ") (just-one-space)))
            (when org-trigger-hook
              (save-excursion
                (run-hook-with-args 'org-trigger-hook change-plist)))
@@ -12471,10 +12790,10 @@ changes.  Such blocking occurs when:
                        (> child-level this-level))
              ;; this todo has children, check whether they are all
              ;; completed
-             (if (and (not (org-entry-is-done-p))
-                      (org-entry-is-todo-p))
-                 (progn (setq org-block-entry-blocking (org-get-heading))
-                        (throw 'dont-block nil)))
+             (when (and (not (org-entry-is-done-p))
+                        (org-entry-is-todo-p))
+               (setq org-block-entry-blocking (org-get-heading))
+               (throw 'dont-block nil))
              (outline-next-heading)
              (setq child-level (funcall outline-level))))))
       ;; Otherwise, if the task's parent has the :ORDERED: property, and
@@ -12482,8 +12801,9 @@ changes.  Such blocking occurs when:
       (save-excursion
        (org-back-to-heading t)
        (let* ((pos (point))
-              (parent-pos (and (org-up-heading-safe) (point))))
-         (if (not parent-pos) (throw 'dont-block t)) ; no parent
+              (parent-pos (and (org-up-heading-safe) (point)))
+              (case-fold-search nil))
+         (unless parent-pos (throw 'dont-block t)) ; no parent
          (when (and (org-not-nil (org-entry-get (point) "ORDERED"))
                     (forward-line 1)
                     (re-search-forward org-not-done-heading-regexp pos t))
@@ -12492,11 +12812,11 @@ changes.  Such blocking occurs when:
          ;; Search further up the hierarchy, to see if an ancestor is blocked
          (while t
            (goto-char parent-pos)
-           (if (not (looking-at org-not-done-heading-regexp))
-               (throw 'dont-block t))  ; do not block, parent is not a TODO
+           (unless (looking-at org-not-done-heading-regexp)
+             (throw 'dont-block t))    ; do not block, parent is not a TODO
            (setq pos (point))
            (setq parent-pos (and (org-up-heading-safe) (point)))
-           (if (not parent-pos) (throw 'dont-block t)) ; no parent
+           (unless parent-pos (throw 'dont-block t)) ; no parent
            (when (and (org-not-nil (org-entry-get (point) "ORDERED"))
                       (forward-line 1)
                       (re-search-forward org-not-done-heading-regexp pos t)
@@ -12533,14 +12853,13 @@ See variable `org-track-ordered-property-with-tag'."
       (org-back-to-heading)
       (if (org-entry-get nil "ORDERED")
          (progn
-           (org-delete-property "ORDERED" "PROPERTIES")
+           (org-delete-property "ORDERED")
            (and tag (org-toggle-tag tag 'off))
            (message "Subtasks can be completed in arbitrary order"))
        (org-entry-put nil "ORDERED" "t")
        (and tag (org-toggle-tag tag 'on))
        (message "Subtasks must be completed in sequence")))))
 
-(defvar org-blocked-by-checkboxes) ; dynamically scoped
 (defun org-block-todo-from-checkboxes (change-plist)
   "Block turning an entry into a TODO, using checkboxes.
 This checks whether the current task should be blocked from state
@@ -12564,32 +12883,32 @@ changes because there are unchecked boxes in this 
entry."
          (outline-next-heading)
          (setq end (point))
          (goto-char beg)
-         (if (org-list-search-forward
-              (concat (org-item-beginning-re)
-                      
"\\(?:address@hidden(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?"
-                      "\\[[- ]\\]")
-              end t)
-             (progn
-               (if (boundp 'org-blocked-by-checkboxes)
-                   (setq org-blocked-by-checkboxes t))
-               (throw 'dont-block nil)))))
+         (when (org-list-search-forward
+                (concat (org-item-beginning-re)
+                        
"\\(?:address@hidden(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?"
+                        "\\[[- ]\\]")
+                end t)
+           (when (boundp 'org-blocked-by-checkboxes)
+             (setq org-blocked-by-checkboxes t))
+           (throw 'dont-block nil))))
       t))) ; do not block
 
 (defun org-entry-blocked-p ()
-  "Is the current entry blocked?"
-  (org-with-silent-modifications
-   (if (org-entry-get nil "NOBLOCKING")
-       nil ;; Never block this entry
-     (not (run-hook-with-args-until-failure
-          'org-blocker-hook
-          (list :type 'todo-state-change
-                :position (point)
-                :from 'todo
-                :to 'done))))))
+  "Non-nil if entry at point is blocked."
+  (and (not (org-entry-get nil "NOBLOCKING"))
+       (member (org-entry-get nil "TODO") org-not-done-keywords)
+       (not (run-hook-with-args-until-failure
+            'org-blocker-hook
+            (list :type 'todo-state-change
+                  :position (point)
+                  :from 'todo
+                  :to 'done)))))
 
 (defun org-update-statistics-cookies (all)
   "Update the statistics cookie, either from TODO or from checkboxes.
-This should be called with the cursor in a line with a statistics cookie."
+This should be called with the cursor in a line with a statistics
+cookie.  When called with a \\[universal-argument] prefix, update
+all statistics cookies in the buffer."
   (interactive "P")
   (if all
       (progn
@@ -12605,7 +12924,7 @@ This should be called with the cursor in a line with a 
statistics cookie."
          (setq l1 (org-outline-level))
          (setq end (save-excursion
                      (outline-next-heading)
-                     (if (org-at-heading-p) (setq l2 (org-outline-level)))
+                     (when (org-at-heading-p) (setq l2 (org-outline-level)))
                      (point)))
          (if (and (save-excursion
                     (re-search-forward
@@ -12642,7 +12961,7 @@ statistics everywhere."
         (box-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
         level ltoggle l1 new ndel
         (cnt-all 0) (cnt-done 0) is-percent kwd
-        checkbox-beg ov ovs ove cookie-present)
+        checkbox-beg cookie-present)
     (catch 'exit
       (save-excursion
        (beginning-of-line 1)
@@ -12677,14 +12996,31 @@ statistics everywhere."
                (setq kwd (and (or recursive (= l1 ltoggle))
                               (match-string 2)))
                (if (or (eq org-provide-todo-statistics 'all-headlines)
+                       (and (eq org-provide-todo-statistics t)
+                            (or (member kwd org-done-keywords)))
                        (and (listp org-provide-todo-statistics)
+                            (stringp (car org-provide-todo-statistics))
                             (or (member kwd org-provide-todo-statistics)
-                                (member kwd org-done-keywords))))
+                                (member kwd org-done-keywords)))
+                       (and (listp org-provide-todo-statistics)
+                            (listp (car org-provide-todo-statistics))
+                            (or (member kwd (car org-provide-todo-statistics))
+                                (and (member kwd org-done-keywords)
+                                     (member kwd (cadr 
org-provide-todo-statistics))))))
                    (setq cnt-all (1+ cnt-all))
-                 (if (eq org-provide-todo-statistics t)
-                     (and kwd (setq cnt-all (1+ cnt-all)))))
-               (and (member kwd org-done-keywords)
-                    (setq cnt-done (1+ cnt-done)))
+                 (and (eq org-provide-todo-statistics t)
+                      kwd
+                      (setq cnt-all (1+ cnt-all))))
+               (when (or (and (member org-provide-todo-statistics '(t 
all-headlines))
+                              (member kwd org-done-keywords))
+                         (and (listp org-provide-todo-statistics)
+                              (listp (car org-provide-todo-statistics))
+                              (member kwd org-done-keywords)
+                              (member kwd (cadr org-provide-todo-statistics)))
+                         (and (listp org-provide-todo-statistics)
+                              (stringp (car org-provide-todo-statistics))
+                              (member kwd org-done-keywords)))
+                 (setq cnt-done (1+ cnt-done)))
                (outline-next-heading)))
            (setq new
                  (if is-percent
@@ -12692,15 +13028,10 @@ statistics everywhere."
                                              (max 1 cnt-all)))
                    (format "[%d/%d]" cnt-done cnt-all))
                  ndel (- (match-end 0) checkbox-beg))
-           ;; handle overlays when updating cookie from column view
-           (when (setq ov (car (overlays-at checkbox-beg)))
-             (setq ovs (overlay-start ov) ove (overlay-end ov))
-             (delete-overlay ov))
            (goto-char checkbox-beg)
            (insert new)
            (delete-region (point) (+ (point) ndel))
-           (when org-auto-align-tags (org-fix-tags-on-the-fly))
-           (when ov (move-overlay ov ovs ove)))
+           (when org-auto-align-tags (org-fix-tags-on-the-fly)))
          (when cookie-present
            (run-hook-with-args 'org-after-todo-statistics-hook
                                cnt-done (- cnt-all cnt-done))))))
@@ -12736,9 +13067,9 @@ This hook runs even if there is no statistics cookie 
present, in which case
     (when (and (stringp state) (> (length state) 0))
       (setq changes (append changes (cdr (assoc state l)))))
     (when (member state org-not-done-keywords)
-      (setq changes (append changes (cdr (assoc 'todo l)))))
+      (setq changes (append changes (cdr (assq 'todo l)))))
     (when (member state org-done-keywords)
-      (setq changes (append changes (cdr (assoc 'done l)))))
+      (setq changes (append changes (cdr (assq 'done l)))))
     (dolist (c changes)
       (org-toggle-tag (car c) (if (cdr c) 'on 'off)))))
 
@@ -12749,7 +13080,7 @@ This hook runs even if there is no statistics cookie 
present, in which case
         org-log-repeat nil
         org-todo-log-states nil)
   (dolist (w (org-split-string value))
-    (let* (a)
+    (let (a)
       (cond
        ((setq a (assoc w org-startup-options))
         (and (member (nth 1 a) '(org-log-done org-log-repeat))
@@ -12786,7 +13117,7 @@ Returns the new TODO keyword, or nil if no state change 
should occur."
         (expert nil)
         (fwidth (+ maxlen 3 1 3))
         (ncol (/ (- (window-width) 4) fwidth))
-        tg cnt c tbl
+        tg cnt e c tbl
         groups ingroup)
     (save-excursion
       (save-window-excursion
@@ -12794,13 +13125,13 @@ Returns the new TODO keyword, or nil if no state 
change should occur."
            (set-buffer (get-buffer-create " *Org todo*"))
          (org-switch-to-buffer-other-window (get-buffer-create " *Org todo*")))
        (erase-buffer)
-       (org-set-local 'org-done-keywords done-keywords)
+       (setq-local org-done-keywords done-keywords)
        (setq tbl fulltable cnt 0)
-       (dolist (e tbl)
+       (while (setq e (pop tbl))
          (cond
           ((equal e '(:startgroup))
            (push '() groups) (setq ingroup t)
-           (when (not (= cnt 0))
+           (unless (= cnt 0)
              (setq cnt 0)
              (insert "\n"))
            (insert "{ "))
@@ -12808,7 +13139,7 @@ Returns the new TODO keyword, or nil if no state change 
should occur."
            (setq ingroup nil cnt 0)
            (insert "}\n"))
           ((equal e '(:newline))
-           (when (not (= cnt 0))
+           (unless (= cnt 0)
              (setq cnt 0)
              (insert "\n")
              (setq e (car tbl))
@@ -12817,19 +13148,19 @@ Returns the new TODO keyword, or nil if no state 
change should occur."
                (setq tbl (cdr tbl)))))
           (t
            (setq tg (car e) c (cdr e))
-           (if ingroup (push tg (car groups)))
+           (when ingroup (push tg (car groups)))
            (setq tg (org-add-props tg nil 'face
                                    (org-get-todo-face tg)))
-           (if (and (= cnt 0) (not ingroup)) (insert "  "))
+           (when (and (= cnt 0) (not ingroup)) (insert "  "))
            (insert "[" c "] " tg (make-string
                                   (- fwidth 4 (length tg)) ?\ ))
            (when (= (setq cnt (1+ cnt)) ncol)
              (insert "\n")
-             (if ingroup (insert "  "))
+             (when ingroup (insert "  "))
              (setq cnt 0)))))
        (insert "\n")
        (goto-char (point-min))
-       (if (not expert) (org-fit-window-to-buffer))
+       (unless expert (org-fit-window-to-buffer))
        (message "[a-z..]:Set [SPC]:clear")
        (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
        (cond
@@ -12851,12 +13182,19 @@ Returns the new TODO keyword, or nil if no state 
change should occur."
   "Return the TODO keyword of the current subtree."
   (save-excursion
     (org-back-to-heading t)
-    (and (looking-at org-todo-line-regexp)
+    (and (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))
         (match-end 2)
         (match-string 2))))
 
 (defun org-at-date-range-p (&optional inactive-ok)
-  "Is the cursor inside a date range?"
+  "Non-nil if point is inside a date range.
+
+When optional argument INACTIVE-OK is non-nil, also consider
+inactive time ranges.
+
+When this function returns a non-nil value, match data is set
+according to `org-tr-regexp-both' or `org-tr-regexp', depending
+on INACTIVE-OK."
   (interactive)
   (save-excursion
     (catch 'exit
@@ -12888,14 +13226,15 @@ Returns the new TODO keyword, or nil if no state 
change should occur."
 (defvar org-last-inserted-timestamp)
 (defvar org-log-post-message)
 (defvar org-log-note-purpose)
-(defvar org-log-note-how)
+(defvar org-log-note-how nil)
 (defvar org-log-note-extra)
 (defun org-auto-repeat-maybe (done-word)
-  "Check if the current headline contains a repeated deadline/schedule.
+  "Check if the current headline contains a repeated time-stamp.
+
 If yes, set TODO state back to what it was and change the base date
 of repeating deadline/scheduled time stamps to new date.
+
 This function is run automatically after each state change to a DONE state."
-  ;; last-state is dynamically scoped into this function
   (let* ((repeat (org-get-repeat))
         (aa (assoc org-last-state org-todo-kwd-alist))
         (interpret (nth 1 aa))
@@ -12903,73 +13242,108 @@ This function is run automatically after each state 
change to a DONE state."
         (whata '(("h" . hour) ("d" . day) ("m" . month) ("y" . year)))
         (msg "Entry repeats: ")
         (org-log-done nil)
-        (org-todo-log-states nil)
-        re type n what ts time to-state)
-    (when repeat
-      (if (eq org-log-repeat t) (setq org-log-repeat 'state))
-      (setq to-state (or (org-entry-get nil "REPEAT_TO_STATE")
-                        org-todo-repeat-to-state))
-      (unless (and to-state (member to-state org-todo-keywords-1))
-       (setq to-state (if (eq interpret 'type) org-last-state head)))
-      (org-todo to-state)
+        (org-todo-log-states nil))
+    (when (and repeat (not (zerop (string-to-number (substring repeat 1)))))
+      (when (eq org-log-repeat t) (setq org-log-repeat 'state))
+      (let ((to-state (or (org-entry-get nil "REPEAT_TO_STATE" 'selective)
+                         org-todo-repeat-to-state)))
+       (org-todo (cond ((and to-state (member to-state org-todo-keywords-1))
+                        to-state)
+                       ((eq interpret 'type) org-last-state)
+                       (head)
+                       (t 'none))))
       (when (or org-log-repeat (org-entry-get nil "CLOCK"))
        (org-entry-put nil "LAST_REPEAT" (format-time-string
                                          (org-time-stamp-format t t))))
       (when org-log-repeat
        (if (or (memq 'org-add-log-note (default-value 'post-command-hook))
                (memq 'org-add-log-note post-command-hook))
-           ;; OK, we are already setup for some record
-           (if (eq org-log-repeat 'note)
-               ;; make sure we take a note, not only a time stamp
-               (setq org-log-note-how 'note))
-         ;; Set up for taking a record
-         (org-add-log-setup 'state (or done-word (car org-done-keywords))
+           ;; We are already setup for some record.
+           (when (eq org-log-repeat 'note)
+             ;; Make sure we take a note, not only a time stamp.
+             (setq org-log-note-how 'note))
+         ;; Set up for taking a record.
+         (org-add-log-setup 'state
+                            (or done-word (car org-done-keywords))
                             org-last-state
-                            'findpos org-log-repeat)))
+                            org-log-repeat)))
       (org-back-to-heading t)
       (org-add-planning-info nil nil 'closed)
-      (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
-                      org-deadline-time-regexp "\\)\\|\\("
-                      org-ts-regexp "\\)"))
-      (while (re-search-forward
-             re (save-excursion (outline-next-heading) (point)) t)
-       (setq type (if (match-end 1) org-scheduled-string
-                    (if (match-end 3) org-deadline-string "Plain:"))
-             ts (match-string (if (match-end 2) 2 (if (match-end 4) 4 0))))
-       (when (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts)
-         (setq n (string-to-number (match-string 2 ts))
-               what (match-string 3 ts))
-         (if (equal what "w") (setq n (* n 7) what "d"))
-         (if (and (equal what "h") (not (string-match 
"[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts)))
-             (user-error "Cannot repeat in Repeat in %d hour(s) because no 
hour has been set" n))
-         ;; Preparation, see if we need to modify the start date for the change
-         (when (match-end 1)
-           (setq time (save-match-data (org-time-string-to-time ts)))
+      (let ((end (save-excursion (outline-next-heading) (point)))
+           (planning-re (regexp-opt
+                         (list org-scheduled-string org-deadline-string))))
+       (while (re-search-forward org-ts-regexp end t)
+         (let* ((ts (match-string 0))
+                (planning? (org-at-planning-p))
+                (type (if (not planning?) "Plain:"
+                        (save-excursion
+                          (re-search-backward
+                           planning-re (line-beginning-position) t)
+                          (match-string 0)))))
            (cond
-            ((equal (match-string 1 ts) ".")
-             ;; Shift starting date to today
-             (org-timestamp-change
-              (- (org-today) (time-to-days time))
-              'day))
-            ((equal (match-string 1 ts) "+")
-             (let ((nshiftmax 10) (nshift 0))
-               (while (or (= nshift 0)
-                          (<= (time-to-days time)
-                              (time-to-days (current-time))))
-                 (when (= (incf nshift) nshiftmax)
-                   (or (y-or-n-p (message "%d repeater intervals were not 
enough to shift date past today.  Continue? " nshift))
-                       (error "Abort")))
-                 (org-timestamp-change n (cdr (assoc what whata)))
-                 (org-at-timestamp-p t)
-                 (setq ts (match-string 1))
-                 (setq time (save-match-data (org-time-string-to-time ts)))))
-             (org-timestamp-change (- n) (cdr (assoc what whata)))
-             ;; rematch, so that we have everything in place for the real shift
-             (org-at-timestamp-p t)
-             (setq ts (match-string 1))
-             (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts))))
-         (save-excursion (org-timestamp-change n (cdr (assoc what whata)) nil 
t))
-         (setq msg (concat msg type " " org-last-changed-timestamp " "))))
+            ;; Ignore fake time-stamps (e.g., within comments).
+            ((and (not planning?)
+                  (not (org-at-property-p))
+                  (not (eq 'timestamp
+                           (org-element-type (save-excursion
+                                               (backward-char)
+                                               (org-element-context)))))))
+            ;; Time-stamps without a repeater are usually skipped.
+            ;; However, a SCHEDULED time-stamp without one is
+            ;; removed, as it is considered as no longer relevant.
+            ((not (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts))
+             (when (equal type org-scheduled-string)
+               (org-remove-timestamp-with-keyword type)))
+            (t
+             (let ((n (string-to-number (match-string 2 ts)))
+                   (what (match-string 3 ts)))
+               (when (equal what "w") (setq n (* n 7) what "d"))
+               (when (and (equal what "h")
+                          (not (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}"
+                                               ts)))
+                 (user-error
+                  "Cannot repeat in Repeat in %d hour(s) because no hour \
+has been set"
+                  n))
+               ;; Preparation, see if we need to modify the start
+               ;; date for the change.
+               (when (match-end 1)
+                 (let ((time (save-match-data (org-time-string-to-time ts))))
+                   (cond
+                    ((equal (match-string 1 ts) ".")
+                     ;; Shift starting date to today
+                     (org-timestamp-change
+                      (- (org-today) (time-to-days time))
+                      'day))
+                    ((equal (match-string 1 ts) "+")
+                     (let ((nshiftmax 10)
+                           (nshift 0))
+                       (while (or (= nshift 0)
+                                  (not (time-less-p (current-time) time)))
+                         (when (= (cl-incf nshift) nshiftmax)
+                           (or (y-or-n-p
+                                (format "%d repeater intervals were not \
+enough to shift date past today.  Continue? "
+                                        nshift))
+                               (user-error "Abort")))
+                         (org-timestamp-change n (cdr (assoc what whata)))
+                         (org-at-timestamp-p t)
+                         (setq ts (match-string 1))
+                         (setq time
+                               (save-match-data
+                                 (org-time-string-to-time ts)))))
+                     (org-timestamp-change (- n) (cdr (assoc what whata)))
+                     ;; Rematch, so that we have everything in place
+                     ;; for the real shift.
+                     (org-at-timestamp-p t)
+                     (setq ts (match-string 1))
+                     (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)"
+                                   ts)))))
+               (save-excursion
+                 (org-timestamp-change n (cdr (assoc what whata)) nil t))
+               (setq msg
+                     (concat
+                      msg type " " org-last-changed-timestamp " "))))))))
       (setq org-log-post-message msg)
       (message "%s" msg))))
 
@@ -12977,7 +13351,7 @@ This function is run automatically after each state 
change to a DONE state."
   "Make a compact tree which shows all headlines marked with TODO.
 The tree will show the lines where the regexp matches, and all higher
 headlines above the match.
-With a \\[universal-argument] prefix, prompt for a regexp to match.
+With a `\\[universal-argument]' prefix, prompt for a regexp to match.
 With a numeric prefix N, construct a sparse tree for the Nth element
 of `org-todo-keywords-1'."
   (interactive "P")
@@ -12985,8 +13359,9 @@ of `org-todo-keywords-1'."
        (kwd-re
         (cond ((null arg) org-not-done-regexp)
               ((equal arg '(4))
-               (let ((kwd (org-icompleting-read "Keyword (or KWD1|KWD2|...): "
-                                                (mapcar 'list 
org-todo-keywords-1))))
+               (let ((kwd
+                      (completing-read "Keyword (or KWD1|KWD2|...): "
+                                       (mapcar #'list org-todo-keywords-1))))
                  (concat "\\("
                          (mapconcat 'identity (org-split-string kwd "|") "\\|")
                          "\\)\\>")))
@@ -12997,75 +13372,99 @@ of `org-todo-keywords-1'."
     (message "%d TODO entries found"
             (org-occur (concat "^" org-outline-regexp " *" kwd-re )))))
 
+(defun org--deadline-or-schedule (arg type time)
+  "Insert DEADLINE or SCHEDULE information in current entry.
+TYPE is either `deadline' or `scheduled'.  See `org-deadline' or
+`org-schedule' for information about ARG and TIME arguments."
+  (let* ((deadline? (eq type 'deadline))
+        (keyword (if deadline? org-deadline-string org-scheduled-string))
+        (log (if deadline? org-log-redeadline org-log-reschedule))
+        (old-date (org-entry-get nil (if deadline? "DEADLINE" "SCHEDULED")))
+        (old-date-time (and old-date (org-time-string-to-time old-date)))
+        ;; Save repeater cookie from either TIME or current scheduled
+        ;; time stamp.  We are going to insert it back at the end of
+        ;; the process.
+        (repeater (or (and (org-string-nw-p time)
+                           ;; We use `org-repeat-re' because we need
+                           ;; to tell the difference between a real
+                           ;; repeater and a time delta, e.g. "+2d".
+                           (string-match org-repeat-re time)
+                           (match-string 1 time))
+                      (and (org-string-nw-p old-date)
+                           (string-match "\\([.+-]+[0-9]+[hdwmy]\
+\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\)"
+                                         old-date)
+                           (match-string 1 old-date)))))
+    (pcase arg
+      (`(4)
+       (when (and old-date log)
+        (org-add-log-setup (if deadline? 'deldeadline 'delschedule)
+                           nil old-date log))
+       (org-remove-timestamp-with-keyword keyword)
+       (message (if deadline? "Item no longer has a deadline."
+                 "Item is no longer scheduled.")))
+      (`(16)
+       (save-excursion
+        (org-back-to-heading t)
+        (let ((regexp (if deadline? org-deadline-time-regexp
+                        org-scheduled-time-regexp)))
+          (if (not (re-search-forward regexp (line-end-position 2) t))
+              (user-error (if deadline? "No deadline information to update"
+                            "No scheduled information to update"))
+            (let* ((rpl0 (match-string 1))
+                   (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0))
+                   (msg (if deadline? "Warn starting from" "Delay until")))
+              (replace-match
+               (concat keyword
+                       " <" rpl
+                       (format " -%dd"
+                               (abs (- (time-to-days
+                                        (save-match-data
+                                          (org-read-date
+                                           nil t nil msg old-date-time)))
+                                       (time-to-days old-date-time))))
+                       ">") t t))))))
+      (_
+       (org-add-planning-info type time 'closed)
+       (when (and old-date
+                 log
+                 (not (equal old-date org-last-inserted-timestamp)))
+        (org-add-log-setup (if deadline? 'redeadline 'reschedule)
+                           org-last-inserted-timestamp
+                           old-date
+                           log))
+       (when repeater
+        (save-excursion
+          (org-back-to-heading t)
+          (when (re-search-forward
+                 (concat keyword " " org-last-inserted-timestamp)
+                 (line-end-position 2)
+                 t)
+            (goto-char (1- (match-end 0)))
+            (insert " " repeater)
+            (setq org-last-inserted-timestamp
+                  (concat (substring org-last-inserted-timestamp 0 -1)
+                          " " repeater
+                          (substring org-last-inserted-timestamp -1))))))
+       (message (if deadline? "Deadline on %s" "Scheduled to %s")
+               org-last-inserted-timestamp)))))
+
 (defun org-deadline (arg &optional time)
   "Insert the \"DEADLINE:\" string with a timestamp to make a deadline.
 With one universal prefix argument, remove any deadline from the item.
 With two universal prefix arguments, prompt for a warning delay.
 With argument TIME, set the deadline at the corresponding date.  TIME
-can either be an Org date like \"2011-07-24\" or a delta like \"+2d\"."
-  (interactive "P")
-  (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
-      (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
-                   'region-start-level 'region))
-           org-loop-over-headlines-in-active-region)
-       (org-map-entries
-        `(org-deadline ',arg ,time)
-        org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
-    (let* ((old-date (org-entry-get nil "DEADLINE"))
-          (old-date-time (if old-date (org-time-string-to-time old-date)))
-          (repeater (and old-date
-                         (string-match
-                          "\\([.+-]+[0-9]+[hdwmy]\\(?:[/ 
][-+]?[0-9]+[hdwmy]\\)?\\) ?"
-                          old-date)
-                         (match-string 1 old-date))))
-      (cond
-       ((equal arg '(4))
-       (when (and old-date org-log-redeadline)
-         (org-add-log-setup 'deldeadline nil old-date 'findpos
-                            org-log-redeadline))
-       (org-remove-timestamp-with-keyword org-deadline-string)
-       (message "Item no longer has a deadline."))
-       ((equal arg '(16))
-       (save-excursion
-         (org-back-to-heading t)
-         (if (re-search-forward
-              org-deadline-time-regexp
-              (save-excursion (outline-next-heading) (point)) t)
-             (let* ((rpl0 (match-string 1))
-                    (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0)))
-               (replace-match
-                (concat org-deadline-string
-                        " <" rpl
-                        (format " -%dd"
-                                (abs
-                                 (- (time-to-days
-                                     (save-match-data
-                                       (org-read-date nil t nil "Warn starting 
from" old-date-time)))
-                                    (time-to-days old-date-time))))
-                        ">") t t))
-           (user-error "No deadline information to update"))))
-       (t
-       (org-add-planning-info 'deadline time 'closed)
-       (when (and old-date org-log-redeadline
-                  (not (equal old-date
-                              (substring org-last-inserted-timestamp 1 -1))))
-         (org-add-log-setup 'redeadline nil old-date 'findpos
-                            org-log-redeadline))
-       (when repeater
-         (save-excursion
-           (org-back-to-heading t)
-           (when (re-search-forward (concat org-deadline-string " "
-                                            org-last-inserted-timestamp)
-                                    (save-excursion
-                                      (outline-next-heading) (point)) t)
-             (goto-char (1- (match-end 0)))
-             (insert " " repeater)
-             (setq org-last-inserted-timestamp
-                   (concat (substring org-last-inserted-timestamp 0 -1)
-                           " " repeater
-                           (substring org-last-inserted-timestamp -1))))))
-       (message "Deadline on %s" org-last-inserted-timestamp))))))
+can either be an Org date like \"2011-07-24\" or a delta like \"+2d\"."
+  (interactive "P")
+  (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
+      (org-map-entries
+       (lambda () (org--deadline-or-schedule arg 'deadline time))
+       nil
+       (if (eq org-loop-over-headlines-in-active-region 'start-level)
+          'region-start-level
+        'region)
+       (lambda () (when (org-invisible-p) (org-end-of-subtree nil t))))
+    (org--deadline-or-schedule arg 'deadline time)))
 
 (defun org-schedule (arg &optional time)
   "Insert the SCHEDULED: string with a timestamp to schedule a TODO item.
@@ -13075,68 +13474,14 @@ With argument TIME, scheduled at the corresponding 
date.  TIME can
 either be an Org date like \"2011-07-24\" or a delta like \"+2d\"."
   (interactive "P")
   (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
-      (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
-                   'region-start-level 'region))
-           org-loop-over-headlines-in-active-region)
-       (org-map-entries
-        `(org-schedule ',arg ,time)
-        org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
-    (let* ((old-date (org-entry-get nil "SCHEDULED"))
-          (old-date-time (if old-date (org-time-string-to-time old-date)))
-          (repeater (and old-date
-                         (string-match
-                          "\\([.+-]+[0-9]+[hdwmy]\\(?:[/ 
][-+]?[0-9]+[hdwmy]\\)?\\) ?"
-                          old-date)
-                         (match-string 1 old-date))))
-      (cond
-       ((equal arg '(4))
-       (progn
-         (when (and old-date org-log-reschedule)
-           (org-add-log-setup 'delschedule nil old-date 'findpos
-                              org-log-reschedule))
-         (org-remove-timestamp-with-keyword org-scheduled-string)
-         (message "Item is no longer scheduled.")))
-       ((equal arg '(16))
-       (save-excursion
-         (org-back-to-heading t)
-         (if (re-search-forward
-              org-scheduled-time-regexp
-              (save-excursion (outline-next-heading) (point)) t)
-             (let* ((rpl0 (match-string 1))
-                    (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0)))
-               (replace-match
-                (concat org-scheduled-string
-                        " <" rpl
-                        (format " -%dd"
-                                (abs
-                                 (- (time-to-days
-                                     (save-match-data
-                                       (org-read-date nil t nil "Delay until" 
old-date-time)))
-                                    (time-to-days old-date-time))))
-                        ">") t t))
-           (user-error "No scheduled information to update"))))
-       (t
-       (org-add-planning-info 'scheduled time 'closed)
-       (when (and old-date org-log-reschedule
-                  (not (equal old-date
-                              (substring org-last-inserted-timestamp 1 -1))))
-         (org-add-log-setup 'reschedule nil old-date 'findpos
-                            org-log-reschedule))
-       (when repeater
-         (save-excursion
-           (org-back-to-heading t)
-           (when (re-search-forward (concat org-scheduled-string " "
-                                            org-last-inserted-timestamp)
-                                    (save-excursion
-                                      (outline-next-heading) (point)) t)
-             (goto-char (1- (match-end 0)))
-             (insert " " repeater)
-             (setq org-last-inserted-timestamp
-                   (concat (substring org-last-inserted-timestamp 0 -1)
-                           " " repeater
-                           (substring org-last-inserted-timestamp -1))))))
-       (message "Scheduled to %s" org-last-inserted-timestamp))))))
+      (org-map-entries
+       (lambda () (org--deadline-or-schedule arg 'scheduled time))
+       nil
+       (if (eq org-loop-over-headlines-in-active-region 'start-level)
+          'region-start-level
+        'region)
+       (lambda () (when (org-invisible-p) (org-end-of-subtree nil t))))
+    (org--deadline-or-schedule arg 'scheduled time)))
 
 (defun org-get-scheduled-time (pom &optional inherit)
   "Get the scheduled time as a time tuple, of a format suitable
@@ -13167,24 +13512,36 @@ nil."
        (if (and (string-match "\\S-" (buffer-substring (point-at-bol) (point)))
                 (equal (char-before) ?\ ))
            (backward-delete-char 1)
-         (if (string-match "^[ \t]*$" (buffer-substring
-                                       (point-at-bol) (point-at-eol)))
-             (delete-region (point-at-bol)
-                            (min (point-max) (1+ (point-at-eol))))))))))
+         (when (string-match "^[ \t]*$" (buffer-substring
+                                         (point-at-bol) (point-at-eol)))
+           (delete-region (point-at-bol)
+                          (min (point-max) (1+ (point-at-eol))))))))))
 
 (defvar org-time-was-given) ; dynamically scoped parameter
 (defvar org-end-time-was-given) ; dynamically scoped parameter
 
-(defun org-add-planning-info (what &optional time &rest remove)
-  "Insert new timestamp with keyword in the line directly after the headline.
-WHAT indicates what kind of time stamp to add.  TIME indicates the time to use.
-If non is given, the user is prompted for a date.
-REMOVE indicates what kind of entries to remove.  An old WHAT entry will also
-be removed."
-  (interactive)
-  (let (org-time-was-given org-end-time-was-given ts
-                          end default-time default-input)
+(defun org-at-planning-p ()
+  "Non-nil when point is on a planning info line."
+  ;; This is as accurate and faster than `org-element-at-point' since
+  ;; planning info location is fixed in the section.
+  (org-with-wide-buffer
+   (beginning-of-line)
+   (and (looking-at-p org-planning-line-re)
+       (eq (point)
+           (ignore-errors
+             (if (and (featurep 'org-inlinetask) (org-inlinetask-in-task-p))
+                 (org-back-to-heading t)
+               (org-with-limited-levels (org-back-to-heading t)))
+             (line-beginning-position 2))))))
 
+(defun org-add-planning-info (what &optional time &rest remove)
+  "Insert new timestamp with keyword in the planning line.
+WHAT indicates what kind of time stamp to add.  It is a symbol
+among `closed', `deadline', `scheduled' and nil.  TIME indicates
+the time to use.  If none is given, the user is prompted for
+a date.  REMOVE indicates what kind of entries to remove.  An old
+WHAT entry will also be removed."
+  (let (org-time-was-given org-end-time-was-given default-time default-input)
     (catch 'exit
       (when (and (memq what '(scheduled deadline))
                 (or (not time)
@@ -13193,108 +13550,98 @@ be removed."
        ;; Try to get a default date/time from existing timestamp
        (save-excursion
          (org-back-to-heading t)
-         (setq end (save-excursion (outline-next-heading) (point)))
-         (when (re-search-forward (if (eq what 'scheduled)
-                                      org-scheduled-time-regexp
-                                    org-deadline-time-regexp)
-                                  end t)
-           (setq ts (match-string 1)
-                 default-time
-                 (apply 'encode-time (org-parse-time-string ts))
-                 default-input (and ts (org-get-compact-tod ts))))))
+         (let ((end (save-excursion (outline-next-heading) (point))) ts)
+           (when (re-search-forward (if (eq what 'scheduled)
+                                        org-scheduled-time-regexp
+                                      org-deadline-time-regexp)
+                                    end t)
+             (setq ts (match-string 1)
+                   default-time (apply 'encode-time (org-parse-time-string ts))
+                   default-input (and ts (org-get-compact-tod ts)))))))
       (when what
        (setq time
              (if (stringp time)
-                 ;; This is a string (relative or absolute), set proper date
-                 (apply 'encode-time
+                 ;; This is a string (relative or absolute), set
+                 ;; proper date.
+                 (apply #'encode-time
                         (org-read-date-analyze
                          time default-time (decode-time default-time)))
                ;; If necessary, get the time from the user
                (or time (org-read-date nil 'to-time nil nil
                                        default-time default-input)))))
 
-      (when (and org-insert-labeled-timestamps-at-point
-                (member what '(scheduled deadline)))
-       (insert
-        (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
-       (org-insert-time-stamp time org-time-was-given
-                              nil nil nil (list org-end-time-was-given))
-       (setq what nil))
-      (save-excursion
-       (save-restriction
-         (let (col list elt ts buffer-invisibility-spec)
-           (org-back-to-heading t)
-           (looking-at (concat org-outline-regexp "\\( *\\)[^\r\n]*"))
-           (goto-char (match-end 1))
-           (setq col (current-column))
-           (goto-char (match-end 0))
-           (if (eobp) (insert "\n") (forward-char 1))
-           (when (and (not what)
-                      (not (looking-at
-                            (concat "[ \t]*"
-                                    org-keyword-time-not-clock-regexp))))
-             ;; Nothing to add, nothing to remove...... :-)
-             (throw 'exit nil))
-           (if (and (not (looking-at org-outline-regexp))
-                    (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
-                                        "[^\r\n]*"))
-                    (not (equal (match-string 1) org-clock-string)))
-               (narrow-to-region (match-beginning 0) (match-end 0))
-             (insert-before-markers "\n")
-             (backward-char 1)
-             (narrow-to-region (point) (point))
-             (and org-adapt-indentation (org-indent-to-column col)))
-           ;; Check if we have to remove something.
-           (setq list (cons what remove))
-           (while list
-             (setq elt (pop list))
-             (when (or (and (eq elt 'scheduled)
-                            (re-search-forward org-scheduled-time-regexp nil 
t))
-                       (and (eq elt 'deadline)
-                            (re-search-forward org-deadline-time-regexp nil t))
-                       (and (eq elt 'closed)
-                            (re-search-forward org-closed-time-regexp nil t)))
-               (replace-match "")
-               (if (looking-at "--+<[^>]+>") (replace-match ""))))
-           (and (looking-at "[ \t]+") (replace-match ""))
-           (and org-adapt-indentation (bolp) (org-indent-to-column col))
-           (when what
-             (insert
-              (if (not (or (bolp) (eq (char-before) ?\ ))) " " "")
-              (cond ((eq what 'scheduled) org-scheduled-string)
-                    ((eq what 'deadline) org-deadline-string)
-                    ((eq what 'closed) org-closed-string))
-              " ")
-             (setq ts (org-insert-time-stamp
-                       time
-                       (or org-time-was-given
-                           (and (eq what 'closed) org-log-done-with-time))
-                       (eq what 'closed)
-                       nil nil (list org-end-time-was-given)))
-             (insert
-              (if (not (or (bolp) (eq (char-before) ?\ )
-                           (memq (char-after) '(32 10))
-                           (eobp))) " " ""))
-             (end-of-line 1))
-           (goto-char (point-min))
-           (widen)
-           (if (and (looking-at "[ \t]*\n")
-                    (equal (char-before) ?\n))
-               (delete-region (1- (point)) (point-at-eol)))
-           ts))))))
-
-(defvar org-log-note-marker (make-marker))
+      (org-with-wide-buffer
+       (org-back-to-heading t)
+       (forward-line)
+       (unless (bolp) (insert "\n"))
+       (cond ((looking-at-p org-planning-line-re)
+             ;; Move to current indentation.
+             (skip-chars-forward " \t")
+             ;; Check if we have to remove something.
+             (dolist (type (if what (cons what remove) remove))
+               (save-excursion
+                 (when (re-search-forward
+                        (cl-case type
+                          (closed org-closed-time-regexp)
+                          (deadline org-deadline-time-regexp)
+                          (scheduled org-scheduled-time-regexp)
+                          (otherwise
+                           (error "Invalid planning type: %s" type)))
+                        (line-end-position) t)
+                   ;; Delete until next keyword or end of line.
+                   (delete-region
+                    (match-beginning 0)
+                    (if (re-search-forward org-keyword-time-not-clock-regexp
+                                           (line-end-position)
+                                           t)
+                        (match-beginning 0)
+                      (line-end-position))))))
+             ;; If there is nothing more to add and no more keyword
+             ;; is left, remove the line completely.
+             (if (and (looking-at-p "[ \t]*$") (not what))
+                 (delete-region (line-beginning-position)
+                                (line-beginning-position 2))
+               ;; If we removed last keyword, do not leave trailing
+               ;; white space at the end of line.
+               (let ((p (point)))
+                 (save-excursion
+                   (end-of-line)
+                   (unless (= (skip-chars-backward " \t" p) 0)
+                     (delete-region (point) (line-end-position)))))))
+            ((not what) (throw 'exit nil)) ; Nothing to do.
+            (t (insert-before-markers "\n")
+               (backward-char 1)
+               (when org-adapt-indentation
+                 (indent-to-column (1+ (org-outline-level))))))
+       (when what
+        ;; Insert planning keyword.
+        (insert (cl-case what
+                  (closed org-closed-string)
+                  (deadline org-deadline-string)
+                  (scheduled org-scheduled-string)
+                  (otherwise (error "Invalid planning type: %s" what)))
+                " ")
+        ;; Insert associated timestamp.
+        (let ((ts (org-insert-time-stamp
+                   time
+                   (or org-time-was-given
+                       (and (eq what 'closed) org-log-done-with-time))
+                   (eq what 'closed)
+                   nil nil (list org-end-time-was-given))))
+          (unless (eolp) (insert " "))
+          ts))))))
+
+(defvar org-log-note-marker (make-marker)
+  "Marker pointing at the entry where the note is to be inserted.")
 (defvar org-log-note-purpose nil)
 (defvar org-log-note-state nil)
 (defvar org-log-note-previous-state nil)
-(defvar org-log-note-how nil)
 (defvar org-log-note-extra nil)
 (defvar org-log-note-window-configuration nil)
 (defvar org-log-note-return-to (make-marker))
 (defvar org-log-note-effective-time nil
   "Remembered current time so that dynamically scoped
-`org-extend-today-until' affects tha timestamps in state change
-log")
+`org-extend-today-until' affects timestamps in state change log")
 
 (defvar org-log-post-message nil
   "Message to be displayed after a log note has been stored.
@@ -13304,85 +13651,92 @@ The auto-repeater uses this.")
   "Add a note to the current entry.
 This is done in the same way as adding a state change note."
   (interactive)
-  (org-add-log-setup 'note nil nil 'findpos nil))
+  (org-add-log-setup 'note))
 
-(defvar org-property-end-re)
-(defun org-add-log-setup (&optional purpose state prev-state
-                                   findpos how extra)
+(defun org-log-beginning (&optional create)
+  "Return expected start of log notes in current entry.
+When optional argument CREATE is non-nil, the function creates
+a drawer to store notes, if necessary.  Returned position ignores
+narrowing."
+  (org-with-wide-buffer
+   (let ((drawer (org-log-into-drawer)))
+     (cond
+      (drawer
+       (org-end-of-meta-data)
+       (let ((regexp (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$"))
+            (end (if (org-at-heading-p) (point)
+                   (save-excursion (outline-next-heading) (point))))
+            (case-fold-search t))
+        (catch 'exit
+          ;; Try to find existing drawer.
+          (while (re-search-forward regexp end t)
+            (let ((element (org-element-at-point)))
+              (when (eq (org-element-type element) 'drawer)
+                (let ((cend  (org-element-property :contents-end element)))
+                  (when (and (not org-log-states-order-reversed) cend)
+                    (goto-char cend)))
+                (throw 'exit nil))))
+          ;; No drawer found.  Create one, if permitted.
+          (when create
+            (unless (bolp) (insert "\n"))
+            (let ((beg (point)))
+              (insert ":" drawer ":\n:END:\n")
+              (org-indent-region beg (point)))
+            (end-of-line -1)))))
+      (t
+       (org-end-of-meta-data org-log-state-notes-insert-after-drawers)
+       (skip-chars-forward " \t\n")
+       (beginning-of-line)
+       (unless org-log-states-order-reversed
+        (org-skip-over-state-notes)
+        (skip-chars-backward " \t\n")
+        (forward-line)))))
+   (if (bolp) (point) (line-beginning-position 2))))
+
+(defun org-add-log-setup (&optional purpose state prev-state how extra)
   "Set up the post command hook to take a note.
 If this is about to TODO state change, the new state is expected in STATE.
-When FINDPOS is non-nil, find the correct position for the note in
-the current entry.  If not, assume that it can be inserted at point.
 HOW is an indicator what kind of note should be created.
 EXTRA is additional text that will be inserted into the notes buffer."
-  (let* ((org-log-into-drawer (org-log-into-drawer))
-        (drawer (cond ((stringp org-log-into-drawer)
-                       org-log-into-drawer)
-                      (org-log-into-drawer "LOGBOOK"))))
-    (save-restriction
-      (save-excursion
-       (when findpos
-         (org-back-to-heading t)
-         (narrow-to-region (point) (save-excursion
-                                     (outline-next-heading) (point)))
-         (looking-at (concat org-outline-regexp "\\( *\\)[^\r\n]*"
-                             "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp
-                             "[^\r\n]*\\)?"))
-         (goto-char (match-end 0))
-         (cond
-          (drawer
-           (if (re-search-forward (concat "^[ \t]*:" drawer ":[ \t]*$")
-                                  nil t)
-               (progn
-                 (goto-char (match-end 0))
-                 (or org-log-states-order-reversed
-                     (and (re-search-forward org-property-end-re nil t)
-                          (goto-char (1- (match-beginning 0))))))
-             (insert "\n:" drawer ":\n:END:")
-             (beginning-of-line 0)
-             (org-indent-line)
-             (beginning-of-line 2)
-             (org-indent-line)
-             (end-of-line 0)))
-          ((and org-log-state-notes-insert-after-drawers
-                (save-excursion
-                  (forward-line) (looking-at org-drawer-regexp)))
-           (forward-line)
-           (while (looking-at org-drawer-regexp)
-             (goto-char (match-end 0))
-             (re-search-forward org-property-end-re (point-max) t)
-             (forward-line))
-           (forward-line -1)))
-         (unless org-log-states-order-reversed
-           (and (= (char-after) ?\n) (forward-char 1))
-           (org-skip-over-state-notes)
-           (skip-chars-backward " \t\n\r")))
-       (move-marker org-log-note-marker (point))
-       (setq org-log-note-purpose purpose
-             org-log-note-state state
-             org-log-note-previous-state prev-state
-             org-log-note-how how
-             org-log-note-extra extra
-             org-log-note-effective-time (org-current-effective-time))
-       (add-hook 'post-command-hook 'org-add-log-note 'append)))))
+  (move-marker org-log-note-marker (point))
+  (setq org-log-note-purpose purpose
+       org-log-note-state state
+       org-log-note-previous-state prev-state
+       org-log-note-how how
+       org-log-note-extra extra
+       org-log-note-effective-time (org-current-effective-time))
+  (add-hook 'post-command-hook 'org-add-log-note 'append))
 
 (defun org-skip-over-state-notes ()
   "Skip past the list of State notes in an entry."
-  (if (looking-at "\n[ \t]*- State") (forward-char 1))
   (when (ignore-errors (goto-char (org-in-item-p)))
     (let* ((struct (org-list-struct))
-          (prevs (org-list-prevs-alist struct)))
-      (while (looking-at "[ \t]*- State")
+          (prevs (org-list-prevs-alist struct))
+          (regexp
+           (concat "[ \t]*- +"
+                   (replace-regexp-in-string
+                    " +" " +"
+                    (org-replace-escapes
+                     (regexp-quote (cdr (assq 'state org-log-note-headings)))
+                     `(("%d" . ,org-ts-regexp-inactive)
+                       ("%D" . ,org-ts-regexp)
+                       ("%s" . "\"\\S-+\"")
+                       ("%S" . "\"\\S-+\"")
+                       ("%t" . ,org-ts-regexp-inactive)
+                       ("%T" . ,org-ts-regexp)
+                       ("%u" . ".*?")
+                       ("%U" . ".*?")))))))
+      (while (looking-at-p regexp)
        (goto-char (or (org-list-get-next-item (point) struct prevs)
                       (org-list-get-item-end (point) struct)))))))
 
-(defun org-add-log-note (&optional purpose)
-  "Pop up a window for taking a note, and add this note later at point."
+(defun org-add-log-note (&optional _purpose)
+  "Pop up a window for taking a note, and add this note later."
   (remove-hook 'post-command-hook 'org-add-log-note)
   (setq org-log-note-window-configuration (current-window-configuration))
   (delete-other-windows)
   (move-marker org-log-note-return-to (point))
-  (org-pop-to-buffer-same-window (marker-buffer org-log-note-marker))
+  (pop-to-buffer-same-window (marker-buffer org-log-note-marker))
   (goto-char org-log-note-marker)
   (org-switch-to-buffer-other-window "*Org Note*")
   (erase-buffer)
@@ -13411,23 +13765,23 @@ EXTRA is additional text that will be inserted into 
the notes buffer."
                     ((eq org-log-note-purpose 'note)
                      "this entry")
                     (t (error "This should not happen")))))
-    (if org-log-note-extra (insert org-log-note-extra))
-    (org-set-local 'org-finish-function 'org-store-log-note)
+    (when org-log-note-extra (insert org-log-note-extra))
+    (setq-local org-finish-function 'org-store-log-note)
     (run-hooks 'org-log-buffer-setup-hook)))
 
 (defvar org-note-abort nil) ; dynamically scoped
 (defun org-store-log-note ()
   "Finish taking a log note, and insert it to where it belongs."
-  (let ((txt (buffer-string)))
-    (kill-buffer (current-buffer))
-    (let ((note (cdr (assq org-log-note-purpose org-log-note-headings)))
-         lines ind bul)
+  (let ((txt (prog1 (buffer-string)
+              (kill-buffer)))
+       (note (cdr (assq org-log-note-purpose org-log-note-headings)))
+       lines)
     (while (string-match "\\`# .*\n[ \t\n]*" txt)
       (setq txt (replace-match "" t t txt)))
-    (if (string-match "\\s-+\\'" txt)
-       (setq txt (replace-match "" t t txt)))
+    (when (string-match "\\s-+\\'" txt)
+      (setq txt (replace-match "" t t txt)))
     (setq lines (org-split-string txt "\n"))
-    (when (and note (string-match "\\S-" note))
+    (when (org-string-nw-p note)
       (setq note
            (org-replace-escapes
             note
@@ -13445,74 +13799,83 @@ EXTRA is additional text that will be inserted into 
the notes buffer."
                   (cons "%D" (format-time-string
                               (org-time-stamp-format nil nil)
                               org-log-note-effective-time))
-                  (cons "%s" (if org-log-note-state
-                                 (concat "\"" org-log-note-state "\"")
-                               ""))
-                  (cons "%S" (if org-log-note-previous-state
-                                 (concat "\"" org-log-note-previous-state "\"")
-                               "\"\"")))))
-      (if lines (setq note (concat note " \\\\")))
+                  (cons "%s" (cond
+                              ((not org-log-note-state) "")
+                              ((string-match-p org-ts-regexp
+                                               org-log-note-state)
+                               (format "\"[%s]\""
+                                       (substring org-log-note-state 1 -1)))
+                              (t (format "\"%s\"" org-log-note-state))))
+                  (cons "%S"
+                        (cond
+                         ((not org-log-note-previous-state) "")
+                         ((string-match-p org-ts-regexp
+                                          org-log-note-previous-state)
+                          (format "\"[%s]\""
+                                  (substring
+                                   org-log-note-previous-state 1 -1)))
+                         (t (format "\"%s\""
+                                    org-log-note-previous-state)))))))
+      (when lines (setq note (concat note " \\\\")))
       (push note lines))
-    (when (or current-prefix-arg org-note-abort)
-      (when org-log-into-drawer
-       (org-remove-empty-drawer-at
-        (if (stringp org-log-into-drawer) org-log-into-drawer "LOGBOOK")
-        org-log-note-marker))
-      (setq lines nil))
-    (when lines
+    (when (and lines (not (or current-prefix-arg org-note-abort)))
       (with-current-buffer (marker-buffer org-log-note-marker)
-       (save-excursion
-         (goto-char org-log-note-marker)
-         (move-marker org-log-note-marker nil)
-         (end-of-line 1)
-         (if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
-         (setq ind (save-excursion
-                     (if (ignore-errors (goto-char (org-in-item-p)))
-                         (let ((struct (org-list-struct)))
-                           (org-list-get-ind
-                            (org-list-get-top-point struct) struct))
-                       (skip-chars-backward " \r\t\n")
-                       (cond
-                        ((and (org-at-heading-p)
-                              org-adapt-indentation)
-                         (1+ (org-current-level)))
-                        ((org-at-heading-p) 0)
-                        (t (org-get-indentation))))))
-         (setq bul (org-list-bullet-string "-"))
-         (org-indent-line-to ind)
-         (insert bul (pop lines))
-         (let ((ind-body (+ (length bul) ind)))
-           (while lines
-             (insert "\n")
-             (org-indent-line-to ind-body)
-             (insert (pop lines))))
-         (message "Note stored")
-         (org-back-to-heading t)
-         (org-cycle-hide-drawers 'children))
+       (org-with-wide-buffer
+        ;; Find location for the new note.
+        (goto-char org-log-note-marker)
+        (set-marker org-log-note-marker nil)
+        ;; Note associated to a clock is to be located right after
+        ;; the clock.  Do not move point.
+        (unless (eq org-log-note-purpose 'clock-out)
+          (goto-char (org-log-beginning t)))
+        ;; Make sure point is at the beginning of an empty line.
+        (cond ((not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
+              ((looking-at "[ \t]*\\S-") (save-excursion (insert "\n"))))
+        ;; In an existing list, add a new item at the top level.
+        ;; Otherwise, indent line like a regular one.
+        (let ((itemp (org-in-item-p)))
+          (if itemp
+              (indent-line-to
+               (let ((struct (save-excursion
+                               (goto-char itemp) (org-list-struct))))
+                 (org-list-get-ind (org-list-get-top-point struct) struct)))
+            (org-indent-line)))
+        (insert (org-list-bullet-string "-") (pop lines))
+        (let ((ind (org-list-item-body-column (line-beginning-position))))
+          (dolist (line lines)
+            (insert "\n")
+            (indent-line-to ind)
+            (insert line)))
+        (message "Note stored")
+        (org-back-to-heading t)
+        (org-cycle-hide-drawers 'children))
        ;; Fix `buffer-undo-list' when `org-store-log-note' is called
        ;; from within `org-add-log-note' because `buffer-undo-list'
        ;; is then modified outside of `org-with-remote-undo'.
        (when (eq this-command 'org-agenda-todo)
-         (setcdr buffer-undo-list (cddr buffer-undo-list)))))))
-  ;; Don't add undo information when called from `org-agenda-todo'
+         (setcdr buffer-undo-list (cddr buffer-undo-list))))))
+  ;; Don't add undo information when called from `org-agenda-todo'.
   (let ((buffer-undo-list (eq this-command 'org-agenda-todo)))
     (set-window-configuration org-log-note-window-configuration)
     (with-current-buffer (marker-buffer org-log-note-return-to)
       (goto-char org-log-note-return-to))
     (move-marker org-log-note-return-to nil)
-    (and org-log-post-message (message "%s" org-log-post-message))))
+    (when org-log-post-message (message "%s" org-log-post-message))))
 
-(defun org-remove-empty-drawer-at (drawer pos)
-  "Remove an empty drawer DRAWER at position POS.
+(defun org-remove-empty-drawer-at (pos)
+  "Remove an empty drawer at position POS.
 POS may also be a marker."
   (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer))
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char pos)
-       (if (org-in-regexp
-            (concat "^[ \t]*:" drawer ":[ \t]*\n[ \t]*:END:[ \t]*\n?") 2)
-           (replace-match ""))))))
+    (org-with-wide-buffer
+     (goto-char pos)
+     (let ((drawer (org-element-at-point)))
+       (when (and (memq (org-element-type drawer) '(drawer property-drawer))
+                 (not (org-element-property :contents-begin drawer)))
+        (delete-region (org-element-property :begin drawer)
+                       (progn (goto-char (org-element-property :end drawer))
+                              (skip-chars-backward " \r\t\n")
+                              (forward-line)
+                              (point))))))))
 
 (defvar org-ts-type nil)
 (defun org-sparse-tree (&optional arg type)
@@ -13533,47 +13896,45 @@ D      Show deadlines and scheduled items between a 
date range."
   (interactive "P")
   (setq type (or type org-sparse-tree-default-date-type))
   (setq org-ts-type type)
-  (message "Sparse tree: [/]regexp [t]odo [T]odo-kwd [m]atch [p]roperty
-             [d]eadlines [b]efore-date [a]fter-date [D]ates range
-             [c]ycle through date types: %s"
-          (case type
+  (message "Sparse tree: [r]egexp [t]odo [T]odo-kwd [m]atch [p]roperty
+             \[d]eadlines [b]efore-date [a]fter-date [D]ates range
+             \[c]ycle through date types: %s"
+          (cl-case type
             (all "all timestamps")
             (scheduled "only scheduled")
             (deadline "only deadline")
             (active "only active timestamps")
             (inactive "only inactive timestamps")
-            (scheduled-or-deadline "scheduled/deadline")
             (closed "with a closed time-stamp")
             (otherwise "scheduled/deadline")))
   (let ((answer (read-char-exclusive)))
-    (case answer
+    (cl-case answer
       (?c
        (org-sparse-tree
        arg
-       (cadr (memq type '(scheduled-or-deadline all scheduled deadline active
-                                                inactive closed)))))
-      (?d (call-interactively #'org-check-deadlines))
-      (?b (call-interactively #'org-check-before-date))
-      (?a (call-interactively #'org-check-after-date))
-      (?D (call-interactively #'org-check-dates-range))
-      (?t (call-interactively #'org-show-todo-tree))
+       (cadr
+        (memq type '(nil all scheduled deadline active inactive closed)))))
+      (?d (call-interactively 'org-check-deadlines))
+      (?b (call-interactively 'org-check-before-date))
+      (?a (call-interactively 'org-check-after-date))
+      (?D (call-interactively 'org-check-dates-range))
+      (?t (call-interactively 'org-show-todo-tree))
       (?T (org-show-todo-tree '(4)))
-      (?m (call-interactively #'org-match-sparse-tree))
+      (?m (call-interactively 'org-match-sparse-tree))
       ((?p ?P)
-       (let* ((kwd (org-icompleting-read
+       (let* ((kwd (completing-read
                    "Property: " (mapcar #'list (org-buffer-property-keys))))
-             (value (org-icompleting-read
+             (value (completing-read
                      "Value: " (mapcar #'list (org-property-values kwd)))))
         (unless (string-match "\\`{.*}\\'" value)
           (setq value (concat "\"" value "\"")))
         (org-match-sparse-tree arg (concat kwd "=" value))))
-      ((?r ?R ?/) (call-interactively #'org-occur))
+      ((?r ?R ?/) (call-interactively 'org-occur))
       (otherwise (user-error "No such sparse tree command \"%c\"" answer)))))
 
-(defvar org-occur-highlights nil
+(defvar-local org-occur-highlights nil
   "List of overlays used for occur matches.")
-(make-variable-buffer-local 'org-occur-highlights)
-(defvar org-occur-parameters nil
+(defvar-local org-occur-parameters nil
   "Parameters of the active org-occur calls.
 This is a list, each call to org-occur pushes as cons cell,
 containing the regular expression and the callback, onto the list.
@@ -13583,18 +13944,21 @@ will only contain one set of parameters.  When the 
highlights are
 removed (for example with `C-c C-c', or with the next edit (depending
 on `org-remove-highlights-with-change'), this variable is emptied
 as well.")
-(make-variable-buffer-local 'org-occur-parameters)
 
 (defun org-occur (regexp &optional keep-previous callback)
   "Make a compact tree which shows all matches of REGEXP.
-The tree will show the lines where the regexp matches, and all higher
-headlines above the match.  It will also show the heading after the match,
-to make sure editing the matching entry is easy.
-If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
-call to `org-occur' will be kept, to allow stacking of calls to this
-command.
-If CALLBACK is non-nil, it is a function which is called to confirm
-that the match should indeed be shown."
+
+The tree will show the lines where the regexp matches, and any other context
+defined in `org-show-context-detail', which see.
+
+When optional argument KEEP-PREVIOUS is non-nil, highlighting and exposing
+done by a previous call to `org-occur' will be kept, to allow stacking of
+calls to this command.
+
+Optional argument CALLBACK can be a function of no argument.  In this case,
+it is called with point at the end of the match, match data being set
+accordingly.  Current match is shown only if the return value is non-nil.
+The function must neither move point nor alter narrowing."
   (interactive "sRegexp: \nP")
   (when (equal regexp "")
     (user-error "Regexp cannot be empty"))
@@ -13604,32 +13968,35 @@ that the match should indeed be shown."
   (let ((cnt 0))
     (save-excursion
       (goto-char (point-min))
-      (if (or (not keep-previous)          ; do not want to keep
-             (not org-occur-highlights))  ; no previous matches
-         ;; hide everything
-         (org-overview))
-      (while (re-search-forward regexp nil t)
-       (when (or (not callback)
-                 (save-match-data (funcall callback)))
-         (setq cnt (1+ cnt))
-         (when org-highlight-sparse-tree-matches
-           (org-highlight-new-match (match-beginning 0) (match-end 0)))
-         (org-show-context 'occur-tree))))
+      (when (or (not keep-previous)        ; do not want to keep
+               (not org-occur-highlights)) ; no previous matches
+       ;; hide everything
+       (org-overview))
+      (let ((case-fold-search (if (eq org-occur-case-fold-search 'smart)
+                                 (isearch-no-upper-case-p regexp t)
+                               org-occur-case-fold-search)))
+       (while (re-search-forward regexp nil t)
+         (when (or (not callback)
+                   (save-match-data (funcall callback)))
+           (setq cnt (1+ cnt))
+           (when org-highlight-sparse-tree-matches
+             (org-highlight-new-match (match-beginning 0) (match-end 0)))
+           (org-show-context 'occur-tree)))))
     (when org-remove-highlights-with-change
-      (org-add-hook 'before-change-functions 'org-remove-occur-highlights
-                   nil 'local))
+      (add-hook 'before-change-functions 'org-remove-occur-highlights
+               nil 'local))
     (unless org-sparse-tree-open-archived-trees
       (org-hide-archived-subtrees (point-min) (point-max)))
     (run-hooks 'org-occur-hook)
-    (if (org-called-interactively-p 'interactive)
-       (message "%d match(es) for regexp %s" cnt regexp))
+    (when (called-interactively-p 'interactive)
+      (message "%d match(es) for regexp %s" cnt regexp))
     cnt))
 
-(defun org-occur-next-match (&optional n reset)
+(defun org-occur-next-match (&optional n _reset)
   "Function for `next-error-function' to find sparse tree matches.
 N is the number of matches to move, when negative move backwards.
-RESET is entirely ignored - this function always goes back to the
-starting point when no match is found."
+This function always goes back to the starting point when no
+match is found."
   (let* ((limit (if (< n 0) (point-min) (point-max)))
         (search-func (if (< n 0)
                          'previous-single-char-property-change
@@ -13641,7 +14008,7 @@ starting point when no match is found."
       (while (setq p1 (funcall search-func (point) 'org-type))
        (when (equal p1 limit)
          (goto-char pos)
-         (error "No more matches"))
+         (user-error "No more matches"))
        (when (equal (get-char-property p1 'org-type) 'org-occur)
          (setq n (1- n))
          (when (= n 0)
@@ -13649,65 +14016,75 @@ starting point when no match is found."
            (throw 'exit (point))))
        (goto-char p1))
       (goto-char p1)
-      (error "No more matches"))))
+      (user-error "No more matches"))))
 
 (defun org-show-context (&optional key)
   "Make sure point and context are visible.
-How much context is shown depends upon the variables
-`org-show-hierarchy-above', `org-show-following-heading',
-`org-show-entry-below' and `org-show-siblings'."
-  (let ((heading-p   (org-at-heading-p t))
-       (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
-       (following-p (org-get-alist-option org-show-following-heading key))
-       (entry-p     (org-get-alist-option org-show-entry-below key))
-       (siblings-p  (org-get-alist-option org-show-siblings key)))
-    ;; Show heading or entry text
-    (if (and heading-p (not entry-p))
-       (org-flag-heading nil)    ; only show the heading
-      (and (or entry-p (outline-invisible-p) (org-invisible-p2))
-          (org-show-hidden-entry)))    ; show entire entry
-    (when following-p
-      ;; Show next sibling, or heading below text
-      (save-excursion
-       (and (if heading-p (org-goto-sibling) (outline-next-heading))
-            (org-flag-heading nil))))
-    (when siblings-p (org-show-siblings))
-    (when hierarchy-p
-      ;; show all higher headings, possibly with siblings
-      (save-excursion
-       (while (and (condition-case nil
-                       (progn (org-up-heading-all 1) t)
-                     (error nil))
-                   (not (bobp)))
-         (org-flag-heading nil)
-         (when siblings-p (org-show-siblings)))))))
+Optional argument KEY, when non-nil, is a symbol.  See
+`org-show-context-detail' for allowed values and how much is to
+be shown."
+  (org-show-set-visibility
+   (cond ((symbolp org-show-context-detail) org-show-context-detail)
+        ((cdr (assq key org-show-context-detail)))
+        (t (cdr (assq 'default org-show-context-detail))))))
+
+(defun org-show-set-visibility (detail)
+  "Set visibility around point according to DETAIL.
+DETAIL is either nil, `minimal', `local', `ancestors', `lineage',
+`tree', `canonical' or t.  See `org-show-context-detail' for more
+information."
+  ;; Show current heading and possibly its entry, following headline
+  ;; or all children.
+  (if (and (org-at-heading-p) (not (eq detail 'local)))
+      (org-flag-heading nil)
+    (org-show-entry)
+    ;; If point is hidden within a drawer or a block, make sure to
+    ;; expose it.
+    (dolist (o (overlays-at (point)))
+      (when (memq (overlay-get o 'invisible) '(org-hide-block outline))
+       (delete-overlay o)))
+    (unless (org-before-first-heading-p)
+      (org-with-limited-levels
+       (cl-case detail
+        ((tree canonical t) (org-show-children))
+        ((nil minimal ancestors))
+        (t (save-excursion
+             (outline-next-heading)
+             (org-flag-heading nil)))))))
+  ;; Show all siblings.
+  (when (eq detail 'lineage) (org-show-siblings))
+  ;; Show ancestors, possibly with their children.
+  (when (memq detail '(ancestors lineage tree canonical t))
+    (save-excursion
+      (while (org-up-heading-safe)
+       (org-flag-heading nil)
+       (when (memq detail '(canonical t)) (org-show-entry))
+       (when (memq detail '(tree canonical t)) (org-show-children))))))
 
 (defvar org-reveal-start-hook nil
   "Hook run before revealing a location.")
 
 (defun org-reveal (&optional siblings)
   "Show current entry, hierarchy above it, and the following headline.
-This can be used to show a consistent set of context around locations
-exposed with `org-show-hierarchy-above' or `org-show-following-heading'
-not t for the search context.
+
+This can be used to show a consistent set of context around
+locations exposed with `org-show-context'.
 
 With optional argument SIBLINGS, on each level of the hierarchy all
 siblings are shown.  This repairs the tree structure to what it would
 look like when opened with hierarchical calls to `org-cycle'.
-With double optional argument \\[universal-argument] \\[universal-argument], \
-go to the parent and show the
-entire tree."
+
+With a \\[universal-argument] \\[universal-argument] prefix, \
+go to the parent and show the entire tree."
   (interactive "P")
   (run-hooks 'org-reveal-start-hook)
-  (let ((org-show-hierarchy-above t)
-       (org-show-following-heading t)
-       (org-show-siblings (if siblings t org-show-siblings)))
-    (org-show-context nil))
-  (when (equal siblings '(16))
-    (save-excursion
-      (when (org-up-heading-safe)
-       (org-show-subtree)
-       (run-hook-with-args 'org-cycle-hook 'subtree)))))
+  (cond ((equal siblings '(4)) (org-show-set-visibility 'canonical))
+       ((equal siblings '(16))
+        (save-excursion
+          (when (org-up-heading-safe)
+            (org-show-subtree)
+            (run-hook-with-args 'org-cycle-hook 'subtree))))
+       (t (org-show-set-visibility 'lineage))))
 
 (defun org-highlight-new-match (beg end)
   "Highlight from BEG to END and mark the highlight is an occur headline."
@@ -13716,13 +14093,13 @@ entire tree."
     (overlay-put ov 'org-type 'org-occur)
     (push ov org-occur-highlights)))
 
-(defun org-remove-occur-highlights (&optional beg end noremove)
+(defun org-remove-occur-highlights (&optional _beg _end noremove)
   "Remove the occur highlights from the buffer.
 BEG and END are ignored.  If NOREMOVE is nil, remove this function
 from the `before-change-functions' in the current buffer."
   (interactive)
   (unless org-inhibit-highlight-removal
-    (mapc 'delete-overlay org-occur-highlights)
+    (mapc #'delete-overlay org-occur-highlights)
     (setq org-occur-highlights nil)
     (setq org-occur-parameters nil)
     (unless noremove
@@ -13746,89 +14123,88 @@ from the `before-change-functions' in the current 
buffer."
   (interactive)
   (org-priority 'down))
 
-(defun org-priority (&optional action show)
+(defun org-priority (&optional action _show)
   "Change the priority of an item.
 ACTION can be `set', `up', `down', or a character."
   (interactive "P")
   (if (equal action '(4))
       (org-show-priority)
-  (unless org-enable-priority-commands
-    (user-error "Priority commands are disabled"))
-  (setq action (or action 'set))
-  (let (current new news have remove)
-    (save-excursion
-      (org-back-to-heading t)
-      (if (looking-at org-priority-regexp)
+    (unless org-enable-priority-commands
+      (user-error "Priority commands are disabled"))
+    (setq action (or action 'set))
+    (let (current new news have remove)
+      (save-excursion
+       (org-back-to-heading t)
+       (when (looking-at org-priority-regexp)
          (setq current (string-to-char (match-string 2))
                have t))
-      (cond
-       ((eq action 'remove)
-       (setq remove t new ?\ ))
-       ((or (eq action 'set)
-           (if (featurep 'xemacs) (characterp action) (integerp action)))
-       (if (not (eq action 'set))
-           (setq new action)
-         (message "Priority %c-%c, SPC to remove: "
-                  org-highest-priority org-lowest-priority)
-         (save-match-data
-           (setq new (read-char-exclusive))))
-       (if (and (= (upcase org-highest-priority) org-highest-priority)
-                (= (upcase org-lowest-priority) org-lowest-priority))
+       (cond
+        ((eq action 'remove)
+         (setq remove t new ?\ ))
+        ((or (eq action 'set)
+             (integerp action))
+         (if (not (eq action 'set))
+             (setq new action)
+           (message "Priority %c-%c, SPC to remove: "
+                    org-highest-priority org-lowest-priority)
+           (save-match-data
+             (setq new (read-char-exclusive))))
+         (when (and (= (upcase org-highest-priority) org-highest-priority)
+                    (= (upcase org-lowest-priority) org-lowest-priority))
            (setq new (upcase new)))
-       (cond ((equal new ?\ ) (setq remove t))
-             ((or (< (upcase new) org-highest-priority) (> (upcase new) 
org-lowest-priority))
-              (user-error "Priority must be between `%c' and `%c'"
-                     org-highest-priority org-lowest-priority))))
-       ((eq action 'up)
-       (setq new (if have
-                     (1- current)  ; normal cycling
-                   ;; last priority was empty
-                   (if (eq last-command this-command)
-                       org-lowest-priority  ; wrap around empty to lowest
-                     ;; default
-                     (if org-priority-start-cycle-with-default
-                         org-default-priority
-                       (1- org-default-priority))))))
-       ((eq action 'down)
-       (setq new (if have
-                     (1+ current)  ; normal cycling
-                   ;; last priority was empty
-                   (if (eq last-command this-command)
-                       org-highest-priority  ; wrap around empty to highest
-                     ;; default
-                     (if org-priority-start-cycle-with-default
-                         org-default-priority
-                       (1+ org-default-priority))))))
-       (t (user-error "Invalid action")))
-      (if (or (< (upcase new) org-highest-priority)
-             (> (upcase new) org-lowest-priority))
+         (cond ((equal new ?\ ) (setq remove t))
+               ((or (< (upcase new) org-highest-priority) (> (upcase new) 
org-lowest-priority))
+                (user-error "Priority must be between `%c' and `%c'"
+                            org-highest-priority org-lowest-priority))))
+        ((eq action 'up)
+         (setq new (if have
+                       (1- current)  ; normal cycling
+                     ;; last priority was empty
+                     (if (eq last-command this-command)
+                         org-lowest-priority  ; wrap around empty to lowest
+                       ;; default
+                       (if org-priority-start-cycle-with-default
+                           org-default-priority
+                         (1- org-default-priority))))))
+        ((eq action 'down)
+         (setq new (if have
+                       (1+ current)  ; normal cycling
+                     ;; last priority was empty
+                     (if (eq last-command this-command)
+                         org-highest-priority  ; wrap around empty to highest
+                       ;; default
+                       (if org-priority-start-cycle-with-default
+                           org-default-priority
+                         (1+ org-default-priority))))))
+        (t (user-error "Invalid action")))
+       (when (or (< (upcase new) org-highest-priority)
+                 (> (upcase new) org-lowest-priority))
          (if (and (memq action '(up down))
                   (not have) (not (eq last-command this-command)))
-              ;; `new' is from default priority
+             ;; `new' is from default priority
              (error
               "The default can not be set, see `org-default-priority' why")
-            ;; normal cycling: `new' is beyond highest/lowest priority
-            ;; and is wrapped around to the empty priority
+           ;; normal cycling: `new' is beyond highest/lowest priority
+           ;; and is wrapped around to the empty priority
            (setq remove t)))
-      (setq news (format "%c" new))
-      (if have
+       (setq news (format "%c" new))
+       (if have
+           (if remove
+               (replace-match "" t t nil 1)
+             (replace-match news t t nil 2))
          (if remove
-             (replace-match "" t t nil 1)
-           (replace-match news t t nil 2))
-       (if remove
-           (user-error "No priority cookie found in line")
-         (let ((case-fold-search nil))
-           (looking-at org-todo-line-regexp))
-         (if (match-end 2)
-             (progn
-               (goto-char (match-end 2))
-               (insert " [#" news "]"))
-           (goto-char (match-beginning 3))
-           (insert "[#" news "] "))))
-      (org-preserve-lc (org-set-tags nil 'align)))
-    (if remove
-       (message "Priority removed")
-      (message "Priority of current item set to %s" news)))))
+             (user-error "No priority cookie found in line")
+           (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))
+           (if (match-end 2)
+               (progn
+                 (goto-char (match-end 2))
+                 (insert " [#" news "]"))
+             (goto-char (match-beginning 3))
+             (insert "[#" news "] "))))
+       (org-set-tags nil 'align))
+      (if remove
+         (message "Priority removed")
+       (message "Priority of current item set to %s" news)))))
 
 (defun org-show-priority ()
   "Show the priority of the current item.
@@ -13863,6 +14239,7 @@ Can be set by the action argument to `org-scan-tags' 
and `org-map-entries'.")
 
 (defvar org-scanner-tags nil
   "The current tag list while the tags scanner is running.")
+
 (defvar org-trust-scanner-tags nil
   "Should `org-get-tags-at' use the tags for the scanner.
 This is for internal dynamical scoping only.
@@ -13874,6 +14251,8 @@ obtain a list of properties.  Building the tags list 
for each entry in such
 a file becomes an N^2 operation - but with this variable set, it scales
 as N.")
 
+(defvar org--matcher-tags-todo-only nil)
+
 (defun org-scan-tags (action matcher todo-only &optional start-level)
   "Scan headline tags with inheritance and produce output ACTION.
 
@@ -13882,11 +14261,14 @@ or `agenda' to produce an entry list for an agenda 
view.  It can also be
 a Lisp form or a function that should be called at each matched headline, in
 this case the return value is a list of all return values from these calls.
 
-MATCHER is a Lisp form to be evaluated, testing if a given set of tags
-qualifies a headline for inclusion.  When TODO-ONLY is non-nil,
-only lines with a not-done TODO keyword are included in the output.
-This should be the same variable that was scoped into
-and set by `org-make-tags-matcher' when it constructed MATCHER.
+MATCHER is a function accepting three arguments, returning
+a non-nil value whenever a given set of tags qualifies a headline
+for inclusion.  See `org-make-tags-matcher' for more information.
+As a special case, it can also be set to t (respectively nil) in
+order to match all (respectively none) headline.
+
+When TODO-ONLY is non-nil, only lines with a not-done TODO
+keyword are included in the output.
 
 START-LEVEL can be a string with asterisks, reducing the scope to
 headlines matching this string."
@@ -13897,8 +14279,8 @@ headlines matching this string."
                         (concat "\\*\\{" (number-to-string start-level) "\\} ")
                       org-outline-regexp)
                     " *\\(\\<\\("
-                    (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
-                    (org-re "\\)\\>\\)? 
*\\(.*?\\)\\(:[[:alnum:address@hidden:]+:\\)?[ \t]*$")))
+                    (mapconcat #'regexp-quote org-todo-keywords-1 "\\|")
+                    "\\)\\>\\)? *\\(.*?\\)\\(:[[:alnum:address@hidden:]+:\\)?[ 
\t]*$"))
         (props (list 'face 'default
                      'done-face 'org-agenda-done
                      'undone-face 'default
@@ -13915,8 +14297,9 @@ headlines matching this string."
          lspos tags tags-list
         (tags-alist (list (cons 0 org-file-tags)))
         (llast 0) rtn rtn1 level category i txt
-        todo marker entry priority)
-    (when (not (or (member action '(agenda sparse-tree)) (functionp action)))
+        todo marker entry priority
+        ts-date ts-date-type ts-date-pair)
+    (unless (or (member action '(agenda sparse-tree)) (functionp action))
       (setq action (list 'lambda nil action)))
     (save-excursion
       (goto-char (point-min))
@@ -13927,11 +14310,17 @@ headlines matching this string."
               (re-search-forward re nil t))
        (setq org-map-continue-from nil)
        (catch :skip
-         (setq todo (if (match-end 1) (org-match-string-no-properties 2))
-               tags (if (match-end 4) (org-match-string-no-properties 4)))
+         (setq todo
+               ;; TODO: is the 1-2 difference a bug?
+               (when (match-end 1) (match-string-no-properties 2))
+               tags (when (match-end 4) (match-string-no-properties 4)))
          (goto-char (setq lspos (match-beginning 0)))
          (setq level (org-reduced-level (org-outline-level))
                category (org-get-category))
+          (when (eq action 'agenda)
+            (setq ts-date-pair (org-agenda-entry-get-agenda-timestamp (point))
+                 ts-date (car ts-date-pair)
+                 ts-date-type (cdr ts-date-pair)))
          (setq i llast llast level)
          ;; remove tag lists from same and sublevels
          (while (>= i level)
@@ -13958,18 +14347,20 @@ headlines matching this string."
          (when (and tags org-use-tag-inheritance
                     (or (not (eq t org-use-tag-inheritance))
                         org-tags-exclude-from-inheritance))
-           ;; selective inheritance, remove uninherited ones
+           ;; Selective inheritance, remove uninherited ones.
            (setcdr (car tags-alist)
                    (org-remove-uninherited-tags (cdar tags-alist))))
          (when (and
 
                 ;; eval matcher only when the todo condition is OK
                 (and (or (not todo-only) (member todo org-not-done-keywords))
-                     (let ((case-fold-search t) (org-trust-scanner-tags t))
-                       (eval matcher)))
+                     (if (functionp matcher)
+                         (let ((case-fold-search t) (org-trust-scanner-tags t))
+                           (funcall matcher todo tags-list level))
+                       matcher))
 
-                ;; Call the skipper, but return t if it does not skip,
-                ;; so that the `and' form continues evaluating
+                ;; Call the skipper, but return t if it does not
+                ;; skip, so that the `and' form continues evaluating.
                 (progn
                   (unless (eq action 'sparse-tree) (org-agenda-skip))
                   t)
@@ -13995,7 +14386,8 @@ headlines matching this string."
                          (if (eq org-tags-match-list-sublevels 'indented)
                              (make-string (1- level) ?.) "")
                          (org-get-heading))
-                        level category
+                        (make-string level ?\s)
+                        category
                         tags-list)
                    priority (org-get-priority txt))
              (goto-char lspos)
@@ -14003,7 +14395,9 @@ headlines matching this string."
              (org-add-props txt props
                'org-marker marker 'org-hd-marker marker 'org-category category
                'todo-state todo
-               'priority priority 'type "tagsmatch")
+                'ts-date ts-date
+               'priority priority
+                'type (concat "tagsmatch" ts-date-type))
              (push txt rtn))
             ((functionp action)
              (setq org-map-continue-from nil)
@@ -14048,13 +14442,19 @@ headlines matching this string."
 
 (defun org-match-sparse-tree (&optional todo-only match)
   "Create a sparse tree according to tags string MATCH.
-MATCH can contain positive and negative selection of tags, like
-\"+WORK+URGENT-WITHBOSS\".
-If optional argument TODO-ONLY is non-nil, only select lines that are
-also TODO lines."
+
+MATCH is a string with match syntax.  It can contain a selection
+of tags (\"+work+urgent-boss\"), properties (\"LEVEL>3\"), and
+TODO keywords (\"TODO=\\\"WAITING\\\"\") or a combination of
+those.  See the manual for details.
+
+If optional argument TODO-ONLY is non-nil, only select lines that
+are also TODO tasks."
   (interactive "P")
   (org-agenda-prepare-buffers (list (current-buffer)))
-  (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only))
+  (let ((org--matcher-tags-todo-only todo-only))
+    (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match))
+                  org--matcher-tags-todo-only)))
 
 (defalias 'org-tags-sparse-tree 'org-match-sparse-tree)
 
@@ -14062,15 +14462,17 @@ also TODO lines."
 (defun org-cached-entry-get (pom property)
   (if (or (eq t org-use-property-inheritance)
          (and (stringp org-use-property-inheritance)
-              (string-match org-use-property-inheritance property))
+              (let ((case-fold-search t))
+                (string-match-p org-use-property-inheritance property)))
          (and (listp org-use-property-inheritance)
-              (member property org-use-property-inheritance)))
-      ;; Caching is not possible, check it directly
+              (member-ignore-case property org-use-property-inheritance)))
+      ;; Caching is not possible, check it directly.
       (org-entry-get pom property 'inherit)
-    ;; Get all properties, so that we can do complicated checks easily
-    (cdr (assoc property (or org-cached-props
-                            (setq org-cached-props
-                                  (org-entry-properties pom)))))))
+    ;; Get all properties, so we can do complicated checks easily.
+    (cdr (assoc-string property
+                      (or org-cached-props
+                          (setq org-cached-props (org-entry-properties pom)))
+                      t))))
 
 (defun org-global-tags-completion-table (&optional files)
   "Return the list of all tags in all agenda buffer/files.
@@ -14079,186 +14481,173 @@ instead of the agenda files."
   (save-excursion
     (org-uniquify
      (delq nil
-          (apply 'append
+          (apply #'append
                  (mapcar
                   (lambda (file)
                     (set-buffer (find-file-noselect file))
-                    (append (org-get-buffer-tags)
-                            (mapcar (lambda (x) (if (stringp (car-safe x))
-                                                    (list (car-safe x)) nil))
-                                    org-tag-alist)))
-                  (if (and files (car files))
-                      files
+                    (mapcar (lambda (x)
+                              (and (stringp (car-safe x))
+                                   (list (car-safe x))))
+                            (or org-current-tag-alist (org-get-buffer-tags))))
+                  (if (car-safe files) files
                     (org-agenda-files))))))))
 
 (defun org-make-tags-matcher (match)
   "Create the TAGS/TODO matcher form for the selection string MATCH.
 
-The variable `todo-only' is scoped dynamically into this function.
-It will be set to t if the matcher restricts matching to TODO entries,
-otherwise will not be touched.
-
-Returns a cons of the selection string MATCH and the constructed
-lisp form implementing the matcher.  The matcher is to be evaluated
-at an Org entry, with point on the headline, and returns t if the
-entry matches the selection string MATCH.  The returned lisp form
-references two variables with information about the entry, which
-must be bound around the form's evaluation: todo, the TODO keyword
-at the entry (or nil of none); and tags-list, the list of all tags
-at the entry including inherited ones.  Additionally, the category
-of the entry (if any) must be specified as the text property
-'org-category on the headline.
-
-See also `org-scan-tags'.
-"
-  (declare (special todo-only))
-  (unless (boundp 'todo-only)
-    (error "`org-make-tags-matcher' expects todo-only to be scoped in"))
+Returns a cons of the selection string MATCH and a function
+implementing the matcher.
+
+The matcher is to be called at an Org entry, with point on the
+headline, and returns non-nil if the entry matches the selection
+string MATCH.  It must be called with three arguments: the TODO
+keyword at the entry (or nil if none), the list of all tags at
+the entry including inherited ones and the reduced level of the
+headline.  Additionally, the category of the entry, if any, must
+be specified as the text property `org-category' on the headline.
+
+This function sets the variable `org--matcher-tags-todo-only' to
+a non-nil value if the matcher restricts matching to TODO
+entries, otherwise it is not touched.
+
+See also `org-scan-tags'."
   (unless match
     ;; Get a new match request, with completion against the global
-    ;; tags table and the local tags in current buffer
+    ;; tags table and the local tags in current buffer.
     (let ((org-last-tags-completion-table
           (org-uniquify
            (delq nil (append (org-get-buffer-tags)
                              (org-global-tags-completion-table))))))
-      (setq match (org-completing-read-no-i
-                  "Match: " 'org-tags-completion-function nil nil nil
-                  'org-tags-history))))
+      (setq match
+           (completing-read
+            "Match: "
+            'org-tags-completion-function nil nil nil 'org-tags-history))))
 
-  ;; Parse the string and create a lisp form
   (let ((match0 match)
-       (re (org-re 
"^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:address@hidden)"))
-       minus tag mm
-       tagsmatch todomatch tagsmatcher todomatcher kwd matcher
-       orterms orlist re-p str-p level-p level-op time-p
-       prop-p pn pv po gv rest (start 0) (ss 0))
-    ;; Expand group tags
+       (re 
"^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:address@hidden)")
+       (start 0)
+       tagsmatch todomatch tagsmatcher todomatcher)
+
+    ;; Expand group tags.
     (setq match (org-tags-expand match))
 
     ;; Check if there is a TODO part of this match, which would be the
-    ;; part after a "/".  TO make sure that this slash is not part of
-    ;; a property value to be matched against, we also check that there
-    ;; is no " after that slash.
-    ;; First, find the last slash
-    (while (string-match "/+" match ss)
-      (setq start (match-beginning 0) ss (match-end 0)))
+    ;; part after a "/".  To make sure that this slash is not part of
+    ;; a property value to be matched against, we also check that
+    ;; there is no / after that slash.  First, find the last slash.
+    (let ((s 0))
+      (while (string-match "/+" match s)
+       (setq start (match-beginning 0))
+       (setq s (match-end 0))))
     (if (and (string-match "/+" match start)
-            (not (save-match-data (string-match "\"" match start))))
-       ;; match contains also a todo-matching request
+            (not (string-match-p "\"" match start)))
+       ;; Match contains also a TODO-matching request.
        (progn
-         (setq tagsmatch (substring match 0 (match-beginning 0))
-               todomatch (substring match (match-end 0)))
-         (if (string-match "^!" todomatch)
-             (setq todo-only t todomatch (substring todomatch 1)))
-         (if (string-match "^\\s-*$" todomatch)
-             (setq todomatch nil)))
-      ;; only matching tags
-      (setq tagsmatch match todomatch nil))
-
-    ;; Make the tags matcher
-    (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
-       (setq tagsmatcher t)
-      (setq orterms (org-split-string tagsmatch "|") orlist nil)
-      (dolist (term orterms)
-       (while (and (equal (substring term -1) "\\") orterms)
-         (setq term (concat term "|" (pop orterms)))) ; repair bad split
-       (while (string-match re term)
-         (setq rest (substring term (match-end 0))
-               minus (and (match-end 1)
-                          (equal (match-string 1 term) "-"))
-               tag (save-match-data (replace-regexp-in-string
-                                     "\\\\-" "-"
-                                     (match-string 2 term)))
-               re-p (equal (string-to-char tag) ?{)
-               level-p (match-end 4)
-               prop-p (match-end 5)
-               mm (cond
-                   (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
-                   (level-p
-                    (setq level-op (org-op-to-function (match-string 3 term)))
-                    `(,level-op level ,(string-to-number
-                                        (match-string 4 term))))
-                   (prop-p
-                    (setq pn (match-string 5 term)
-                          po (match-string 6 term)
-                          pv (match-string 7 term)
-                          re-p (equal (string-to-char pv) ?{)
-                          str-p (equal (string-to-char pv) ?\")
-                          time-p (save-match-data
-                                   (string-match "^\"[[<].*[]>]\"$" pv))
-                          pv (if (or re-p str-p) (substring pv 1 -1) pv))
-                    (if time-p (setq pv (org-matcher-time pv)))
-                    (setq po (org-op-to-function po (if time-p 'time str-p)))
-                    (cond
-                     ((equal pn "CATEGORY")
-                      (setq gv '(get-text-property (point) 'org-category)))
-                     ((equal pn "TODO")
-                      (setq gv 'todo))
-                     (t
-                      (setq gv `(org-cached-entry-get nil ,pn))))
-                    (if re-p
-                        (if (eq po 'org<>)
-                            `(not (string-match ,pv (or ,gv "")))
-                          `(string-match ,pv (or ,gv "")))
-                      (if str-p
-                          `(,po (or ,gv "") ,pv)
-                        `(,po (string-to-number (or ,gv ""))
-                              ,(string-to-number pv) ))))
-                   (t `(member ,tag tags-list)))
-               mm (if minus (list 'not mm) mm)
-               term rest)
-         (push mm tagsmatcher))
-       (push (if (> (length tagsmatcher) 1)
-                 (cons 'and tagsmatcher)
-               (car tagsmatcher))
-             orlist)
-       (setq tagsmatcher nil))
-      (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car 
orlist)))
-      (setq tagsmatcher
-           (list 'progn '(setq org-cached-props nil) tagsmatcher)))
-    ;; Make the todo matcher
-    (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
-       (setq todomatcher t)
-      (setq orterms (org-split-string todomatch "|") orlist nil)
-      (dolist (term orterms)
-       (while (string-match re term)
-         (setq minus (and (match-end 1)
-                          (equal (match-string 1 term) "-"))
-               kwd (match-string 2 term)
-               re-p (equal (string-to-char kwd) ?{)
-               term (substring term (match-end 0))
-               mm (if re-p
-                      `(string-match  ,(substring kwd 1 -1) todo)
-                    (list 'equal 'todo kwd))
-               mm (if minus (list 'not mm) mm))
-         (push mm todomatcher))
-       (push (if (> (length todomatcher) 1)
-                 (cons 'and todomatcher)
-               (car todomatcher))
-             orlist)
-       (setq todomatcher nil))
-      (setq todomatcher (if (> (length orlist) 1)
-                           (cons 'or orlist) (car orlist))))
-
-    ;; Return the string and lisp forms of the matcher
-    (setq matcher (if todomatcher
-                     (list 'and tagsmatcher todomatcher)
-                   tagsmatcher))
-    (when todo-only
-      (setq matcher (list 'and '(member todo org-not-done-keywords)
-                         matcher)))
-    (cons match0 matcher)))
-
-(defun org-tags-expand (match &optional single-as-list downcased)
+         (setq tagsmatch (substring match 0 (match-beginning 0)))
+         (setq todomatch (substring match (match-end 0)))
+         (when (string-prefix-p "!" todomatch)
+           (setq org--matcher-tags-todo-only t)
+           (setq todomatch (substring todomatch 1)))
+         (when (string-match "\\`\\s-*\\'" todomatch)
+           (setq todomatch nil)))
+      ;; Only matching tags.
+      (setq tagsmatch match)
+      (setq todomatch nil))
+
+    ;; Make the tags matcher.
+    (when (org-string-nw-p tagsmatch)
+      (let ((orlist nil)
+           (orterms (org-split-string tagsmatch "|"))
+           term)
+       (while (setq term (pop orterms))
+         (while (and (equal (substring term -1) "\\") orterms)
+           (setq term (concat term "|" (pop orterms)))) ;repair bad split.
+         (while (string-match re term)
+           (let* ((rest (substring term (match-end 0)))
+                  (minus (and (match-end 1)
+                              (equal (match-string 1 term) "-")))
+                  (tag (save-match-data
+                         (replace-regexp-in-string
+                          "\\\\-" "-" (match-string 2 term))))
+                  (regexp (eq (string-to-char tag) ?{))
+                  (levelp (match-end 4))
+                  (propp (match-end 5))
+                  (mm
+                   (cond
+                    (regexp `(org-match-any-p ,(substring tag 1 -1) tags-list))
+                    (levelp
+                     `(,(org-op-to-function (match-string 3 term))
+                       level
+                       ,(string-to-number (match-string 4 term))))
+                    (propp
+                     (let* ((gv (pcase (upcase (match-string 5 term))
+                                  ("CATEGORY"
+                                   '(get-text-property (point) 'org-category))
+                                  ("TODO" 'todo)
+                                  (p `(org-cached-entry-get nil ,p))))
+                            (pv (match-string 7 term))
+                            (regexp (eq (string-to-char pv) ?{))
+                            (strp (eq (string-to-char pv) ?\"))
+                            (timep (string-match-p "^\"[[<].*[]>]\"$" pv))
+                            (po (org-op-to-function (match-string 6 term)
+                                                    (if timep 'time strp))))
+                       (setq pv (if (or regexp strp) (substring pv 1 -1) pv))
+                       (when timep (setq pv (org-matcher-time pv)))
+                       (cond ((and regexp (eq po 'org<>))
+                              `(not (string-match ,pv (or ,gv ""))))
+                             (regexp `(string-match ,pv (or ,gv "")))
+                             (strp `(,po (or ,gv "") ,pv))
+                             (t
+                              `(,po
+                                (string-to-number (or ,gv ""))
+                                ,(string-to-number pv))))))
+                    (t `(member ,tag tags-list)))))
+             (push (if minus `(not ,mm) mm) tagsmatcher)
+             (setq term rest)))
+         (push `(and ,@tagsmatcher) orlist)
+         (setq tagsmatcher nil))
+       (setq tagsmatcher `(progn (setq org-cached-props nil) (or ,@orlist)))))
+
+    ;; Make the TODO matcher.
+    (when (org-string-nw-p todomatch)
+      (let ((orlist nil))
+       (dolist (term (org-split-string todomatch "|"))
+         (while (string-match re term)
+           (let* ((minus (and (match-end 1)
+                              (equal (match-string 1 term) "-")))
+                  (kwd (match-string 2 term))
+                  (regexp (eq (string-to-char kwd) ?{))
+                  (mm (if regexp `(string-match ,(substring kwd 1 -1) todo)
+                        `(equal todo ,kwd))))
+             (push (if minus `(not ,mm) mm) todomatcher))
+           (setq term (substring term (match-end 0))))
+         (push (if (> (length todomatcher) 1)
+                   (cons 'and todomatcher)
+                 (car todomatcher))
+               orlist)
+         (setq todomatcher nil))
+       (setq todomatcher (cons 'or orlist))))
+
+    ;; Return the string and function of the matcher.  If no
+    ;; tags-specific or todo-specific matcher exists, match
+    ;; everything.
+    (let ((matcher (if (and tagsmatcher todomatcher)
+                      `(and ,tagsmatcher ,todomatcher)
+                    (or tagsmatcher todomatcher t))))
+      (when org--matcher-tags-todo-only
+       (setq matcher `(and (member todo org-not-done-keywords) ,matcher)))
+      (cons match0 `(lambda (todo tags-list level) ,matcher)))))
+
+(defun org-tags-expand (match &optional single-as-list downcased 
tags-already-expanded)
   "Expand group tags in MATCH.
 
 This replaces every group tag in MATCH with a regexp tag search.
 For example, a group tag \"Work\" defined as { Work : Lab Conf }
 will be replaced like this:
 
-   Work =>  {\\(?:Work\\|Lab\\|Conf\\)}
-  +Work => +{\\(?:Work\\|Lab\\|Conf\\)}
-  -Work => -{\\(?:Work\\|Lab\\|Conf\\)}
+   Work =>  {\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
+  +Work => +{\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
+  -Work => -{\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
 
 Replacing by a regexp preserves the structure of the match.
 E.g., this expansion
@@ -14268,6 +14657,12 @@ E.g., this expansion
 will match anything tagged with \"Lab\" and \"Home\", or tagged
 with \"Conf\" and \"Home\" or tagged with \"Work\" and \"home\".
 
+A group tag in MATCH can contain regular expressions of its own.
+For example, a group tag \"Proj\" defined as { Proj : address@hidden }
+will be replaced like this:
+
+   Proj => {\\<\\(?:Proj\\)\\>\\|address@hidden
+
 When the optional argument SINGLE-AS-LIST is non-nil, MATCH is
 assumed to be a single group tag, and the function will return
 the list of tags in this group.
@@ -14276,34 +14671,113 @@ When DOWNCASE is non-nil, expand downcased TAGS."
   (if org-group-tags
       (let* ((case-fold-search t)
             (stable org-mode-syntax-table)
-            (tal (or org-tag-groups-alist-for-agenda
-                     org-tag-groups-alist))
-            (tal (if downcased
-                     (mapcar (lambda(tg) (mapcar 'downcase tg)) tal) tal))
-            (tml (mapcar 'car tal))
-            (rtnmatch match) rpl)
-       ;; @ and _ are allowed as word-components in tags
+            (taggroups (or org-tag-groups-alist-for-agenda 
org-tag-groups-alist))
+            (taggroups (if downcased
+                           (mapcar (lambda (tg) (mapcar #'downcase tg))
+                                   taggroups)
+                         taggroups))
+            (taggroups-keys (mapcar #'car taggroups))
+            (return-match (if downcased (downcase match) match))
+            (count 0)
+            (work-already-expanded tags-already-expanded)
+            regexps-in-match tags-in-group regexp-in-group 
regexp-in-group-escaped)
+       ;; @ and _ are allowed as word-components in tags.
        (modify-syntax-entry ?@ "w" stable)
        (modify-syntax-entry ?_ "w" stable)
-       (while (and tml
+       ;; Temporarily replace regexp-expressions in the match-expression.
+       (while (string-match "{.+?}" return-match)
+         (cl-incf count)
+         (push (match-string 0 return-match) regexps-in-match)
+         (setq return-match (replace-match (format "<%d>" count) t nil 
return-match)))
+       (while (and taggroups-keys
                    (with-syntax-table stable
                      (string-match
                       (concat "\\(?1:[+-]?\\)\\(?2:\\<"
-                              (regexp-opt tml) "\\>\\)")
-                       rtnmatch)))
-         (let* ((dir (match-string 1 rtnmatch))
-                (tag (match-string 2 rtnmatch))
+                              (regexp-opt taggroups-keys) "\\>\\)")
+                      return-match)))
+         (let* ((dir (match-string 1 return-match))
+                (tag (match-string 2 return-match))
                 (tag (if downcased (downcase tag) tag)))
-           (setq tml (delete tag tml))
-           (when (not (get-text-property 0 'grouptag (match-string 2 
rtnmatch)))
-             (setq rpl (append (org-uniquify rpl) (assoc tag tal)))
-             (setq rpl (concat dir "{\\<" (regexp-opt rpl) "\\>}"))
-             (if (stringp rpl) (org-add-props rpl '(grouptag t)))
-             (setq rtnmatch (replace-match rpl t t rtnmatch)))))
+           (unless (or (get-text-property 0 'grouptag (match-string 2 
return-match))
+                       (member tag work-already-expanded))
+             (setq tags-in-group (assoc tag taggroups))
+             (push tag work-already-expanded)
+             ;; Recursively expand each tag in the group, if the tag hasn't
+             ;; already been expanded.  Restore the match-data after all 
recursive calls.
+             (save-match-data
+               (let (tags-expanded)
+                 (dolist (x (cdr tags-in-group))
+                   (if (and (member x taggroups-keys)
+                            (not (member x work-already-expanded)))
+                       (setq tags-expanded
+                             (delete-dups
+                              (append
+                               (org-tags-expand x t downcased
+                                                work-already-expanded)
+                               tags-expanded)))
+                     (setq tags-expanded
+                           (append (list x) tags-expanded)))
+                   (setq work-already-expanded
+                         (delete-dups
+                          (append tags-expanded
+                                  work-already-expanded))))
+                 (setq tags-in-group
+                       (delete-dups (cons (car tags-in-group)
+                                          tags-expanded)))))
+             ;; Filter tag-regexps from tags.
+             (setq regexp-in-group-escaped
+                   (delq nil (mapcar (lambda (x)
+                                       (if (stringp x)
+                                           (and (equal "{" (substring x 0 1))
+                                                (equal "}" (substring x -1))
+                                                x)
+                                         x))
+                                     tags-in-group))
+                   regexp-in-group
+                   (mapcar (lambda (x)
+                             (substring x 1 -1))
+                           regexp-in-group-escaped)
+                   tags-in-group
+                   (delq nil (mapcar (lambda (x)
+                                       (if (stringp x)
+                                           (and (not (equal "{" (substring x 0 
1)))
+                                                (not (equal "}" (substring x 
-1)))
+                                                x)
+                                         x))
+                                     tags-in-group)))
+             ;; If single-as-list, do no more in the while-loop.
+             (if (not single-as-list)
+                 (progn
+                   (when regexp-in-group
+                     (setq regexp-in-group
+                           (concat "\\|"
+                                   (mapconcat 'identity regexp-in-group
+                                              "\\|"))))
+                   (setq tags-in-group
+                         (concat dir
+                                 "{\\<"
+                                 (regexp-opt tags-in-group)
+                                 "\\>"
+                                 regexp-in-group
+                                 "}"))
+                   (when (stringp tags-in-group)
+                     (org-add-props tags-in-group '(grouptag t)))
+                   (setq return-match
+                         (replace-match tags-in-group t t return-match)))
+               (setq tags-in-group
+                     (append regexp-in-group-escaped tags-in-group))))
+           (setq taggroups-keys (delete tag taggroups-keys))))
+       ;; Add the regular expressions back into the match-expression again.
+       (while regexps-in-match
+         (setq return-match (replace-regexp-in-string (format "<%d>" count)
+                                                      (pop regexps-in-match)
+                                                      return-match t t))
+         (cl-decf count))
        (if single-as-list
-           (or (reverse rpl) (list rtnmatch))
-         rtnmatch))
-    (if single-as-list (list (if downcased (downcase match) match))
+           (if tags-in-group tags-in-group (list return-match))
+         return-match))
+    (if single-as-list
+       (list (if downcased (downcase match) match))
       match)))
 
 (defun org-op-to-function (op &optional stringp)
@@ -14371,7 +14845,7 @@ epoch to the beginning of today (00:00)."
 
 (defvar org-add-colon-after-tag-completion nil)  ;; dynamically scoped param
 (defvar org-tags-overlay (make-overlay 1 1))
-(org-detach-overlay org-tags-overlay)
+(delete-overlay org-tags-overlay)
 
 (defun org-get-local-tags-at (&optional pos)
   "Get a list of tags defined in the current headline."
@@ -14405,10 +14879,9 @@ ignore inherited ones."
                    (org-back-to-heading t)
                    (while (not (equal lastpos (point)))
                      (setq lastpos (point))
-                     (when (looking-at
-                            (org-re 
"[^\r\n]+?:\\([[:alnum:address@hidden:]+\\):[ \t]*$"))
+                     (when (looking-at ".+?:\\([[:alnum:address@hidden:]+\\):[ 
\t]*$")
                        (setq ltags (org-split-string
-                                    (org-match-string-no-properties 1) ":"))
+                                    (match-string-no-properties 1) ":"))
                        (when parent
                          (setq ltags (mapcar 'org-add-prop-inherited ltags)))
                        (setq tags (append
@@ -14417,7 +14890,7 @@ ignore inherited ones."
                                      ltags)
                                    tags)))
                      (or org-use-tag-inheritance (throw 'done t))
-                     (if local (throw 'done t))
+                     (when local (throw 'done t))
                      (or (org-up-heading-safe) (error nil))
                      (setq parent t)))
                (error nil)))))
@@ -14439,7 +14912,7 @@ If ONOFF is `on' or `off', don't toggle but set to this 
state."
   (let (res current)
     (save-excursion
       (org-back-to-heading t)
-      (if (re-search-forward (org-re "[ \t]:\\([[:alnum:address@hidden:]+\\):[ 
\t]*$")
+      (if (re-search-forward "[ \t]:\\([[:alnum:address@hidden:]+\\):[ \t]*$"
                             (point-at-eol) t)
          (progn
            (setq current (match-string 1))
@@ -14465,29 +14938,24 @@ If ONOFF is `on' or `off', don't toggle but set to 
this state."
       (run-hooks 'org-after-tags-change-hook))
     res))
 
-(defun org-align-tags-here (to-col)
-  ;; Assumes that this is a headline
-  "Align tags on the current headline to TO-COL."
-  (let ((pos (point)) (col (current-column)) ncol tags-l p)
-    (beginning-of-line 1)
-    (if        (and (looking-at (org-re ".*?\\([ 
\t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"))
-            (< pos (match-beginning 2)))
-       (progn
-         (setq tags-l (- (match-end 2) (match-beginning 2)))
-         (goto-char (match-beginning 1))
-         (insert " ")
-         (delete-region (point) (1+ (match-beginning 2)))
-         (setq ncol (max (current-column)
-                         (1+ col)
-                         (if (> to-col 0)
-                             to-col
-                           (- (abs to-col) tags-l))))
-         (setq p (point))
-         (insert (make-string (- ncol (current-column)) ?\ ))
-         (setq ncol (current-column))
-         (when indent-tabs-mode (tabify p (point-at-eol)))
-         (org-move-to-column (min ncol col)))
-      (goto-char pos))))
+(defun org--align-tags-here (to-col)
+  "Align tags on the current headline to TO-COL.
+Assume point is on a headline."
+  (let ((pos (point)))
+    (beginning-of-line)
+    (if        (or (not (looking-at ".*?\\([ 
\t]+\\)\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"))
+           (>= pos (match-beginning 2)))
+       ;; No tags or point within tags: do not align.
+       (goto-char pos)
+      (goto-char (match-beginning 1))
+      (let ((shift (max (- (if (>= to-col 0) to-col
+                            (- (abs to-col) (string-width (match-string 2))))
+                          (current-column))
+                       1)))
+       (replace-match (make-string shift ?\s) nil nil nil 1)
+       ;; Preserve initial position, if possible.  In any case, stop
+       ;; before tags.
+       (when (< pos (point)) (goto-char pos))))))
 
 (defun org-set-tags-command (&optional arg just-align)
   "Call the set-tags command for the current entry."
@@ -14517,7 +14985,8 @@ If DATA is nil or the empty string, any tags will be 
removed."
   (when data
     (save-excursion
       (org-back-to-heading t)
-      (when (looking-at org-complex-heading-regexp)
+      (when (let ((case-fold-search nil))
+             (looking-at org-complex-heading-regexp))
        (if (match-end 5)
            (progn
              (goto-char (match-beginning 5))
@@ -14528,11 +14997,11 @@ If DATA is nil or the empty string, any tags will be 
removed."
          (insert " " data)
          (org-set-tags nil 'align)))
       (beginning-of-line 1)
-      (if (looking-at ".*?\\([ \t]+\\)$")
-         (delete-region (match-beginning 1) (match-end 1))))))
+      (when (looking-at ".*?\\([ \t]+\\)$")
+       (delete-region (match-beginning 1) (match-end 1))))))
 
 (defun org-align-all-tags ()
-  "Align the tags i all headings."
+  "Align the tags in all headings."
   (interactive)
   (save-excursion
     (or (ignore-errors (org-back-to-heading t))
@@ -14549,106 +15018,124 @@ When JUST-ALIGN is non-nil, only align tags."
   (interactive "P")
   (if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
       (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
-                   'region-start-level 'region))
-           org-loop-over-headlines-in-active-region)
-       (org-map-entries
-        ;; We don't use ARG and JUST-ALIGN here because these args
-        ;; are not useful when looping over headlines.
-        `(org-set-tags)
-        org-loop-over-headlines-in-active-region
-        cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
-    (let* ((re org-outline-regexp-bol)
-          (current (unless arg (org-get-tags-string)))
-          (col (current-column))
-          (org-setting-tags t)
-          table current-tags inherited-tags ; computed below when needed
-          tags p0 c0 c1 rpl di tc level)
+                    'region-start-level
+                 'region))
+            org-loop-over-headlines-in-active-region)
+        (org-map-entries
+         ;; We don't use ARG and JUST-ALIGN here because these args
+         ;; are not useful when looping over headlines.
+         #'org-set-tags
+         org-loop-over-headlines-in-active-region
+         cl
+        '(when (org-invisible-p) (org-end-of-subtree nil t))))
+    (let ((org-setting-tags t))
       (if arg
-         (save-excursion
-           (goto-char (point-min))
-           (let ((buffer-invisibility-spec (org-inhibit-invisibility)))
-             (while (re-search-forward re nil t)
-               (org-set-tags nil t)
-               (end-of-line 1)))
-           (message "All tags realigned to column %d" org-tags-column))
-       (if just-align
-           (setq tags current)
-         ;; Get a new set of tags from the user
-         (save-excursion
-           (setq table (append org-tag-persistent-alist
-                               (or org-tag-alist (org-get-buffer-tags))
-                               (and
-                                org-complete-tags-always-offer-all-agenda-tags
-                                (org-global-tags-completion-table
-                                 (org-agenda-files))))
-                 org-last-tags-completion-table table
-                 current-tags (org-split-string current ":")
-                 inherited-tags (nreverse
-                                 (nthcdr (length current-tags)
-                                         (nreverse (org-get-tags-at))))
-                 tags
-                 (if (or (eq t org-use-fast-tag-selection)
-                         (and org-use-fast-tag-selection
-                              (delq nil (mapcar 'cdr table))))
-                     (org-fast-tag-selection
-                      current-tags inherited-tags table
-                      (if org-fast-tag-selection-include-todo
-                          org-todo-key-alist))
-                   (let ((org-add-colon-after-tag-completion (< 1 (length 
table))))
-                     (org-trim
-                      (org-icompleting-read "Tags: "
-                                            'org-tags-completion-function
-                                            nil nil current 
'org-tags-history))))))
-         (while (string-match "[-+&]+" tags)
-           ;; No boolean logic, just a list
-           (setq tags (replace-match ":" t t tags))))
-
-       (setq tags (replace-regexp-in-string "[,]" ":" tags))
-
-       (if org-tags-sort-function
-           (setq tags (mapconcat 'identity
-                                 (sort (org-split-string
-                                        tags (org-re 
"[^[:alnum:address@hidden"))
-                                       org-tags-sort-function) ":")))
-
-       (if (string-match "\\`[\t ]*\\'" tags)
-           (setq tags "")
-         (unless (string-match ":$" tags) (setq tags (concat tags ":")))
-         (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
-
-       ;; Insert new tags at the correct column
-       (beginning-of-line 1)
-       (setq level (or (and (looking-at org-outline-regexp)
-                            (- (match-end 0) (point) 1))
-                       1))
-       (cond
-        ((and (equal current "") (equal tags "")))
-        ((re-search-forward
-          (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
-          (point-at-eol) t)
-         (if (equal tags "")
-             (setq rpl "")
-           (goto-char (match-beginning 0))
-           (setq c0 (current-column)
-                 ;; compute offset for the case of org-indent-mode active
-                 di (if (org-bound-and-true-p org-indent-mode)
-                        (* (1- org-indent-indentation-per-level) (1- level))
-                      0)
-                 p0 (if (equal (char-before) ?*) (1+ (point)) (point))
-                 tc (+ org-tags-column (if (> org-tags-column 0) (- di) di))
-                 c1 (max (1+ c0) (if (> tc 0) tc (- (- tc) (length tags))))
-                 rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
-         (replace-match rpl t t)
-         (and (not (featurep 'xemacs)) c0 indent-tabs-mode (tabify p0 (point)))
-         tags)
-        (t (error "Tags alignment failed")))
-       (org-move-to-column col)
-       (unless just-align
-         (run-hooks 'org-after-tags-change-hook))))))
+          (save-excursion
+            (goto-char (point-min))
+            (while (re-search-forward org-outline-regexp-bol nil t)
+             (org-set-tags nil t)
+             (end-of-line))
+            (message "All tags realigned to column %d" org-tags-column))
+       (let* ((current (org-get-tags-string))
+              (tags
+               (if just-align current
+                 ;; Get a new set of tags from the user.
+                 (save-excursion
+                   (let* ((seen)
+                          (table
+                           (setq
+                            org-last-tags-completion-table
+                            ;; Uniquify tags in alists, yet preserve
+                            ;; structure (i.e., keywords).
+                            (delq nil
+                                  (mapcar
+                                   (lambda (pair)
+                                     (let ((head (car pair)))
+                                       (cond ((symbolp head) pair)
+                                             ((member head seen) nil)
+                                             (t (push head seen)
+                                                pair))))
+                                   (append
+                                    (or org-current-tag-alist
+                                        (org-get-buffer-tags))
+                                    (and
+                                     
org-complete-tags-always-offer-all-agenda-tags
+                                     (org-global-tags-completion-table
+                                      (org-agenda-files))))))))
+                          (current-tags (org-split-string current ":"))
+                          (inherited-tags
+                           (nreverse (nthcdr (length current-tags)
+                                             (nreverse (org-get-tags-at))))))
+                     (replace-regexp-in-string
+                      "\\([-+&]+\\|,\\)"
+                      ":"
+                      (if (or (eq t org-use-fast-tag-selection)
+                              (and org-use-fast-tag-selection
+                                   (delq nil (mapcar #'cdr table))))
+                          (org-fast-tag-selection
+                           current-tags inherited-tags table
+                           (and org-fast-tag-selection-include-todo
+                                org-todo-key-alist))
+                        (let ((org-add-colon-after-tag-completion
+                               (< 1 (length table))))
+                          (org-trim
+                           (completing-read
+                            "Tags: "
+                            #'org-tags-completion-function
+                            nil nil current 'org-tags-history))))))))))
+
+         (when org-tags-sort-function
+           (setq tags
+                 (mapconcat
+                  #'identity
+                  (sort (org-split-string tags "[^[:alnum:address@hidden")
+                        org-tags-sort-function)
+                  ":")))
+
+         (if (or (string= ":" tags)
+                 (string= "::" tags))
+             (setq tags ""))
+         (if (not (org-string-nw-p tags)) (setq tags "")
+           (unless (string-suffix-p ":" tags) (setq tags (concat tags ":")))
+           (unless (string-prefix-p ":" tags) (setq tags (concat ":" tags))))
+
+         ;; Insert new tags at the correct column.
+         (unless (equal current tags)
+           (save-excursion
+             (beginning-of-line)
+             (let ((case-fold-search nil))
+               (looking-at org-complex-heading-regexp))
+             ;; Remove current tags, if any.
+             (when (match-end 5) (replace-match "" nil nil nil 5))
+             ;; Insert new tags, if any.  Otherwise, remove trailing
+             ;; white spaces.
+             (end-of-line)
+             (if (not (equal tags ""))
+                 ;; When text is being inserted on an invisible
+                 ;; region boundary, it can be inadvertently sucked
+                 ;; into invisibility.
+                 (outline-flag-region (point) (progn (insert " " tags) 
(point)) nil)
+               (skip-chars-backward " \t")
+               (delete-region (point) (line-end-position)))))
+         ;; Align tags, if any.  Fix tags column if `org-indent-mode'
+         ;; is on.
+         (unless (equal tags "")
+           (let* ((level (save-excursion
+                           (beginning-of-line)
+                           (skip-chars-forward "\\*")))
+                  (offset (if (bound-and-true-p org-indent-mode)
+                              (* (1- org-indent-indentation-per-level)
+                                 (1- level))
+                            0))
+                  (tags-column
+                   (+ org-tags-column
+                      (if (> org-tags-column 0) (- offset) offset))))
+             (org--align-tags-here tags-column))))
+        (unless just-align (run-hooks 'org-after-tags-change-hook))))))
 
 (defun org-change-tag-in-region (beg end tag off)
   "Add or remove TAG for each entry in the region.
-This works in the agenda, and also in an org-mode buffer."
+This works in the agenda, and also in an Org buffer."
   (interactive
    (list (region-beginning) (region-end)
         (let ((org-last-tags-completion-table
@@ -14657,37 +15144,37 @@ This works in the agenda, and also in an org-mode 
buffer."
                     (delq nil (append (org-get-buffer-tags)
                                       (org-global-tags-completion-table))))
                  (org-global-tags-completion-table))))
-          (org-icompleting-read
+          (completing-read
            "Tag: " 'org-tags-completion-function nil nil nil
            'org-tags-history))
         (progn
           (message "[s]et or [r]emove? ")
           (equal (read-char-exclusive) ?r))))
-  (if (fboundp 'deactivate-mark) (deactivate-mark))
+  (when (fboundp 'deactivate-mark) (deactivate-mark))
   (let ((agendap (equal major-mode 'org-agenda-mode))
        l1 l2 m buf pos newhead (cnt 0))
     (goto-char end)
     (setq l2 (1- (org-current-line)))
     (goto-char beg)
     (setq l1 (org-current-line))
-    (loop for l from l1 to l2 do
-         (org-goto-line l)
-         (setq m (get-text-property (point) 'org-hd-marker))
-         (when (or (and (derived-mode-p 'org-mode) (org-at-heading-p))
-                   (and agendap m))
-           (setq buf (if agendap (marker-buffer m) (current-buffer))
-                 pos (if agendap m (point)))
-           (with-current-buffer buf
-             (save-excursion
-               (save-restriction
-                 (goto-char pos)
-                 (setq cnt (1+ cnt))
-                 (org-toggle-tag tag (if off 'off 'on))
-                 (setq newhead (org-get-heading)))))
-           (and agendap (org-agenda-change-all-lines newhead m))))
+    (cl-loop for l from l1 to l2 do
+            (org-goto-line l)
+            (setq m (get-text-property (point) 'org-hd-marker))
+            (when (or (and (derived-mode-p 'org-mode) (org-at-heading-p))
+                      (and agendap m))
+              (setq buf (if agendap (marker-buffer m) (current-buffer))
+                    pos (if agendap m (point)))
+              (with-current-buffer buf
+                (save-excursion
+                  (save-restriction
+                    (goto-char pos)
+                    (setq cnt (1+ cnt))
+                    (org-toggle-tag tag (if off 'off 'on))
+                    (setq newhead (org-get-heading)))))
+              (and agendap (org-agenda-change-all-lines newhead m))))
     (message "Tag :%s: %s in %d headings" tag (if off "removed" "set") cnt)))
 
-(defun org-tags-completion-function (string predicate &optional flag)
+(defun org-tags-completion-function (string _predicate &optional flag)
   (let (s1 s2 rtn (ctable org-last-tags-completion-table)
           (confirm (lambda (x) (stringp (car x)))))
     (if (string-match "^\\(.*[-+:&,|]\\)\\([^-+:&,|]*\\)$" string)
@@ -14698,12 +15185,12 @@ This works in the agenda, and also in an org-mode 
buffer."
      ((eq flag nil)
       ;; try completion
       (setq rtn (try-completion s2 ctable confirm))
-      (if (stringp rtn)
-         (setq rtn
-               (concat s1 s2 (substring rtn (length s2))
-                       (if (and org-add-colon-after-tag-completion
-                                (assoc rtn ctable))
-                           ":" ""))))
+      (when (stringp rtn)
+       (setq rtn
+             (concat s1 s2 (substring rtn (length s2))
+                     (if (and org-add-colon-after-tag-completion
+                              (assoc rtn ctable))
+                         ":" ""))))
       rtn)
      ((eq flag t)
       ;; all-completions
@@ -14722,8 +15209,8 @@ Also insert END."
 (defun org-fast-tag-show-exit (flag)
   (save-excursion
     (org-goto-line 3)
-    (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
-       (replace-match ""))
+    (when (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
+      (replace-match ""))
     (when flag
       (end-of-line 1)
       (org-move-to-column (- (window-width) 19) t)
@@ -14732,11 +15219,8 @@ Also insert END."
 (defun org-set-current-tags-overlay (current prefix)
   "Add an overlay to CURRENT tag with PREFIX."
   (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
-    (if (featurep 'xemacs)
-       (org-overlay-display org-tags-overlay (concat prefix s)
-                            'secondary-selection)
-      (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
-      (org-overlay-display org-tags-overlay (concat prefix s)))))
+    (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
+    (org-overlay-display org-tags-overlay (concat prefix s))))
 
 (defvar org-last-tag-selection-key nil)
 (defun org-fast-tag-selection (current inherited table &optional todo-table)
@@ -14759,15 +15243,14 @@ Returns the new tags string, or nil to not change the 
current settings."
         (ncol (/ (- (window-width) 4) fwidth))
         (i-face 'org-done)
         (c-face 'org-todo)
-        tg cnt c char c1 c2 ntable tbl rtn
+        tg cnt e c char c1 c2 ntable tbl rtn
         ov-start ov-end ov-prefix
         (exit-after-next org-fast-tag-selection-single-key)
         (done-keywords org-done-keywords)
-        groups ingroup)
+        groups ingroup intaggroup)
     (save-excursion
       (beginning-of-line 1)
-      (if (looking-at
-          (org-re ".*[ \t]\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$"))
+      (if (looking-at ".*[ \t]\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$")
          (setq ov-start (match-beginning 1)
                ov-end (match-end 1)
                ov-prefix "")
@@ -14788,32 +15271,41 @@ Returns the new tags string, or nil to not change the 
current settings."
        (set-window-buffer (split-window-vertically) (get-buffer-create " *Org 
tags*"))
        (org-switch-to-buffer-other-window " *Org tags*"))
       (erase-buffer)
-      (org-set-local 'org-done-keywords done-keywords)
+      (setq-local org-done-keywords done-keywords)
       (org-fast-tag-insert "Inherited" inherited i-face "\n")
       (org-fast-tag-insert "Current" current c-face "\n\n")
       (org-fast-tag-show-exit exit-after-next)
       (org-set-current-tags-overlay current ov-prefix)
       (setq tbl fulltable char ?a cnt 0)
-      (dolist (e tbl)
+      (while (setq e (pop tbl))
        (cond
-        ((equal (car e) :startgroup)
+        ((eq (car e) :startgroup)
          (push '() groups) (setq ingroup t)
-         (when (not (= cnt 0))
+         (unless (zerop cnt)
            (setq cnt 0)
            (insert "\n"))
          (insert (if (cdr e) (format "%s: " (cdr e)) "") "{ "))
-        ((equal (car e) :endgroup)
+        ((eq (car e) :endgroup)
          (setq ingroup nil cnt 0)
          (insert "}" (if (cdr e) (format " (%s) " (cdr e)) "") "\n"))
+        ((eq (car e) :startgrouptag)
+         (setq intaggroup t)
+         (unless (zerop cnt)
+           (setq cnt 0)
+           (insert "\n"))
+         (insert "[ "))
+        ((eq (car e) :endgrouptag)
+         (setq intaggroup nil cnt 0)
+         (insert "]\n"))
         ((equal e '(:newline))
-         (when (not (= cnt 0))
+         (unless (zerop cnt)
            (setq cnt 0)
            (insert "\n")
            (setq e (car tbl))
            (while (equal (car tbl) '(:newline))
              (insert "\n")
              (setq tbl (cdr tbl)))))
-        ((equal e '(:grouptags)) nil)
+        ((equal e '(:grouptags)) (insert " : "))
         (t
          (setq tg (copy-sequence (car e)) c2 nil)
          (if (cdr e)
@@ -14827,27 +15319,27 @@ Returns the new tags string, or nil to not change the 
current settings."
                  (setq char (1+ char)))
              (setq c2 c1))
            (setq c (or c2 char)))
-         (if ingroup (push tg (car groups)))
+         (when ingroup (push tg (car groups)))
          (setq tg (org-add-props tg nil 'face
                                  (cond
                                   ((not (assoc tg table))
                                    (org-get-todo-face tg))
                                   ((member tg current) c-face)
                                   ((member tg inherited) i-face))))
-         (if (equal (caar tbl) :grouptags)
-             (org-add-props tg nil 'face 'org-tag-group))
-         (if (and (= cnt 0) (not ingroup)) (insert "  "))
+         (when (equal (caar tbl) :grouptags)
+           (org-add-props tg nil 'face 'org-tag-group))
+         (when (and (zerop cnt) (not ingroup) (not intaggroup)) (insert " "))
          (insert "[" c "] " tg (make-string
                                 (- fwidth 4 (length tg)) ?\ ))
          (push (cons tg c) ntable)
-         (when (= (setq cnt (1+ cnt)) ncol)
+         (when (= (cl-incf cnt) ncol)
            (insert "\n")
-           (if ingroup (insert "  "))
+           (when (or ingroup intaggroup) (insert " "))
            (setq cnt 0)))))
       (setq ntable (nreverse ntable))
       (insert "\n")
       (goto-char (point-min))
-      (if (not expert) (org-fit-window-to-buffer))
+      (unless expert (org-fit-window-to-buffer))
       (setq rtn
            (catch 'exit
              (while t
@@ -14873,53 +15365,51 @@ Returns the new tags string, or nil to not change the 
current settings."
                    (org-fit-window-to-buffer)))
                 ((or (= c ?\C-g)
                      (and (= c ?q) (not (rassoc c ntable))))
-                 (org-detach-overlay org-tags-overlay)
+                 (delete-overlay org-tags-overlay)
                  (setq quit-flag t))
                 ((= c ?\ )
                  (setq current nil)
-                 (if exit-after-next (setq exit-after-next 'now)))
+                 (when exit-after-next (setq exit-after-next 'now)))
                 ((= c ?\t)
                  (condition-case nil
-                     (setq tg (org-icompleting-read
+                     (setq tg (completing-read
                                "Tag: "
                                (or buffer-tags
                                    (with-current-buffer buf
-                                     (org-get-buffer-tags)))))
+                                     (setq buffer-tags
+                                           (org-get-buffer-tags))))))
                    (quit (setq tg "")))
                  (when (string-match "\\S-" tg)
-                   (add-to-list 'buffer-tags (list tg))
+                   (cl-pushnew (list tg) buffer-tags :test #'equal)
                    (if (member tg current)
                        (setq current (delete tg current))
                      (push tg current)))
-                 (if exit-after-next (setq exit-after-next 'now)))
+                 (when exit-after-next (setq exit-after-next 'now)))
                 ((setq e (rassoc c todo-table) tg (car e))
                  (with-current-buffer buf
                    (save-excursion (org-todo tg)))
-                 (if exit-after-next (setq exit-after-next 'now)))
+                 (when exit-after-next (setq exit-after-next 'now)))
                 ((setq e (rassoc c ntable) tg (car e))
                  (if (member tg current)
                      (setq current (delete tg current))
-                   (loop for g in groups do
-                         (if (member tg g)
-                             (mapc (lambda (x)
-                                     (setq current (delete x current)))
-                                   g)))
+                   (cl-loop for g in groups do
+                            (when (member tg g)
+                              (dolist (x g) (setq current (delete x 
current)))))
                    (push tg current))
-                 (if exit-after-next (setq exit-after-next 'now))))
+                 (when exit-after-next (setq exit-after-next 'now))))
 
                ;; Create a sorted list
                (setq current
                      (sort current
                            (lambda (a b)
                              (assoc b (cdr (memq (assoc a ntable) ntable))))))
-               (if (eq exit-after-next 'now) (throw 'exit t))
+               (when (eq exit-after-next 'now) (throw 'exit t))
                (goto-char (point-min))
                (beginning-of-line 2)
                (delete-region (point) (point-at-eol))
                (org-fast-tag-insert "Current" current c-face)
                (org-set-current-tags-overlay current ov-prefix)
-               (while (re-search-forward
-                       (org-re "\\[.\\] \\([[:alnum:address@hidden)") nil t)
+               (while (re-search-forward "\\[.\\] \\([[:alnum:address@hidden)" 
nil t)
                  (setq tg (match-string 1))
                  (add-text-properties
                   (match-beginning 1) (match-end 1)
@@ -14929,7 +15419,7 @@ Returns the new tags string, or nil to not change the 
current settings."
                          ((member tg inherited) i-face)
                          (t (get-text-property (match-beginning 1) 'face))))))
                (goto-char (point-min)))))
-      (org-detach-overlay org-tags-overlay)
+      (delete-overlay org-tags-overlay)
       (if rtn
          (mapconcat 'identity current ":")
        nil))))
@@ -14940,8 +15430,8 @@ Returns the new tags string, or nil to not change the 
current settings."
     (user-error "Not on a heading"))
   (save-excursion
     (beginning-of-line 1)
-    (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:address@hidden:]+:\\)[ 
\t]*$"))
-       (org-match-string-no-properties 1)
+    (if (looking-at ".*[ \t]\\(:[[:alnum:address@hidden:]+:\\)[ \t]*$")
+       (match-string-no-properties 1)
       "")))
 
 (defun org-get-tags ()
@@ -14950,19 +15440,20 @@ Returns the new tags string, or nil to not change the 
current settings."
 
 (defun org-get-buffer-tags ()
   "Get a table of all tags used in the buffer, for completion."
-  (let (tags)
-    (save-excursion
-      (goto-char (point-min))
-      (while (re-search-forward
-             (org-re "[ \t]:\\([[:alnum:address@hidden:]+\\):[ \t\r\n]") nil t)
-       (when (equal (char-after (point-at-bol 0)) ?*)
-         (mapc (lambda (x) (add-to-list 'tags x))
-               (org-split-string (org-match-string-no-properties 1) ":")))))
-    (mapc (lambda (s) (add-to-list 'tags s)) org-file-tags)
-    (mapcar 'list tags)))
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let ((tag-re (concat org-outline-regexp-bol
+                        "\\(?:.*?[ \t]\\)?:\\([[:alnum:address@hidden:]+\\):[ 
\t]*$"))
+        tags)
+     (while (re-search-forward tag-re nil t)
+       (dolist (tag (org-split-string (match-string-no-properties 1) ":"))
+        (push tag tags)))
+     (mapcar #'list (append org-file-tags (org-uniquify tags))))))
 
 ;;;; The mapping API
 
+(defvar org-agenda-skip-comment-trees)
+(defvar org-agenda-skip-function)
 (defun org-map-entries (func &optional match scope &rest skip)
   "Call FUNC at each headline selected by MATCH in SCOPE.
 
@@ -15032,13 +15523,12 @@ a *different* entry, you cannot use these techniques."
            (car (org-delete-all '(comment archive) skip)))
           (org-tags-match-list-sublevels t)
           (start-level (eq scope 'region-start-level))
-          matcher file res
+          matcher res
           org-todo-keywords-for-agenda
           org-done-keywords-for-agenda
           org-todo-keyword-alist-for-agenda
-          org-drawers-for-agenda
           org-tag-alist-for-agenda
-          todo-only)
+          org--matcher-tags-todo-only)
 
       (cond
        ((eq match t)   (setq matcher t))
@@ -15071,7 +15561,9 @@ a *different* entry, you cannot use these techniques."
              (progn
                (org-agenda-prepare-buffers
                 (and buffer-file-name (list buffer-file-name)))
-               (setq res (org-scan-tags func matcher todo-only start-level)))
+               (setq res
+                     (org-scan-tags
+                      func matcher org--matcher-tags-todo-only start-level)))
            ;; Get the right scope
            (cond
             ((and scope (listp scope) (symbolp (car scope)))
@@ -15088,22 +15580,21 @@ a *different* entry, you cannot use these techniques."
            (org-agenda-prepare-buffers scope)
            (dolist (file scope)
              (with-current-buffer (org-find-base-buffer-visiting file)
-               (save-excursion
-                 (save-restriction
-                   (widen)
-                   (goto-char (point-min))
-                   (setq res (append res (org-scan-tags func matcher 
todo-only))))))))))
+               (org-with-wide-buffer
+                (goto-char (point-min))
+                (setq res
+                      (append
+                       res
+                       (org-scan-tags
+                        func matcher org--matcher-tags-todo-only)))))))))
       res)))
 
-;;;; Properties
-
-;;; Setting and retrieving properties
+;;; Properties API
 
 (defconst org-special-properties
-  '("TODO" "TAGS" "ALLTAGS" "DEADLINE" "SCHEDULED" "CLOCK" "CLOSED" "PRIORITY"
-    "TIMESTAMP" "TIMESTAMP_IA" "BLOCKED" "FILE" "CLOCKSUM" "CLOCKSUM_T")
-  "The special properties valid in Org-mode.
-
+  '("ALLTAGS" "BLOCKED" "CLOCKSUM" "CLOCKSUM_T" "CLOSED" "DEADLINE" "FILE"
+    "ITEM" "PRIORITY" "SCHEDULED" "TAGS" "TIMESTAMP" "TIMESTAMP_IA" "TODO")
+  "The special properties valid in Org mode.
 These are properties that are not defined in the property drawer,
 but in some other way.")
 
@@ -15112,59 +15603,86 @@ but in some other way.")
     "LOCATION" "LOGGING" "COLUMNS" "VISIBILITY"
     "TABLE_EXPORT_FORMAT" "TABLE_EXPORT_FILE"
     "EXPORT_OPTIONS" "EXPORT_TEXT" "EXPORT_FILE_NAME"
-    "EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE"
+    "EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE" "UNNUMBERED"
     "ORDERED" "NOBLOCKING" "COOKIE_DATA" "LOG_INTO_DRAWER" "REPEAT_TO_STATE"
     "CLOCK_MODELINE_TOTAL" "STYLE" "HTML_CONTAINER_CLASS")
-  "Some properties that are used by Org-mode for various purposes.
+  "Some properties that are used by Org mode for various purposes.
 Being in this list makes sure that they are offered for completion.")
 
-(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
-  "Regular expression matching the first line of a property drawer.")
-
-(defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
-  "Regular expression matching the last line of a property drawer.")
-
-(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$"
-  "Regular expression matching the first line of a property drawer.")
-
-(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$"
-  "Regular expression matching the first line of a property drawer.")
-
-(defconst org-property-drawer-re
-  (concat "\\(" org-property-start-re "\\)[^\000]*\\("
-         org-property-end-re "\\)\n?")
-  "Matches an entire property drawer.")
+(defun org--valid-property-p (property)
+  "Non nil when string PROPERTY is a valid property name."
+  (not
+   (or (equal property "")
+       (string-match-p "\\s-" property))))
+
+(defun org--update-property-plist (key val props)
+  "Associate KEY to VAL in alist PROPS.
+Modifications are made by side-effect.  Return new alist."
+  (let* ((appending (string= (substring key -1) "+"))
+        (key (if appending (substring key 0 -1) key))
+        (old (assoc-string key props t)))
+    (if (not old) (cons (cons key val) props)
+      (setcdr old (if appending (concat (cdr old) " " val) val))
+      props)))
+
+(defun org-get-property-block (&optional beg force)
+  "Return the (beg . end) range of the body of the property drawer.
+BEG is the beginning of the current subtree, or of the part
+before the first headline.  If it is not given, it will be found.
+If the drawer does not exist, create it if FORCE is non-nil, or
+return nil."
+  (org-with-wide-buffer
+   (when beg (goto-char beg))
+   (unless (org-before-first-heading-p)
+     (let ((beg (cond (beg)
+                     ((or (not (featurep 'org-inlinetask))
+                          (org-inlinetask-in-task-p))
+                      (org-back-to-heading t))
+                     (t (org-with-limited-levels (org-back-to-heading t))))))
+       (forward-line)
+       (when (looking-at-p org-planning-line-re) (forward-line))
+       (cond ((looking-at org-property-drawer-re)
+             (forward-line)
+             (cons (point) (progn (goto-char (match-end 0))
+                                  (line-beginning-position))))
+            (force
+             (goto-char beg)
+             (org-insert-property-drawer)
+             (let ((pos (save-excursion (search-forward ":END:")
+                                        (line-beginning-position))))
+               (cons pos pos))))))))
 
-(defconst org-clock-drawer-re
-  (concat "\\(" org-clock-drawer-start-re "\\)[^\000]*\\("
-         org-property-end-re "\\)\n?")
-  "Matches an entire clock drawer.")
+(defun org-at-property-p ()
+  "Non-nil when point is inside a property drawer.
+See `org-property-re' for match data, if applicable."
+  (save-excursion
+    (beginning-of-line)
+    (and (looking-at org-property-re)
+        (let ((property-drawer (save-match-data (org-get-property-block))))
+          (and property-drawer
+               (>= (point) (car property-drawer))
+               (< (point) (cdr property-drawer)))))))
 
 (defun org-property-action ()
   "Do an action on properties."
   (interactive)
-  (let (c)
-    (org-at-property-p)
-    (message "Property Action:  [s]et  [d]elete  [D]elete globally  [c]ompute")
-    (setq c (read-char-exclusive))
-    (cond
-     ((equal c ?s)
-      (call-interactively 'org-set-property))
-     ((equal c ?d)
-      (call-interactively 'org-delete-property))
-     ((equal c ?D)
-      (call-interactively 'org-delete-property-globally))
-     ((equal c ?c)
-      (call-interactively 'org-compute-property-at-point))
-     (t (user-error "No such property action %c" c)))))
+  (unless (org-at-property-p) (user-error "Not at a property"))
+  (message "Property Action:  [s]et  [d]elete  [D]elete globally  [c]ompute")
+  (let ((c (read-char-exclusive)))
+    (cl-case c
+      (?s (call-interactively #'org-set-property))
+      (?d (call-interactively #'org-delete-property))
+      (?D (call-interactively #'org-delete-property-globally))
+      (?c (call-interactively #'org-compute-property-at-point))
+      (otherwise (user-error "No such property action %c" c)))))
 
 (defun org-inc-effort ()
   "Increment the value of the effort property in the current entry."
   (interactive)
   (org-set-effort nil t))
 
-(defvar org-clock-effort)       ;; Defined in org-clock.el
-(defvar org-clock-current-task) ;; Defined in org-clock.el
+(defvar org-clock-effort)       ; Defined in org-clock.el.
+(defvar org-clock-current-task) ; Defined in org-clock.el.
 (defun org-set-effort (&optional value increment)
   "Set the effort property of the current entry.
 With numerical prefix arg, use the nth allowed value, 0 stands for the
@@ -15172,7 +15690,7 @@ With numerical prefix arg, use the nth allowed value, 0 
stands for the
 
 When INCREMENT is non-nil, set the property to the next allowed value."
   (interactive "P")
-  (if (equal value 0) (setq value 10))
+  (when (equal value 0) (setq value 10))
   (let* ((completion-ignore-case t)
         (prop org-effort-property)
         (cur (org-entry-get nil prop))
@@ -15186,7 +15704,7 @@ When INCREMENT is non-nil, set the property to the next 
allowed value."
                (or (car (nth (1- value) allowed))
                    (car (org-last allowed))))
               ((and allowed increment)
-               (or (caadr (member (list cur) allowed))
+               (or (cl-caadr (member (list cur) allowed))
                    (user-error "Allowed effort values are not set")))
               (allowed
                (message "Select 1-9,0, [RET%s]: %s"
@@ -15196,231 +15714,295 @@ When INCREMENT is non-nil, set the property to the 
next allowed value."
                (if (equal rpl ?\r)
                    cur
                  (setq rpl (- rpl ?0))
-                 (if (equal rpl 0) (setq rpl 10))
+                 (when (equal rpl 0) (setq rpl 10))
                  (if (and (> rpl 0) (<= rpl (length allowed)))
                      (car (nth (1- rpl) allowed))
                    (org-completing-read "Effort: " allowed nil))))
               (t
-               (let (org-completion-use-ido org-completion-use-iswitchb)
-                 (org-completing-read
-                  (concat "Effort " (if (and cur (string-match "\\S-" cur))
-                                        (concat "[" cur "]") "")
-                          ": ")
-                  existing nil nil "" nil cur))))))
+               (org-completing-read
+                (concat "Effort" (and cur (string-match "\\S-" cur)
+                                      (concat " [" cur "]"))
+                        ": ")
+                existing nil nil "" nil cur)))))
     (unless (equal (org-entry-get nil prop) val)
       (org-entry-put nil prop val))
-    (save-excursion
-      (org-back-to-heading t)
-      (put-text-property (point-at-bol) (point-at-eol) 'org-effort val))
-    (when (string= heading org-clock-current-task)
-      (setq org-clock-effort (get-text-property (point-at-bol) 'org-effort))
+    (org-refresh-property
+     '((effort . identity)
+       (effort-minutes . org-duration-string-to-minutes))
+     val)
+    (when (equal heading (bound-and-true-p org-clock-current-task))
+      (setq org-clock-effort (get-text-property (point-at-bol) 'effort))
       (org-clock-update-mode-line))
     (message "%s is now %s" prop val)))
 
-(defun org-at-property-p ()
-  "Is cursor inside a property drawer?"
-  (save-excursion
-    (when (equal 'node-property (car (org-element-at-point)))
-      (beginning-of-line 1)
-      (looking-at org-property-re))))
+(defun org-entry-properties (&optional pom which)
+  "Get all properties of the current entry.
+
+When POM is a buffer position, get all properties from the entry
+there instead.
+
+This includes the TODO keyword, the tags, time strings for
+deadline, scheduled, and clocking, and any additional properties
+defined in the entry.
 
-(defun org-get-property-block (&optional beg end force)
-  "Return the (beg . end) range of the body of the property drawer.
-BEG and END are the beginning and end of the current subtree, or of
-the part before the first headline.  If they are not given, they will
-be found.  If the drawer does not exist and FORCE is non-nil, create
-the drawer."
-  (catch 'exit
-    (save-excursion
-      (let* ((beg (or beg (and (org-before-first-heading-p) (point-min))
-                     (progn (org-back-to-heading t) (point))))
-            (end (or end (and (not (outline-next-heading)) (point-max))
-                     (point))))
-       (goto-char beg)
-       (if (re-search-forward org-property-start-re end t)
-           (setq beg (1+ (match-end 0)))
-         (if force
-             (save-excursion
-               (org-insert-property-drawer)
-               (setq end (progn (outline-next-heading) (point))))
-           (throw 'exit nil))
-         (goto-char beg)
-         (if (re-search-forward org-property-start-re end t)
-             (setq beg (1+ (match-end 0)))))
-       (if (re-search-forward org-property-end-re end t)
-           (setq end (match-beginning 0))
-         (or force (throw 'exit nil))
-         (goto-char beg)
-         (setq end beg)
-         (org-indent-line)
-         (insert ":END:\n"))
-       (cons beg end)))))
-
-(defun org-entry-properties (&optional pom which specific)
-  "Get all properties of the entry at point-or-marker POM.
-This includes the TODO keyword, the tags, time strings for deadline,
-scheduled, and clocking, and any additional properties defined in the
-entry.  The return value is an alist, keys may occur multiple times
-if the property key was used several times.
-POM may also be nil, in which case the current entry is used.
 If WHICH is nil or `all', get all properties.  If WHICH is
-`special' or `standard', only get that subclass.  If WHICH
-is a string only get exactly this property.  SPECIFIC can be a string, the
-specific property we are interested in.  Specifying it can speed
-things up because then unnecessary parsing is avoided."
-  (setq which (or which 'all))
-  (org-with-wide-buffer
-   (org-with-point-at pom
-     (let ((clockstr (substring org-clock-string 0 -1))
-          (excluded '("TODO" "TAGS" "ALLTAGS" "PRIORITY" "BLOCKED"))
-          (case-fold-search nil)
-          beg end range props sum-props key key1 value string clocksum 
clocksumt)
-       (when (and (derived-mode-p 'org-mode)
-                 (ignore-errors (org-back-to-heading t)))
-        (setq beg (point))
-        (setq sum-props (get-text-property (point) 'org-summaries))
-        (setq clocksum (get-text-property (point) :org-clock-minutes)
-              clocksumt (get-text-property (point) :org-clock-minutes-today))
-        (outline-next-heading)
-        (setq end (point))
-        (when (memq which '(all special))
-          ;; Get the special properties, like TODO and tags
-          (goto-char beg)
-          (when (and (or (not specific) (string= specific "TODO"))
-                     (looking-at org-todo-line-regexp) (match-end 2))
-            (push (cons "TODO" (org-match-string-no-properties 2)) props))
-          (when (and (or (not specific) (string= specific "PRIORITY"))
-                     (looking-at org-priority-regexp))
-            (push (cons "PRIORITY" (org-match-string-no-properties 2)) props))
-          (when (or (not specific) (string= specific "FILE"))
-            (push (cons "FILE" buffer-file-name) props))
-          (when (and (or (not specific) (string= specific "TAGS"))
-                     (setq value (org-get-tags-string))
-                     (string-match "\\S-" value))
-            (push (cons "TAGS" value) props))
-          (when (and (or (not specific) (string= specific "ALLTAGS"))
-                     (setq value (org-get-tags-at)))
-            (push (cons "ALLTAGS" (concat ":" (mapconcat 'identity value ":")
-                                          ":"))
-                  props))
-          (when (or (not specific) (string= specific "BLOCKED"))
-            (push (cons "BLOCKED" (if (org-entry-blocked-p) "t" "")) props))
-          (when (or (not specific)
-                    (member specific
-                            '("SCHEDULED" "DEADLINE" "CLOCK" "CLOSED"
-                              "TIMESTAMP" "TIMESTAMP_IA")))
-            (catch 'match
-              (while (and (re-search-forward org-maybe-keyword-time-regexp end 
t)
-                          (not (text-property-any 0 (length (match-string 0))
-                                                  'face 'font-lock-comment-face
-                                                  (match-string 0))))
-                (setq key (if (match-end 1)
-                              (substring (org-match-string-no-properties 1)
-                                         0 -1))
-                      string (if (equal key clockstr)
-                                 (org-trim
-                                  (buffer-substring-no-properties
-                                   (match-beginning 3) (goto-char
-                                                        (point-at-eol))))
-                               (substring (org-match-string-no-properties 3)
-                                          1 -1)))
-                ;; Get the correct property name from the key.  This is
-                ;; necessary if the user has configured time keywords.
-                (setq key1 (concat key ":"))
-                (cond
-                 ((not key)
-                  (setq key
-                        (if (= (char-after (match-beginning 3)) ?\[)
-                            "TIMESTAMP_IA" "TIMESTAMP")))
-                 ((equal key1 org-scheduled-string) (setq key "SCHEDULED"))
-                 ((equal key1 org-deadline-string)  (setq key "DEADLINE"))
-                 ((equal key1 org-closed-string)    (setq key "CLOSED"))
-                 ((equal key1 org-clock-string)     (setq key "CLOCK")))
-                (if (and specific (equal key specific) (not (equal key 
"CLOCK")))
-                    (progn
-                      (push (cons key string) props)
-                      ;; no need to search further if match is found
-                      (throw 'match t))
-                  (when (or (equal key "CLOCK") (not (assoc key props)))
-                    (push (cons key string) props)))))))
-
-        (when (memq which '(all standard))
-          ;; Get the standard properties, like :PROP: ...
-          (setq range (org-get-property-block beg end))
-          (when range
-            (goto-char (car range))
-            (while (re-search-forward org-property-re
-                                      (cdr range) t)
-              (setq key (org-match-string-no-properties 2)
-                    value (org-trim (or (org-match-string-no-properties 3) 
"")))
-              (unless (member key excluded)
-                (push (cons key (or value "")) props)))))
-        (if clocksum
-            (push (cons "CLOCKSUM"
-                        (org-columns-number-to-string (/ (float clocksum) 60.)
-                                                      'add_times))
-                  props))
-        (if clocksumt
-            (push (cons "CLOCKSUM_T"
-                        (org-columns-number-to-string (/ (float clocksumt) 60.)
-                                                      'add_times))
-                  props))
-        (unless (assoc "CATEGORY" props)
-          (push (cons "CATEGORY" (org-get-category)) props))
-        (append sum-props (nreverse props)))))))
+`special' or `standard', only get that subclass.  If WHICH is
+a string, only get that property.
+
+Return value is an alist.  Keys are properties, as upcased
+strings."
+  (org-with-point-at pom
+    (when (and (derived-mode-p 'org-mode)
+              (ignore-errors (org-back-to-heading t)))
+      (catch 'exit
+       (let* ((beg (point))
+              (specific (and (stringp which) (upcase which)))
+              (which (cond ((not specific) which)
+                           ((member specific org-special-properties) 'special)
+                           (t 'standard)))
+              props)
+         ;; Get the special properties, like TODO and TAGS.
+         (when (memq which '(nil all special))
+           (when (or (not specific) (string= specific "CLOCKSUM"))
+             (let ((clocksum (get-text-property (point) :org-clock-minutes)))
+               (when clocksum
+                 (push (cons "CLOCKSUM"
+                             (org-minutes-to-clocksum-string clocksum))
+                       props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "CLOCKSUM_T"))
+             (let ((clocksumt (get-text-property (point)
+                                                 :org-clock-minutes-today)))
+               (when clocksumt
+                 (push (cons "CLOCKSUM_T"
+                             (org-minutes-to-clocksum-string clocksumt))
+                       props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "ITEM"))
+             (let ((case-fold-search nil))
+               (when (looking-at org-complex-heading-regexp)
+                 (push (cons "ITEM"
+                             (let ((title (match-string-no-properties 4)))
+                               (if (org-string-nw-p title)
+                                   (org-remove-tabs title)
+                                 "")))
+                       props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "TODO"))
+             (let ((case-fold-search nil))
+               (when (and (looking-at org-todo-line-regexp) (match-end 2))
+                 (push (cons "TODO" (match-string-no-properties 2)) props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "PRIORITY"))
+             (push (cons "PRIORITY"
+                         (if (looking-at org-priority-regexp)
+                             (match-string-no-properties 2)
+                           (char-to-string org-default-priority)))
+                   props)
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "FILE"))
+             (push (cons "FILE" (buffer-file-name (buffer-base-buffer)))
+                   props)
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "TAGS"))
+             (let ((value (org-string-nw-p (org-get-tags-string))))
+               (when value (push (cons "TAGS" value) props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "ALLTAGS"))
+             (let ((value (org-get-tags-at)))
+               (when value
+                 (push (cons "ALLTAGS"
+                             (format ":%s:" (mapconcat #'identity value ":")))
+                       props)))
+             (when specific (throw 'exit props)))
+           (when (or (not specific) (string= specific "BLOCKED"))
+             (push (cons "BLOCKED" (if (org-entry-blocked-p) "t" "")) props)
+             (when specific (throw 'exit props)))
+           (when (or (not specific)
+                     (member specific '("CLOSED" "DEADLINE" "SCHEDULED")))
+             (forward-line)
+             (when (looking-at-p org-planning-line-re)
+               (end-of-line)
+               (let ((bol (line-beginning-position))
+                     ;; Backward compatibility: time keywords used to
+                     ;; be configurable (before 8.3).  Make sure we
+                     ;; get the correct keyword.
+                     (key-assoc `(("CLOSED" . ,org-closed-string)
+                                  ("DEADLINE" . ,org-deadline-string)
+                                  ("SCHEDULED" . ,org-scheduled-string))))
+                 (dolist (pair (if specific (list (assoc specific key-assoc))
+                                 key-assoc))
+                   (save-excursion
+                     (when (search-backward (cdr pair) bol t)
+                       (goto-char (match-end 0))
+                       (skip-chars-forward " \t")
+                       (and (looking-at org-ts-regexp-both)
+                            (push (cons (car pair)
+                                        (match-string-no-properties 0))
+                                  props)))))))
+             (when specific (throw 'exit props)))
+           (when (or (not specific)
+                     (member specific '("TIMESTAMP" "TIMESTAMP_IA")))
+             (let ((find-ts
+                    (lambda (end ts)
+                      ;; Fix next time-stamp before END.  TS is the
+                      ;; list of time-stamps found so far.
+                      (let ((ts ts)
+                            (regexp (cond
+                                     ((string= specific "TIMESTAMP")
+                                      org-ts-regexp)
+                                     ((string= specific "TIMESTAMP_IA")
+                                      org-ts-regexp-inactive)
+                                     ((assoc "TIMESTAMP_IA" ts)
+                                      org-ts-regexp)
+                                     ((assoc "TIMESTAMP" ts)
+                                      org-ts-regexp-inactive)
+                                     (t org-ts-regexp-both))))
+                        (catch 'next
+                          (while (re-search-forward regexp end t)
+                            (backward-char)
+                            (let ((object (org-element-context)))
+                              ;; Accept to match timestamps in node
+                              ;; properties, too.
+                              (when (memq (org-element-type object)
+                                          '(node-property timestamp))
+                                (let ((type
+                                       (org-element-property :type object)))
+                                  (cond
+                                   ((and (memq type '(active active-range))
+                                         (not (equal specific "TIMESTAMP_IA")))
+                                    (unless (assoc "TIMESTAMP" ts)
+                                      (push (cons "TIMESTAMP"
+                                                  (org-element-property
+                                                   :raw-value object))
+                                            ts)
+                                      (when specific (throw 'exit ts))))
+                                   ((and (memq type '(inactive inactive-range))
+                                         (not (string= specific "TIMESTAMP")))
+                                    (unless (assoc "TIMESTAMP_IA" ts)
+                                      (push (cons "TIMESTAMP_IA"
+                                                  (org-element-property
+                                                   :raw-value object))
+                                            ts)
+                                      (when specific (throw 'exit ts))))))
+                                ;; Both timestamp types are found,
+                                ;; move to next part.
+                                (when (= (length ts) 2) (throw 'next ts)))))
+                          ts)))))
+               (goto-char beg)
+               ;; First look for timestamps within headline.
+               (let ((ts (funcall find-ts (line-end-position) nil)))
+                 (if (= (length ts) 2) (setq props (nconc ts props))
+                   ;; Then find timestamps in the section, skipping
+                   ;; planning line.
+                   (let ((end (save-excursion (outline-next-heading))))
+                     (forward-line)
+                     (when (looking-at-p org-planning-line-re) (forward-line))
+                     (setq props (nconc (funcall find-ts end ts) props))))))))
+         ;; Get the standard properties, like :PROP:.
+         (when (memq which '(nil all standard))
+           ;; If we are looking after a specific property, delegate
+           ;; to `org-entry-get', which is faster.  However, make an
+           ;; exception for "CATEGORY", since it can be also set
+           ;; through keywords (i.e. #+CATEGORY).
+           (if (and specific (not (equal specific "CATEGORY")))
+               (let ((value (org-entry-get beg specific nil t)))
+                 (throw 'exit (and value (list (cons specific value)))))
+             (let ((range (org-get-property-block beg)))
+               (when range
+                 (let ((end (cdr range)) seen-base)
+                   (goto-char (car range))
+                   ;; Unlike to `org--update-property-plist', we
+                   ;; handle the case where base values is found
+                   ;; after its extension.  We also forbid standard
+                   ;; properties to be named as special properties.
+                   (while (re-search-forward org-property-re end t)
+                     (let* ((key (upcase (match-string-no-properties 2)))
+                            (extendp (string-match-p "\\+\\'" key))
+                            (key-base (if extendp (substring key 0 -1) key))
+                            (value (match-string-no-properties 3)))
+                       (cond
+                        ((member-ignore-case key-base org-special-properties))
+                        (extendp
+                         (setq props
+                               (org--update-property-plist key value props)))
+                        ((member key seen-base))
+                        (t (push key seen-base)
+                           (let ((p (assoc-string key props t)))
+                             (if p (setcdr p (concat value " " (cdr p)))
+                               (push (cons key value) props))))))))))))
+         (unless (assoc "CATEGORY" props)
+           (push (cons "CATEGORY" (org-get-category beg)) props)
+           (when (string= specific "CATEGORY") (throw 'exit props)))
+         ;; Return value.
+         props)))))
+
+(defun org--property-local-values (property literal-nil)
+  "Return value for PROPERTY in current entry.
+Value is a list whose car is the base value for PROPERTY and cdr
+a list of accumulated values.  Return nil if neither is found in
+the entry.  Also return nil when PROPERTY is set to \"nil\",
+unless LITERAL-NIL is non-nil."
+  (let ((range (org-get-property-block)))
+    (when range
+      (goto-char (car range))
+      (let* ((case-fold-search t)
+            (end (cdr range))
+            (value
+             ;; Base value.
+             (save-excursion
+               (let ((v (and (re-search-forward
+                              (org-re-property property nil t) end t)
+                             (match-string-no-properties 3))))
+                 (list (if literal-nil v (org-not-nil v)))))))
+       ;; Find additional values.
+       (let* ((property+ (org-re-property (concat property "+") nil t)))
+         (while (re-search-forward property+ end t)
+           (push (match-string-no-properties 3) value)))
+       ;; Return final values.
+       (and (not (equal value '(nil))) (nreverse value))))))
+
+(defun org--property-global-value (property literal-nil)
+  "Return value for PROPERTY in current buffer.
+Return value is a string.  Return nil if property is not set
+globally.  Also return nil when PROPERTY is set to \"nil\",
+unless LITERAL-NIL is non-nil."
+  (let ((global
+        (cdr (or (assoc-string property org-file-properties t)
+                 (assoc-string property org-global-properties t)
+                 (assoc-string property org-global-properties-fixed t)))))
+    (if literal-nil global (org-not-nil global))))
 
 (defun org-entry-get (pom property &optional inherit literal-nil)
   "Get value of PROPERTY for entry or content at point-or-marker POM.
-If INHERIT is non-nil and the entry does not have the property,
-then also check higher levels of the hierarchy.
-If INHERIT is the symbol `selective', use inheritance only if the setting
-in `org-use-property-inheritance' selects PROPERTY for inheritance.
-If the property is present but empty, the return value is the empty string.
-If the property is not present at all, nil is returned.
-
-Return the value as a string.
 
-If LITERAL-NIL is set, return the string value \"nil\" as a string,
-do not interpret it as the list atom nil.  This is used for inheritance
-when a \"nil\" value can supersede a non-nil value higher up the hierarchy."
+If INHERIT is non-nil and the entry does not have the property,
+then also check higher levels of the hierarchy.  If INHERIT is
+the symbol `selective', use inheritance only if the setting in
+`org-use-property-inheritance' selects PROPERTY for inheritance.
+
+If the property is present but empty, the return value is the
+empty string.  If the property is not present at all, nil is
+returned.  In any other case, return the value as a string.
+Search is case-insensitive.
+
+If LITERAL-NIL is set, return the string value \"nil\" as
+a string, do not interpret it as the list atom nil.  This is used
+for inheritance when a \"nil\" value can supersede a non-nil
+value higher up the hierarchy."
   (org-with-point-at pom
-    (if (and inherit (if (eq inherit 'selective)
-                        (org-property-inherit-p property)
-                      t))
-       (org-entry-get-with-inheritance property literal-nil)
-      (if (member property org-special-properties)
-         ;; We need a special property.  Use `org-entry-properties'
-         ;; to retrieve it, but specify the wanted property
-         (cdr (assoc property (org-entry-properties nil 'special property)))
-       (org-with-wide-buffer
-        (let ((range (org-get-property-block)))
-          (when (and range (not (eq (car range) (cdr range)))
-                     (save-excursion
-                       (goto-char (car range))
-                       (re-search-forward
-                        (concat (org-re-property property) "\\|"
-                                (org-re-property (concat property "+")))
-                        (cdr range) t)))
-            (let* ((props
-                    (list (or (assoc property org-file-properties)
-                              (assoc property org-global-properties)
-                              (assoc property org-global-properties-fixed))))
-                   (ap (lambda (key)
-                         (when (re-search-forward
-                                (org-re-property key) (cdr range) t)
-                           (setq props
-                                 (org-update-property-plist
-                                  key
-                                  (if (match-end 3)
-                                      (org-match-string-no-properties 3) "")
-                                  props)))))
-                   val)
-              (goto-char (car range))
-              (funcall ap property)
-              (goto-char (car range))
-              (while (funcall ap (concat property "+")))
-              (setq val (cdr (assoc property props)))
-              (when val (if literal-nil val (org-not-nil val)))))))))))
+    (cond
+     ((member-ignore-case property (cons "CATEGORY" org-special-properties))
+      ;; We need a special property.  Use `org-entry-properties' to
+      ;; retrieve it, but specify the wanted property.
+      (cdr (assoc-string property (org-entry-properties nil property))))
+     ((and inherit
+          (or (not (eq inherit 'selective)) (org-property-inherit-p property)))
+      (org-entry-get-with-inheritance property literal-nil))
+     (t
+      (let* ((local (org--property-local-values property literal-nil))
+            (value (and local (mapconcat #'identity (delq nil local) " "))))
+       (if literal-nil value (org-not-nil value)))))))
 
 (defun org-property-or-variable-value (var &optional inherit)
   "Check if there is a property fixing the value of VAR.
@@ -15430,26 +16012,26 @@ If yes, return this value.  If not, return the 
current value of the variable."
        (read prop)
       (symbol-value var))))
 
-(defun org-entry-delete (pom property &optional delete-empty-drawer)
-  "Delete the property PROPERTY from entry at point-or-marker POM.
-When optional argument DELETE-EMPTY-DRAWER is a string, it defines
-an empty drawer to delete."
+(defun org-entry-delete (pom property)
+  "Delete PROPERTY from entry at point-or-marker POM.
+Accumulated properties, i.e. PROPERTY+, are also removed.  Return
+non-nil when a property was removed."
   (org-with-point-at pom
-    (if (member property org-special-properties)
-       nil ; cannot delete these properties.
-      (let ((range (org-get-property-block)))
-       (if (and range
-                (goto-char (car range))
-                (re-search-forward
-                 (org-re-property property nil t)
-                 (cdr range) t))
-           (progn
-             (delete-region (match-beginning 0) (1+ (point-at-eol)))
-             (and delete-empty-drawer
-                  (org-remove-empty-drawer-at
-                   delete-empty-drawer (car range)))
-             t)
-         nil)))))
+    (pcase (org-get-property-block)
+      (`(,begin . ,origin)
+       (let* ((end (copy-marker origin))
+             (re (org-re-property
+                  (concat (regexp-quote property) "\\+?") t t)))
+        (goto-char begin)
+        (while (re-search-forward re end t)
+          (delete-region (match-beginning 0) (line-beginning-position 2)))
+        ;; If drawer is empty, remove it altogether.
+        (when (= begin end)
+          (delete-region (line-beginning-position 0)
+                         (line-beginning-position 2)))
+        ;; Return non-nil if some property was removed.
+        (prog1 (/= end origin) (set-marker end nil))))
+      (_ nil))))
 
 ;; Multi-values properties are properties that contain multiple values
 ;; These values are assumed to be single words, separated by whitespace.
@@ -15526,24 +16108,29 @@ If the value found is \"nil\", return nil to show 
that the property
 should be considered as undefined (this is the meaning of nil here).
 However, if LITERAL-NIL is set, return the string value \"nil\" instead."
   (move-marker org-entry-property-inherited-from nil)
-  (let (tmp)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (catch 'ex
-         (while t
-           (when (setq tmp (org-entry-get nil property nil literal-nil))
-             (or (ignore-errors (org-back-to-heading t))
-                 (goto-char (point-min)))
-             (move-marker org-entry-property-inherited-from (point))
-             (throw 'ex tmp))
-           (or (ignore-errors (org-up-heading-safe))
-               (throw 'ex nil))))))
-    (setq tmp (or tmp
-                 (cdr (assoc property org-file-properties))
-                 (cdr (assoc property org-global-properties))
-                 (cdr (assoc property org-global-properties-fixed))))
-    (if literal-nil tmp (org-not-nil tmp))))
+  (org-with-wide-buffer
+   (let (value)
+     (catch 'exit
+       (while t
+        (let ((v (org--property-local-values property literal-nil)))
+          (when v
+            (setq value
+                  (concat (mapconcat #'identity (delq nil v) " ")
+                          (and value " ")
+                          value)))
+          (cond
+           ((car v)
+            (org-back-to-heading t)
+            (move-marker org-entry-property-inherited-from (point))
+            (throw 'exit nil))
+           ((org-up-heading-safe))
+           (t
+            (let ((global (org--property-global-value property literal-nil)))
+              (cond ((not global))
+                    (value (setq value (concat global " " value)))
+                    (t (setq value global))))
+            (throw 'exit nil))))))
+     (if literal-nil value (org-not-nil value)))))
 
 (defvar org-property-changed-functions nil
   "Hook called when the value of a property has changed.
@@ -15552,177 +16139,188 @@ and the new value.")
 
 (defun org-entry-put (pom property value)
   "Set PROPERTY to VALUE for entry at point-or-marker POM.
-If the value is nil, it is converted to the empty string.
-If it is not a string, an error is raised."
+
+If the value is nil, it is converted to the empty string.  If it
+is not a string, an error is raised.  Also raise an error on
+invalid property names.
+
+PROPERTY can be any regular property (see
+`org-special-properties').  It can also be \"TODO\",
+\"PRIORITY\", \"SCHEDULED\" and \"DEADLINE\".
+
+For the last two properties, VALUE may have any of the special
+values \"earlier\" and \"later\".  The function then increases or
+decreases scheduled or deadline date by one day."
   (cond ((null value) (setq value ""))
-       ((not (stringp value))
-        (error "Properties values should be strings.")))
+       ((not (stringp value)) (error "Properties values should be strings"))
+       ((not (org--valid-property-p property))
+        (user-error "Invalid property name: \"%s\"" property)))
   (org-with-point-at pom
-    (org-back-to-heading t)
-    (let ((beg (point)) (end (save-excursion (outline-next-heading) (point)))
-         range)
+    (if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p))
+       (org-back-to-heading t)
+      (org-with-limited-levels (org-back-to-heading t)))
+    (let ((beg (point)))
       (cond
        ((equal property "TODO")
-       (when (and (string-match "\\S-" value)
-                  (not (member value org-todo-keywords-1)))
-         (user-error "\"%s\" is not a valid TODO state" value))
-       (if (or (not value)
-               (not (string-match "\\S-" value)))
-           (setq value 'none))
+       (cond ((not (org-string-nw-p value)) (setq value 'none))
+             ((not (member value org-todo-keywords-1))
+              (user-error "\"%s\" is not a valid TODO state" value)))
        (org-todo value)
        (org-set-tags nil 'align))
        ((equal property "PRIORITY")
-       (org-priority (if (and value (string-match "\\S-" value))
-                         (string-to-char value) ?\ ))
+       (org-priority (if (org-string-nw-p value) (string-to-char value) ?\s))
        (org-set-tags nil 'align))
-       ((equal property "CLOCKSUM")
-       (if (not (re-search-forward
-                 (concat org-clock-string ".*\\]--\\(\\[[^]]+\\]\\)") nil t))
-           (error "Cannot find a clock log")
-         (goto-char (- (match-end 1) 2))
-         (cond
-          ((eq value 'earlier) (org-timestamp-down))
-          ((eq value 'later) (org-timestamp-up)))
-         (org-clock-sum-current-item)))
        ((equal property "SCHEDULED")
-       (if (re-search-forward org-scheduled-time-regexp end t)
-           (cond
-            ((eq value 'earlier) (org-timestamp-change -1 'day))
-            ((eq value 'later) (org-timestamp-change 1 'day))
-            (t (call-interactively 'org-schedule)))
-         (call-interactively 'org-schedule)))
+       (forward-line)
+       (if (and (looking-at-p org-planning-line-re)
+                (re-search-forward
+                 org-scheduled-time-regexp (line-end-position) t))
+           (cond ((string= value "earlier") (org-timestamp-change -1 'day))
+                 ((string= value "later") (org-timestamp-change 1 'day))
+                 ((string= value "") (org-schedule '(4)))
+                 (t (org-schedule nil value)))
+         (if (member value '("earlier" "later" ""))
+             (call-interactively #'org-schedule)
+           (org-schedule nil value))))
        ((equal property "DEADLINE")
-       (if (re-search-forward org-deadline-time-regexp end t)
-           (cond
-            ((eq value 'earlier) (org-timestamp-change -1 'day))
-            ((eq value 'later) (org-timestamp-change 1 'day))
-            (t (call-interactively 'org-deadline)))
-         (call-interactively 'org-deadline)))
+       (forward-line)
+       (if (and (looking-at-p org-planning-line-re)
+                (re-search-forward
+                 org-deadline-time-regexp (line-end-position) t))
+           (cond ((string= value "earlier") (org-timestamp-change -1 'day))
+                 ((string= value "later") (org-timestamp-change 1 'day))
+                 ((string= value "") (org-deadline '(4)))
+                 (t (org-deadline nil value)))
+         (if (member value '("earlier" "later" ""))
+             (call-interactively #'org-deadline)
+           (org-deadline nil value))))
        ((member property org-special-properties)
-       (error "The %s property can not yet be set with `org-entry-put'"
-              property))
-       (t ; a non-special property
-       (let ((buffer-invisibility-spec (org-inhibit-invisibility))) ; Emacs 21
-         (setq range (org-get-property-block beg end 'force))
+       (error "The %s property cannot be set with `org-entry-put'" property))
+       (t
+       (let* ((range (org-get-property-block beg 'force))
+              (end (cdr range))
+              (case-fold-search t))
          (goto-char (car range))
-         (if (re-search-forward
-              (org-re-property property nil t) (cdr range) t)
-             (progn
-               (delete-region (match-beginning 0) (match-end 0))
-               (goto-char (match-beginning 0)))
-           (goto-char (cdr range))
+         (if (re-search-forward (org-re-property property nil t) end t)
+             (progn (delete-region (match-beginning 0) (match-end 0))
+                    (goto-char (match-beginning 0)))
+           (goto-char end)
            (insert "\n")
-           (backward-char 1)
-           (org-indent-line))
+           (backward-char))
          (insert ":" property ":")
-         (and value (insert " " value))
+         (when value (insert " " value))
          (org-indent-line)))))
     (run-hook-with-args 'org-property-changed-functions property value)))
 
-(defun org-buffer-property-keys (&optional include-specials include-defaults 
include-columns)
+(defun org-buffer-property-keys
+    (&optional specials defaults columns ignore-malformed)
   "Get all property keys in the current buffer.
-With INCLUDE-SPECIALS, also list the special properties that reflect things
-like tags and TODO state.
-With INCLUDE-DEFAULTS, also include properties that has special meaning
-internally: ARCHIVE, CATEGORY, SUMMARY, DESCRIPTION, LOCATION, and LOGGING
-and others.
-With INCLUDE-COLUMNS, also include property names given in COLUMN
-formats in the current buffer."
-  (let (rtn range cfmt s p)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (while (re-search-forward org-property-start-re nil t)
-         (setq range (org-get-property-block))
-         (goto-char (car range))
-         (while (re-search-forward org-property-re
-                 (cdr range) t)
-           (add-to-list 'rtn (org-match-string-no-properties 2)))
-         (outline-next-heading))))
 
-    (when include-specials
-      (setq rtn (append org-special-properties rtn)))
+When SPECIALS is non-nil, also list the special properties that
+reflect things like tags and TODO state.
 
-    (when include-defaults
-      (mapc (lambda (x) (add-to-list 'rtn x)) org-default-properties)
-      (add-to-list 'rtn org-effort-property))
+When DEFAULTS is non-nil, also include properties that has
+special meaning internally: ARCHIVE, CATEGORY, SUMMARY,
+DESCRIPTION, LOCATION, and LOGGING and others.
 
-    (when include-columns
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (while (re-search-forward
-                 "^\\(#\\+COLUMNS:\\|[ \t]*:COLUMNS:\\)[ \t]*\\(.*\\)"
-                 nil t)
-           (setq cfmt (match-string 2) s 0)
-           (while (string-match (org-re "%[0-9]*\\([-[:alnum:]_]+\\)")
-                                cfmt s)
-             (setq s (match-end 0)
-                   p (match-string 1 cfmt))
-             (unless (or (equal p "ITEM")
-                         (member p org-special-properties))
-               (add-to-list 'rtn (match-string 1 cfmt))))))))
-
-    (sort rtn (lambda (a b) (string< (upcase a) (upcase b))))))
+When COLUMNS in non-nil, also include property names given in
+COLUMN formats in the current buffer.
+
+When IGNORE-MALFORMED is non-nil, malformed drawer repair will not be
+automatically performed, such drawers will be silently ignored."
+  (let ((case-fold-search t)
+       (props (append
+               (and specials org-special-properties)
+               (and defaults (cons org-effort-property org-default-properties))
+               nil)))
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (while (re-search-forward org-property-start-re nil t)
+       (let ((range (org-get-property-block)))
+        (catch 'skip
+          (unless range
+            (when (and (not ignore-malformed)
+                       (not (org-before-first-heading-p))
+                       (y-or-n-p (format "Malformed drawer at %d, repair?"
+                                         (line-beginning-position))))
+              (org-get-property-block nil t))
+            (throw 'skip nil))
+          (goto-char (car range))
+          (let ((begin (car range))
+                (end (cdr range)))
+            ;; Make sure that found property block is not located
+            ;; before current point, as it would generate an infloop.
+            ;; It can happen, for example, in the following
+            ;; situation:
+            ;;
+            ;; * Headline
+            ;;   :PROPERTIES:
+            ;;   ...
+            ;;   :END:
+            ;; *************** Inlinetask
+            ;; #+BEGIN_EXAMPLE
+            ;; :PROPERTIES:
+            ;; #+END_EXAMPLE
+            ;;
+            (if (< begin (point)) (throw 'skip nil) (goto-char begin))
+            (while (< (point) end)
+              (let ((p (progn (looking-at org-property-re)
+                              (match-string-no-properties 2))))
+                ;; Only add true property name, not extension symbol.
+                (push (if (not (string-match-p "\\+\\'" p)) p
+                        (substring p 0 -1))
+                      props))
+              (forward-line))))
+        (outline-next-heading)))
+     (when columns
+       (goto-char (point-min))
+       (while (re-search-forward "^[ \t]*\\(?:#\\+\\|:\\)COLUMNS:" nil t)
+        (let ((element (org-element-at-point)))
+          (when (memq (org-element-type element) '(keyword node-property))
+            (let ((value (org-element-property :value element))
+                  (start 0))
+              (while (string-match "%[0-9]*\\(\\S-+\\)" value start)
+                (setq start (match-end 0))
+                (let ((p (match-string-no-properties 1 value)))
+                  (unless (member-ignore-case p org-special-properties)
+                    (push p props))))))))))
+    (sort (delete-dups props) (lambda (a b) (string< (upcase a) (upcase b))))))
 
 (defun org-property-values (key)
-  "Return a list of all values of property KEY in the current buffer."
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (let ((re (org-re-property key))
-           values)
-       (while (re-search-forward re nil t)
-         (add-to-list 'values (org-trim (match-string 3))))
-       (delete "" values)))))
+  "List all non-nil values of property KEY in current buffer."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let ((case-fold-search t)
+        (re (org-re-property key))
+        values)
+     (while (re-search-forward re nil t)
+       (push (org-entry-get (point) key) values))
+     (delete-dups values))))
 
 (defun org-insert-property-drawer ()
   "Insert a property drawer into the current entry."
-  (org-back-to-heading t)
-  (looking-at org-outline-regexp)
-  (let ((indent (if org-adapt-indentation
-                   (- (match-end 0) (match-beginning 0))
-                 0))
-       (beg (point))
-       (re (concat "^[ \t]*" org-keyword-time-regexp))
-       end hiddenp)
-    (outline-next-heading)
-    (setq end (point))
-    (goto-char beg)
-    (while (re-search-forward re end t))
-    (setq hiddenp (outline-invisible-p))
-    (end-of-line 1)
-    (and (equal (char-after) ?\n) (forward-char 1))
-    (while (looking-at "^[ \t]*\\(:CLOCK:\\|:LOGBOOK:\\|CLOCK:\\|:END:\\)")
-      (if (member (match-string 1) '("CLOCK:" ":END:"))
-         ;; just skip this line
-         (beginning-of-line 2)
-       ;; Drawer start, find the end
-       (re-search-forward "^\\*+ \\|^[ \t]*:END:" nil t)
-       (beginning-of-line 1)))
-    (org-skip-over-state-notes)
-    (skip-chars-backward " \t\n\r")
-    (if (and (eq (char-before) ?*) (not (eq (char-after) ?\n)))
-       (forward-char 1))
-    (goto-char (point-at-eol))
-    (let ((inhibit-read-only t)) (insert "\n:PROPERTIES:\n:END:"))
-    (beginning-of-line 0)
-    (org-indent-to-column indent)
-    (beginning-of-line 2)
-    (org-indent-to-column indent)
-    (beginning-of-line 0)
-    (if hiddenp
-       (save-excursion
-         (org-back-to-heading t)
-         (hide-entry))
-      (org-flag-drawer t))))
+  (org-with-wide-buffer
+   (if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p))
+       (org-back-to-heading t)
+     (org-with-limited-levels (org-back-to-heading t)))
+   (forward-line)
+   (when (looking-at-p org-planning-line-re) (forward-line))
+   (unless (looking-at-p org-property-drawer-re)
+     ;; Make sure we start editing a line from current entry, not from
+     ;; next one.  It prevents extending text properties or overlays
+     ;; belonging to the latter.
+     (when (bolp) (backward-char))
+     (let ((begin (1+ (point)))
+          (inhibit-read-only t))
+       (insert "\n:PROPERTIES:\n:END:")
+       (when (eobp) (insert "\n"))
+       (org-indent-region begin (point))))))
 
 (defun org-insert-drawer (&optional arg drawer)
   "Insert a drawer at point.
 
+When optional argument ARG is non-nil, insert a property drawer.
+
 Optional argument DRAWER, when non-nil, is a string representing
 drawer's name.  Otherwise, the user is prompted for a name.
 
@@ -15731,23 +16329,14 @@ instead.
 
 Point is left between drawer's boundaries."
   (interactive "P")
-  (let* ((logbook (if (stringp org-log-into-drawer) org-log-into-drawer
-                   "LOGBOOK"))
-        ;; SYSTEM-DRAWERS is a list of drawer names that are used
-        ;; internally by Org.  They are meant to be inserted
-        ;; automatically.
-        (system-drawers `("CLOCK" ,logbook "PROPERTIES"))
-        ;; Remove system drawers from list.  Note: For some reason,
-        ;; `org-completing-read' ignores the predicate while
-        ;; `completing-read' handles it fine.
-        (drawer (if arg "PROPERTIES"
-                  (or drawer
-                      (completing-read
-                       "Drawer: " org-drawers
-                       (lambda (d) (not (member d system-drawers))))))))
+  (let* ((drawer (if arg "PROPERTIES"
+                  (or drawer (read-from-minibuffer "Drawer: ")))))
     (cond
      ;; With C-u, fall back on `org-insert-property-drawer'
      (arg (org-insert-property-drawer))
+     ;; Check validity of suggested drawer's name.
+     ((not (string-match-p org-drawer-regexp (format ":%s:" drawer)))
+      (user-error "Invalid drawer name"))
      ;; With an active region, insert a drawer at point.
      ((not (org-region-active-p))
       (progn
@@ -15813,38 +16402,25 @@ This is computed according to 
`org-property-set-functions-alist'."
                  (funcall set-function prompt allowed nil
                           (not (get-text-property 0 'org-unrestricted
                                                   (caar allowed))))
-               (let (org-completion-use-ido org-completion-use-iswitchb)
-                 (funcall set-function prompt
-                          (mapcar 'list (org-property-values property))
-                          nil nil "" nil cur)))))
+               (funcall set-function prompt
+                        (mapcar 'list (org-property-values property))
+                        nil nil "" nil cur))))
     (org-trim val)))
 
 (defvar org-last-set-property nil)
 (defvar org-last-set-property-value nil)
 (defun org-read-property-name ()
   "Read a property name."
-  (let* ((completion-ignore-case t)
-        (keys (org-buffer-property-keys nil t t))
-        (default-prop (or (save-excursion
-                            (save-match-data
-                              (beginning-of-line)
-                              (and (looking-at "^\\s-*:\\([^:\n]+\\):")
-                                   (null (string= (match-string 1) "END"))
-                                   (match-string 1))))
-                          org-last-set-property))
-        (property (org-icompleting-read
-                   (concat "Property"
-                           (if default-prop (concat " [" default-prop "]") "")
-                           ": ")
-                   (mapcar 'list keys)
-                   nil nil nil nil
-                   default-prop)))
-    (if (member property keys)
-       property
-      (or (cdr (assoc (downcase property)
-                     (mapcar (lambda (x) (cons (downcase x) x))
-                             keys)))
-         property))))
+  (let ((completion-ignore-case t)
+       (default-prop (or (and (org-at-property-p)
+                              (match-string-no-properties 2))
+                         org-last-set-property)))
+    (org-completing-read
+     (concat "Property"
+            (if default-prop (concat " [" default-prop "]") "")
+            ": ")
+     (mapcar #'list (org-buffer-property-keys nil t t))
+     nil nil nil nil default-prop)))
 
 (defun org-set-property-and-value (use-last)
   "Allow to set [PROPERTY]: [value] direction from prompt.
@@ -15865,26 +16441,52 @@ When use-default, don't even ask, just use the last
 
 (defun org-set-property (property value)
   "In the current entry, set PROPERTY to VALUE.
+
 When called interactively, this will prompt for a property name, offering
 completion on existing and default properties.  And then it will prompt
 for a value, offering completion either on allowed values (via an inherited
 xxx_ALL property) or on existing values in other instances of this property
-in the current file."
+in the current file.
+
+Throw an error when trying to set a property with an invalid name."
   (interactive (list nil nil))
-  (let* ((property (or property (org-read-property-name)))
-        (value (or value (org-read-property-value property)))
-        (fn (cdr (assoc property org-properties-postprocess-alist))))
-    (setq org-last-set-property property)
-    (setq org-last-set-property-value (concat property ": " value))
-    ;; Possibly postprocess the inserted value:
-    (when fn (setq value (funcall fn value)))
-    (unless (equal (org-entry-get nil property) value)
-      (org-entry-put nil property value))))
-
-(defun org-delete-property (property &optional delete-empty-drawer)
-  "In the current entry, delete PROPERTY.
-When optional argument DELETE-EMPTY-DRAWER is a string, it defines
-an empty drawer to delete."
+  (let ((property (or property (org-read-property-name))))
+    ;; `org-entry-put' also makes the following check, but this one
+    ;; avoids polluting `org-last-set-property' and
+    ;; `org-last-set-property-value' needlessly.
+    (unless (org--valid-property-p property)
+      (user-error "Invalid property name: \"%s\"" property))
+    (let ((value (or value (org-read-property-value property)))
+         (fn (cdr (assoc-string property org-properties-postprocess-alist t))))
+      (setq org-last-set-property property)
+      (setq org-last-set-property-value (concat property ": " value))
+      ;; Possibly postprocess the inserted value:
+      (when fn (setq value (funcall fn value)))
+      (unless (equal (org-entry-get nil property) value)
+       (org-entry-put nil property value)))))
+
+(defun org-find-property (property &optional value)
+  "Find first entry in buffer that sets PROPERTY.
+
+When optional argument VALUE is non-nil, only consider an entry
+if it contains PROPERTY set to this value.  If PROPERTY should be
+explicitly set to nil, use string \"nil\" for VALUE.
+
+Return position where the entry begins, or nil if there is no
+such entry.  If narrowing is in effect, only search the visible
+part of the buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((case-fold-search t)
+         (re (org-re-property property nil (not value) value)))
+      (catch 'exit
+       (while (re-search-forward re nil t)
+         (when (if value (org-at-property-p)
+                 (org-entry-get (point) property nil t))
+           (throw 'exit (progn (org-back-to-heading t) (point)))))))))
+
+(defun org-delete-property (property)
+  "In the current entry, delete PROPERTY."
   (interactive
    (let* ((completion-ignore-case t)
          (cat (org-entry-get (point) "CATEGORY"))
@@ -15892,33 +16494,30 @@ an empty drawer to delete."
          (props (if cat props0
                   (delete `("CATEGORY" . ,(org-get-category)) props0)))
          (prop (if (< 1 (length props))
-                   (org-icompleting-read "Property: " props nil t)
+                   (completing-read "Property: " props nil t)
                  (caar props))))
      (list prop)))
   (if (not property)
       (message "No property to delete in this entry")
-    (org-entry-delete nil property delete-empty-drawer)
+    (org-entry-delete nil property)
     (message "Property \"%s\" deleted" property)))
 
 (defun org-delete-property-globally (property)
-  "Remove PROPERTY globally, from all entries."
+  "Remove PROPERTY globally, from all entries.
+This function ignores narrowing, if any."
   (interactive
    (let* ((completion-ignore-case t)
-         (prop (org-icompleting-read
+         (prop (completing-read
                 "Globally remove property: "
-                (mapcar 'list (org-buffer-property-keys)))))
+                (mapcar #'list (org-buffer-property-keys)))))
      (list prop)))
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (let ((cnt 0))
-       (while (re-search-forward
-               (org-re-property property)
-               nil t)
-         (setq cnt (1+ cnt))
-         (delete-region (match-beginning 0) (1+ (point-at-eol))))
-       (message "Property \"%s\" removed from %d entries" property cnt)))))
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let ((count 0)
+        (re (org-re-property (concat (regexp-quote property) "\\+?") t t)))
+     (while (re-search-forward re nil t)
+       (when (org-entry-delete (point) property) (cl-incf count)))
+     (message "Property \"%s\" removed from %d entries" property count))))
 
 (defvar org-columns-current-fmt-compiled) ; defined in org-colview.el
 
@@ -15929,9 +16528,9 @@ then applies it to the property in the column format's 
scope."
   (interactive)
   (unless (org-at-property-p)
     (user-error "Not at a property"))
-  (let ((prop (org-match-string-no-properties 2)))
+  (let ((prop (match-string-no-properties 2)))
     (org-columns-get-format-and-top-level)
-    (unless (nth 3 (assoc prop org-columns-current-fmt-compiled))
+    (unless (nth 3 (assoc-string prop org-columns-current-fmt-compiled t))
       (user-error "No operator defined for property %s" prop))
     (org-columns-compute prop)))
 
@@ -15958,6 +16557,7 @@ completion."
        (while (>= n org-highest-priority)
          (push (char-to-string n) vals)
          (setq n (1- n)))))
+     ((equal property "CATEGORY"))
      ((member property org-special-properties))
      ((setq vals (run-hook-with-args-until-success
                  'org-property-allowed-value-functions property)))
@@ -15976,7 +16576,7 @@ completion."
       (org-add-props (car vals) '(org-unrestricted t)))
     (if table (mapcar 'list vals) vals)))
 
-(defun org-property-previous-allowed-value (&optional previous)
+(defun org-property-previous-allowed-value (&optional _previous)
   "Switch to the next allowed value for this property."
   (interactive)
   (org-property-next-allowed-value t))
@@ -15996,21 +16596,22 @@ completion."
         nval)
     (unless allowed
       (user-error "Allowed values for this property have not been defined"))
-    (if previous (setq allowed (reverse allowed)))
-    (if (member value allowed)
-       (setq nval (car (cdr (member value allowed)))))
+    (when previous (setq allowed (reverse allowed)))
+    (when (member value allowed)
+      (setq nval (car (cdr (member value allowed)))))
     (setq nval (or nval (car allowed)))
-    (if (equal nval value)
-       (user-error "Only one allowed value for this property"))
+    (when (equal nval value)
+      (user-error "Only one allowed value for this property"))
     (org-at-property-p)
     (replace-match (concat " :" key ": " nval) t t)
     (org-indent-line)
     (beginning-of-line 1)
     (skip-chars-forward " \t")
     (when (equal prop org-effort-property)
-      (save-excursion
-       (org-back-to-heading t)
-       (put-text-property (point-at-bol) (point-at-eol) 'org-effort nval))
+      (org-refresh-property
+       '((effort . identity)
+        (effort-minutes . org-duration-string-to-minutes))
+       nval)
       (when (string= org-clock-current-task heading)
        (setq org-clock-effort nval)
        (org-clock-update-mode-line)))
@@ -16035,31 +16636,28 @@ only headings."
         (level 1)
         (lmin 1)
         (lmax 1)
-        limit re end found pos heading cnt flevel)
+        end found flevel)
     (unless buffer (error "File not found :%s" file))
     (with-current-buffer buffer
-      (save-excursion
-       (save-restriction
-         (widen)
-         (setq limit (point-max))
-         (goto-char (point-min))
-         (dolist (heading path)
-           (setq re (format org-complex-heading-regexp-format
-                            (regexp-quote heading)))
-           (setq cnt 0 pos (point))
-           (while (re-search-forward re end t)
-             (setq level (- (match-end 1) (match-beginning 1)))
-             (if (and (>= level lmin) (<= level lmax))
-                 (setq found (match-beginning 0) flevel level cnt (1+ cnt))))
-           (when (= cnt 0) (error "Heading not found on level %d: %s"
-                                  lmax heading))
-           (when (> cnt 1) (error "Heading not unique on level %d: %s"
-                                  lmax heading))
-           (goto-char found)
-           (setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0)))
-           (setq end (save-excursion (org-end-of-subtree t t))))
-         (when (org-at-heading-p)
-           (point-marker)))))))
+      (org-with-wide-buffer
+       (goto-char (point-min))
+       (dolist (heading path)
+        (let ((re (format org-complex-heading-regexp-format
+                          (regexp-quote heading)))
+              (cnt 0))
+          (while (re-search-forward re end t)
+            (setq level (- (match-end 1) (match-beginning 1)))
+            (when (and (>= level lmin) (<= level lmax))
+              (setq found (match-beginning 0) flevel level cnt (1+ cnt))))
+          (when (= cnt 0)
+            (error "Heading not found on level %d: %s" lmax heading))
+          (when (> cnt 1)
+            (error "Heading not unique on level %d: %s" lmax heading))
+          (goto-char found)
+          (setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0)))
+          (setq end (save-excursion (org-end-of-subtree t t)))))
+       (when (org-at-heading-p)
+        (point-marker))))))
 
 (defun org-find-exact-headline-in-buffer (heading &optional buffer pos-only)
   "Find node HEADING in BUFFER.
@@ -16069,24 +16667,22 @@ If POS-ONLY is set, return just the position instead 
of a marker.
 The heading text must match exact, but it may have a TODO keyword,
 a priority cookie and tags in the standard locations."
   (with-current-buffer (or buffer (current-buffer))
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (let (case-fold-search)
-         (if (re-search-forward
-              (format org-complex-heading-regexp-format
-                      (regexp-quote heading)) nil t)
-             (if pos-only
-                 (match-beginning 0)
-               (move-marker (make-marker) (match-beginning 0)))))))))
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (let (case-fold-search)
+       (when (re-search-forward
+             (format org-complex-heading-regexp-format
+                     (regexp-quote heading)) nil t)
+        (if pos-only
+            (match-beginning 0)
+          (move-marker (make-marker) (match-beginning 0))))))))
 
 (defun org-find-exact-heading-in-directory (heading &optional dir)
   "Find Org node headline HEADING in all .org files in directory DIR.
 When the target headline is found, return a marker to this location."
   (let ((files (directory-files (or dir default-directory)
-                               nil "\\`[^.#].*\\.org\\'"))
-        file visiting m buffer)
+                               t "\\`[^.#].*\\.org\\'"))
+       visiting m buffer)
     (catch 'found
       (dolist (file files)
         (message "trying %s" file)
@@ -16105,19 +16701,10 @@ Return the position where this entry starts, or nil 
if there is no such entry."
   (interactive "sID: ")
   (let ((id (cond
             ((stringp ident) ident)
-            ((symbol-name ident) (symbol-name ident))
+            ((symbolp ident) (symbol-name ident))
             ((numberp ident) (number-to-string ident))
-            (t (error "IDENT %s must be a string, symbol or number" ident))))
-       (case-fold-search nil))
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (when (re-search-forward
-              (concat "^[ \t]*:ID:[ \t]+" (regexp-quote id) "[ \t]*$")
-              nil t)
-         (org-back-to-heading t)
-         (point))))))
+            (t (error "IDENT %s must be a string, symbol or number" ident)))))
+    (org-with-wide-buffer (org-find-property "ID" id))))
 
 ;;;; Timestamps
 
@@ -16128,17 +16715,16 @@ Return the position where this entry starts, or nil 
if there is no such entry."
 
 (defun org-time-stamp (arg &optional inactive)
   "Prompt for a date/time and insert a time stamp.
+
 If the user specifies a time like HH:MM or if this command is
 called with at least one prefix argument, the time stamp contains
-the date and the time.  Otherwise, only the date is be included.
+the date and the time.  Otherwise, only the date is included.
 
-All parts of a date not specified by the user is filled in from
-the current date/time.  So if you just press return without
-typing anything, the time stamp will represent the current
-date/time.
+All parts of a date not specified by the user are filled in from
+the timestamp at point, if any, or the current date/time
+otherwise.
 
-If there is already a timestamp at the cursor, it will be
-modified.
+If there is already a timestamp at the cursor, it is replaced.
 
 With two universal prefix arguments, insert an active timestamp
 with the current time without prompting the user.
@@ -16146,57 +16732,56 @@ with the current time without prompting the user.
 When called from lisp, the timestamp is inactive if INACTIVE is
 non-nil."
   (interactive "P")
-  (let* ((ts nil)
-        (default-time
-          ;; Default time is either today, or, when entering a range,
-          ;; the range start.
-          (if (or (and (org-at-timestamp-p t) (setq ts (match-string 0)))
-                  (save-excursion
-                    (re-search-backward
-                     (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
-                     (- (point) 20) t)))
-              (apply 'encode-time (org-parse-time-string (match-string 1)))
-            (current-time)))
-        (default-input (and ts (org-get-compact-tod ts)))
-        (repeater (save-excursion
-                    (save-match-data
-                      (beginning-of-line)
-                      (when (re-search-forward
-                             "\\([.+-]+[0-9]+[hdwmy] ?\\)+" ;;\\(?:[/ 
][-+]?[0-9]+[hdwmy]\\)?\\) ?"
-                             (save-excursion (progn (end-of-line) (point))) t)
-                        (match-string 0)))))
-        org-time-was-given org-end-time-was-given time)
+  (let* ((ts (cond
+             ((org-at-date-range-p t)
+              (match-string (if (< (point) (- (match-beginning 2) 2)) 1 2)))
+             ((org-at-timestamp-p t) (match-string 0))))
+        ;; Default time is either the timestamp at point or today.
+        ;; When entering a range, only the range start is considered.
+         (default-time (if (not ts) (current-time)
+                        (apply #'encode-time (org-parse-time-string ts))))
+         (default-input (and ts (org-get-compact-tod ts)))
+         (repeater (and ts
+                       (string-match "\\([.+-]+[0-9]+[hdwmy] ?\\)+" ts)
+                       (match-string 0 ts)))
+        org-time-was-given
+        org-end-time-was-given
+        (time
+         (and (if (equal arg '(16)) (current-time)
+                ;; Preserve `this-command' and `last-command'.
+                (let ((this-command this-command)
+                      (last-command last-command))
+                  (org-read-date
+                   arg 'totime nil nil default-time default-input
+                   inactive))))))
     (cond
-     ((and (org-at-timestamp-p t)
-          (memq last-command '(org-time-stamp org-time-stamp-inactive))
-          (memq this-command '(org-time-stamp org-time-stamp-inactive)))
+     ((and ts
+           (memq last-command '(org-time-stamp org-time-stamp-inactive))
+           (memq this-command '(org-time-stamp org-time-stamp-inactive)))
       (insert "--")
-      (setq time (let ((this-command this-command))
-                  (org-read-date arg 'totime nil nil
-                                 default-time default-input inactive)))
       (org-insert-time-stamp time (or org-time-was-given arg) inactive))
-     ((org-at-timestamp-p t)
-      (setq time (let ((this-command this-command))
-                  (org-read-date arg 'totime nil nil default-time 
default-input inactive)))
-      (when (org-at-timestamp-p t) ; just to get the match data
-                                       ;       (setq inactive (eq (char-after 
(match-beginning 0)) ?\[))
-       (replace-match "")
+     (ts
+      ;; Make sure we're on a timestamp.  When in the middle of a date
+      ;; range, move arbitrarily to range end.
+      (unless (org-at-timestamp-p t)
+       (skip-chars-forward "-")
+       (org-at-timestamp-p t))
+      (replace-match "")
+      (setq org-last-changed-timestamp
+           (org-insert-time-stamp
+            time (or org-time-was-given arg)
+            inactive nil nil (list org-end-time-was-given)))
+      (when repeater
+       (backward-char)
+       (insert " " repeater)
        (setq org-last-changed-timestamp
-             (org-insert-time-stamp
-              time (or org-time-was-given arg)
-              inactive nil nil (list org-end-time-was-given)))
-       (when repeater (goto-char (1- (point))) (insert " " repeater)
-             (setq org-last-changed-timestamp
-                   (concat (substring org-last-inserted-timestamp 0 -1)
-                           " " repeater ">"))))
+             (concat (substring org-last-inserted-timestamp 0 -1)
+                     " " repeater ">")))
       (message "Timestamp updated"))
-     ((equal arg '(16))
-      (org-insert-time-stamp (current-time) t inactive))
-     (t
-      (setq time (let ((this-command this-command))
-                  (org-read-date arg 'totime nil nil default-time 
default-input inactive)))
-      (org-insert-time-stamp time (or org-time-was-given arg) inactive
-                            nil nil (list org-end-time-was-given))))))
+     ((equal arg '(16)) (org-insert-time-stamp time t inactive))
+     (t (org-insert-time-stamp
+        time (or org-time-was-given arg) inactive nil nil
+        (list org-end-time-was-given))))))
 
 ;; FIXME: can we use this for something else, like computing time differences?
 (defun org-get-compact-tod (s)
@@ -16211,7 +16796,7 @@ non-nil."
       (if (not t2)
          t1
        (setq dh (- h2 h1) dm (- m2 m1))
-       (if (< dm 0) (setq dm (+ dm 60) dh (1- dh)))
+       (when (< dm 0) (setq dm (+ dm 60) dh (1- dh)))
        (concat t1 "+" (number-to-string dh)
                (and (/= 0 dm) (format ":%02d" dm)))))))
 
@@ -16226,7 +16811,7 @@ So these are more for recording a certain time/date."
 
 (defvar org-date-ovl (make-overlay 1 1))
 (overlay-put org-date-ovl 'face 'org-date-selected)
-(org-detach-overlay org-date-ovl)
+(delete-overlay org-date-ovl)
 
 (defvar org-ans1) ; dynamically scoped parameter
 (defvar org-ans2) ; dynamically scoped parameter
@@ -16243,13 +16828,14 @@ So these are more for recording a certain time/date."
 (defvar org-read-date-inactive)
 
 (defvar org-read-date-minibuffer-local-map
-  (let* ((org-replace-disputed-keys nil)
-        (map (make-sparse-keymap)))
+  (let* ((map (make-sparse-keymap)))
     (set-keymap-parent map minibuffer-local-map)
     (org-defkey map (kbd ".")
                 (lambda () (interactive)
                  ;; Are we at the beginning of the prompt?
-                 (if (looking-back "^[^:]+: ")
+                 (if (looking-back "^[^:]+: "
+                                   (let ((inhibit-field-text-motion t))
+                                     (line-beginning-position)))
                      (org-eval-in-calendar '(calendar-goto-today))
                    (insert "."))))
     (org-defkey map (kbd "C-.")
@@ -16316,7 +16902,8 @@ So these are more for recording a certain time/date."
 (defvar org-defdecode)
 (defvar org-with-time)
 
-(defun org-read-date (&optional org-with-time to-time from-string prompt
+(defvar calendar-setup)                        ; Dynamically scoped.
+(defun org-read-date (&optional with-time to-time from-string prompt
                                default-time default-input inactive)
   "Read a date, possibly a time, and make things smooth for the user.
 The prompt will suggest to enter an ISO date, but you can also enter anything
@@ -16360,8 +16947,8 @@ If you don't like the calendar, turn it off with
 
 With optional argument TO-TIME, the date will immediately be converted
 to an internal time.
-With an optional argument ORG-WITH-TIME, the prompt will suggest to
-also insert a time.  Note that when ORG-WITH-TIME is not set, you can
+With an optional argument WITH-TIME, the prompt will suggest to
+also insert a time.  Note that when WITH-TIME is not set, you can
 still enter a time, and this function will inform the calling routine
 about this change.  The calling routine may then choose to change the
 format used to insert the time stamp into the buffer to include the time.
@@ -16370,75 +16957,90 @@ the user.  PROMPT can overwrite the default prompt.  
DEFAULT-TIME is
 the time/date that is used for everything that is not specified by the
 user."
   (require 'parse-time)
-  (let* ((org-time-stamp-rounding-minutes
-         (if (equal org-with-time '(16)) '(0 0) 
org-time-stamp-rounding-minutes))
+  (let* ((org-with-time with-time)
+        (org-time-stamp-rounding-minutes
+         (if (equal org-with-time '(16))
+             '(0 0)
+           org-time-stamp-rounding-minutes))
         (org-dcst org-display-custom-times)
         (ct (org-current-time))
         (org-def (or org-overriding-default-time default-time ct))
         (org-defdecode (decode-time org-def))
-        (dummy (progn
-                 (when (< (nth 2 org-defdecode) org-extend-today-until)
-                   (setcar (nthcdr 2 org-defdecode) -1)
-                   (setcar (nthcdr 1 org-defdecode) 59)
-                   (setq org-def (apply 'encode-time org-defdecode)
-                         org-defdecode (decode-time org-def)))))
-        (mouse-autoselect-window nil) ; Don't let the mouse jump
-        (calendar-frame-setup nil)
-        (calendar-setup nil)
+         (cur-frame (selected-frame))
+        (mouse-autoselect-window nil)  ; Don't let the mouse jump
+        (calendar-setup
+         (and (eq calendar-setup 'calendar-only) 'calendar-only))
         (calendar-move-hook nil)
         (calendar-view-diary-initially-flag nil)
         (calendar-view-holidays-initially-flag nil)
-        (timestr (format-time-string
-                  (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") org-def))
-        (prompt (concat (if prompt (concat prompt " ") "")
-                        (format "Date+time [%s]: " timestr)))
-        ans (org-ans0 "") org-ans1 org-ans2 final)
-
-    (cond
-     (from-string (setq ans from-string))
-     (org-read-date-popup-calendar
-      (save-excursion
-       (save-window-excursion
-         (calendar)
-         (org-eval-in-calendar '(setq cursor-type nil) t)
-          (unwind-protect
-              (progn
-               (calendar-forward-day (- (time-to-days org-def)
-                                        (calendar-absolute-from-gregorian
-                                         (calendar-current-date))))
-               (org-eval-in-calendar nil t)
-               (let* ((old-map (current-local-map))
-                      (map (copy-keymap calendar-mode-map))
-                      (minibuffer-local-map
-                       (copy-keymap org-read-date-minibuffer-local-map)))
-                 (org-defkey map (kbd "RET") 'org-calendar-select)
-                 (org-defkey map [mouse-1] 'org-calendar-select-mouse)
-                 (org-defkey map [mouse-2] 'org-calendar-select-mouse)
-                 (unwind-protect
-                     (progn
-                       (use-local-map map)
-                       (setq org-read-date-inactive inactive)
-                       (add-hook 'post-command-hook 'org-read-date-display)
-                       (setq org-ans0 (read-string prompt default-input
-                                                   'org-read-date-history nil))
-                       ;; org-ans0: from prompt
-                       ;; org-ans1: from mouse click
-                       ;; org-ans2: from calendar motion
-                       (setq ans (concat org-ans0 " " (or org-ans1 org-ans2))))
-                   (remove-hook 'post-command-hook 'org-read-date-display)
-                   (use-local-map old-map)
-                   (when org-read-date-overlay
-                     (delete-overlay org-read-date-overlay)
-                      (setq org-read-date-overlay nil)))))
-           (bury-buffer "*Calendar*")))))
-
-     (t ; Naked prompt only
-      (unwind-protect
-         (setq ans (read-string prompt default-input
-                                'org-read-date-history timestr))
-       (when org-read-date-overlay
-         (delete-overlay org-read-date-overlay)
-         (setq org-read-date-overlay nil)))))
+        ans (org-ans0 "") org-ans1 org-ans2 final cal-frame)
+    ;; Rationalize `org-def' and `org-defdecode', if required.
+    (when (< (nth 2 org-defdecode) org-extend-today-until)
+      (setf (nth 2 org-defdecode) -1)
+      (setf (nth 1 org-defdecode) 59)
+      (setq org-def (apply #'encode-time org-defdecode))
+      (setq org-defdecode (decode-time org-def)))
+    (let* ((timestr (format-time-string
+                    (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
+                    org-def))
+          (prompt (concat (if prompt (concat prompt " ") "")
+                          (format "Date+time [%s]: " timestr))))
+      (cond
+       (from-string (setq ans from-string))
+       (org-read-date-popup-calendar
+       (save-excursion
+         (save-window-excursion
+           (calendar)
+           (when (eq calendar-setup 'calendar-only)
+             (setq cal-frame
+                   (window-frame (get-buffer-window "*Calendar*" 'visible)))
+             (select-frame cal-frame))
+           (org-eval-in-calendar '(setq cursor-type nil) t)
+           (unwind-protect
+               (progn
+                 (calendar-forward-day (- (time-to-days org-def)
+                                          (calendar-absolute-from-gregorian
+                                           (calendar-current-date))))
+                 (org-eval-in-calendar nil t)
+                 (let* ((old-map (current-local-map))
+                        (map (copy-keymap calendar-mode-map))
+                        (minibuffer-local-map
+                         (copy-keymap org-read-date-minibuffer-local-map)))
+                   (org-defkey map (kbd "RET") 'org-calendar-select)
+                   (org-defkey map [mouse-1] 'org-calendar-select-mouse)
+                   (org-defkey map [mouse-2] 'org-calendar-select-mouse)
+                   (unwind-protect
+                       (progn
+                         (use-local-map map)
+                         (setq org-read-date-inactive inactive)
+                         (add-hook 'post-command-hook 'org-read-date-display)
+                         (setq org-ans0
+                               (read-string prompt
+                                            default-input
+                                            'org-read-date-history
+                                            nil))
+                         ;; org-ans0: from prompt
+                         ;; org-ans1: from mouse click
+                         ;; org-ans2: from calendar motion
+                         (setq ans
+                               (concat org-ans0 " " (or org-ans1 org-ans2))))
+                     (remove-hook 'post-command-hook 'org-read-date-display)
+                     (use-local-map old-map)
+                     (when org-read-date-overlay
+                       (delete-overlay org-read-date-overlay)
+                       (setq org-read-date-overlay nil)))))
+             (bury-buffer "*Calendar*")
+             (when cal-frame
+               (delete-frame cal-frame)
+               (select-frame-set-input-focus cur-frame))))))
+
+       (t                              ; Naked prompt only
+       (unwind-protect
+           (setq ans (read-string prompt default-input
+                                  'org-read-date-history timestr))
+         (when org-read-date-overlay
+           (delete-overlay org-read-date-overlay)
+           (setq org-read-date-overlay nil))))))
 
     (setq final (org-read-date-analyze ans org-def org-defdecode))
 
@@ -16499,13 +17101,18 @@ user."
              (make-overlay (1- (point-at-eol)) (point-at-eol)))
        (org-overlay-display org-read-date-overlay txt 'secondary-selection)))))
 
-(defun org-read-date-analyze (ans org-def org-defdecode)
+(defun org-read-date-analyze (ans def defdecode)
   "Analyze the combined answer of the date prompt."
   ;; FIXME: cleanup and comment
-  (let ((nowdecode (decode-time))
+  ;; Pass `current-time' result to `decode-time' (instead of calling
+  ;; without arguments) so that only `current-time' has to be
+  ;; overriden in tests.
+  (let ((org-def def)
+       (org-defdecode defdecode)
+       (nowdecode (decode-time (current-time)))
        delta deltan deltaw deltadef year month day
        hour minute second wday pm h2 m2 tl wday1
-       iso-year iso-weekday iso-week iso-year iso-date futurep kill-year)
+       iso-year iso-weekday iso-week iso-date futurep kill-year)
     (setq org-read-date-analyze-futurep nil
          org-read-date-analyze-forced-year nil)
     (when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans)
@@ -16521,11 +17128,11 @@ user."
     ;; info and postpone interpreting it until the rest of the parsing
     ;; is done.
     (when (string-match 
"\\<\\(?:\\([0-9]+\\)-\\)?[wW]\\([0-9]\\{1,2\\}\\)\\(?:-\\([0-6]\\)\\)?\\([ 
\t]\\|$\\)" ans)
-      (setq iso-year (if (match-end 1)
-                        (org-small-year-to-year
-                         (string-to-number (match-string 1 ans))))
-           iso-weekday (if (match-end 3)
-                           (string-to-number (match-string 3 ans)))
+      (setq iso-year (when (match-end 1)
+                      (org-small-year-to-year
+                       (string-to-number (match-string 1 ans))))
+           iso-weekday (when (match-end 3)
+                         (string-to-number (match-string 3 ans)))
            iso-week (string-to-number (match-string 2 ans)))
       (setq ans (replace-match "" t t ans)))
 
@@ -16538,7 +17145,7 @@ user."
                          (string-to-number (format-time-string "%Y"))))
            month (string-to-number (match-string 3 ans))
            day (string-to-number (match-string 4 ans)))
-      (if (< year 100) (setq year (+ 2000 year)))
+      (setq year (org-small-year-to-year year))
       (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
                               t nil ans)))
 
@@ -16562,26 +17169,26 @@ user."
                          (string-to-number (format-time-string "%Y"))))
            month (string-to-number (match-string 1 ans))
            day (string-to-number (match-string 2 ans)))
-      (if (< year 100) (setq year (+ 2000 year)))
+      (setq year (org-small-year-to-year year))
       (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
                               t nil ans)))
     ;; Help matching am/pm times, because `parse-time-string' does not do that.
     ;; If there is a time with am/pm, and *no* time without it, we convert
     ;; so that matching will be successful.
-    (loop for i from 1 to 2 do ; twice, for end time as well
-         (when (and (not (string-match 
"\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
-                    (string-match 
"\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
-           (setq hour (string-to-number (match-string 1 ans))
-                 minute (if (match-end 3)
-                            (string-to-number (match-string 3 ans))
-                          0)
-                 pm (equal ?p
-                           (string-to-char (downcase (match-string 4 ans)))))
-           (if (and (= hour 12) (not pm))
-               (setq hour 0)
-             (if (and pm (< hour 12)) (setq hour (+ 12 hour))))
-           (setq ans (replace-match (format "%02d:%02d" hour minute)
-                                    t t ans))))
+    (cl-loop for i from 1 to 2 do      ; twice, for end time as well
+            (when (and (not (string-match 
"\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
+                       (string-match 
"\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
+              (setq hour (string-to-number (match-string 1 ans))
+                    minute (if (match-end 3)
+                               (string-to-number (match-string 3 ans))
+                             0)
+                    pm (equal ?p
+                              (string-to-char (downcase (match-string 4 
ans)))))
+              (if (and (= hour 12) (not pm))
+                  (setq hour 0)
+                (when (and pm (< hour 12)) (setq hour (+ 12 hour))))
+              (setq ans (replace-match (format "%02d:%02d" hour minute)
+                                       t t ans))))
 
     ;; Check if a time range is given as a duration
     (when (string-match 
"\\([012]?[0-9]\\):\\([0-6][0-9]\\)\\+\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?"
 ans)
@@ -16590,7 +17197,7 @@ user."
            minute (string-to-number (match-string 2 ans))
            m2 (+ minute (if (match-end 5) (string-to-number
                                            (match-string 5 ans))0)))
-      (if (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60)))
+      (when (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60)))
       (setq ans (replace-match (format "%02d:%02d-%02d:%02d" hour minute h2 m2)
                               t t ans)))
 
@@ -16605,16 +17212,35 @@ user."
 
     (setq tl (parse-time-string ans)
          day (or (nth 3 tl) (nth 3 org-defdecode))
-         month (or (nth 4 tl)
-                   (if (and org-read-date-prefer-future
-                            (nth 3 tl) (< (nth 3 tl) (nth 3 nowdecode)))
-                       (prog1 (1+ (nth 4 nowdecode)) (setq futurep t))
-                     (nth 4 org-defdecode)))
-         year (or (and (not kill-year) (nth 5 tl))
-                  (if (and org-read-date-prefer-future
-                           (nth 4 tl) (< (nth 4 tl) (nth 4 nowdecode)))
-                      (prog1 (1+ (nth 5 nowdecode)) (setq futurep t))
-                    (nth 5 org-defdecode)))
+         month
+         (cond ((nth 4 tl))
+               ((not org-read-date-prefer-future) (nth 4 org-defdecode))
+               ;; Day was specified.  Make sure DAY+MONTH
+               ;; combination happens in the future.
+               ((nth 3 tl)
+                (setq futurep t)
+                (if (< day (nth 3 nowdecode)) (1+ (nth 4 nowdecode))
+                  (nth 4 nowdecode)))
+               (t (nth 4 org-defdecode)))
+         year
+         (cond ((and (not kill-year) (nth 5 tl)))
+               ((not org-read-date-prefer-future) (nth 5 org-defdecode))
+               ;; Month was guessed in the future and is at least
+               ;; equal to NOWDECODE's.  Fix year accordingly.
+               (futurep
+                (if (or (> month (nth 4 nowdecode))
+                        (>= day (nth 3 nowdecode)))
+                    (nth 5 nowdecode)
+                  (1+ (nth 5 nowdecode))))
+               ;; Month was specified.  Make sure MONTH+YEAR
+               ;; combination happens in the future.
+               ((nth 4 tl)
+                (setq futurep t)
+                (cond ((> month (nth 4 nowdecode)) (nth 5 nowdecode))
+                      ((< month (nth 4 nowdecode)) (1+ (nth 5 nowdecode)))
+                      ((< day (nth 3 nowdecode)) (1+ (nth 5 nowdecode)))
+                      (t (nth 5 nowdecode))))
+               (t (nth 5 org-defdecode)))
          hour (or (nth 2 tl) (nth 2 org-defdecode))
          minute (or (nth 1 tl) (nth 1 org-defdecode))
          second (or (nth 0 tl) 0)
@@ -16643,7 +17269,7 @@ user."
            day (or iso-weekday wday 1)
            wday nil ; to make sure that the trigger below does not match
            iso-date (calendar-gregorian-from-absolute
-                     (calendar-absolute-from-iso
+                     (calendar-iso-to-absolute
                       (list iso-week day year))))
                                        ; FIXME:  Should we also push ISO weeks 
into the future?
                                        ;      (when (and 
org-read-date-prefer-future
@@ -16652,7 +17278,7 @@ user."
                                        ;                   (time-to-days 
(current-time))))
                                        ;       (setq year (1+ year)
                                        ;             iso-date 
(calendar-gregorian-from-absolute
-                                       ;                       
(calendar-absolute-from-iso
+                                       ;                       
(calendar-iso-to-absolute
                                        ;                        (list iso-week 
day year)))))
       (setq month (car iso-date)
            year (nth 2 iso-date)
@@ -16660,7 +17286,10 @@ user."
      (deltan
       (setq futurep nil)
       (unless deltadef
-       (let ((now (decode-time)))
+       ;; Pass `current-time' result to `decode-time' (instead of
+       ;; calling without arguments) so that only `current-time' has
+       ;; to be overriden in tests.
+       (let ((now (decode-time (current-time))))
          (setq day (nth 3 now) month (nth 4 now) year (nth 5 now))))
       (cond ((member deltaw '("d" "")) (setq day (+ day deltan)))
            ((equal deltaw "w") (setq day (+ day (* 7 deltan))))
@@ -16672,17 +17301,17 @@ user."
       (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
       (unless (equal wday wday1)
        (setq day (+ day (% (- wday wday1 -7) 7))))))
-    (if (and (boundp 'org-time-was-given)
-            (nth 2 tl))
-       (setq org-time-was-given t))
-    (if (< year 100) (setq year (+ 2000 year)))
+    (when (and (boundp 'org-time-was-given)
+              (nth 2 tl))
+      (setq org-time-was-given t))
+    (when (< year 100) (setq year (+ 2000 year)))
     ;; Check of the date is representable
     (if org-read-date-force-compatible-dates
        (progn
-         (if (< year 1970)
-             (setq year 1970 org-read-date-analyze-forced-year t))
-         (if (> year 2037)
-             (setq year 2037  org-read-date-analyze-forced-year t)))
+         (when (< year 1970)
+           (setq year 1970 org-read-date-analyze-forced-year t))
+         (when (> year 2037)
+           (setq year 2037 org-read-date-analyze-forced-year t)))
       (condition-case nil
          (ignore (encode-time second minute hour day month year))
        (error
@@ -16722,12 +17351,11 @@ DEF-FLAG   is t when a double ++ or -- indicates 
shift relative to
       (if wday1
          (progn
            (setq delta (mod (+ 7 (- wday1 wday)) 7))
-           (if (= delta 0) (setq delta 7))
-           (if (= dir ?-)
-               (progn
-                 (setq delta (- delta 7))
-                 (if (= delta 0) (setq delta -7))))
-           (if (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 7)))))
+           (when (= delta 0) (setq delta 7))
+           (when (= dir ?-)
+             (setq delta (- delta 7))
+             (when (= delta 0) (setq delta -7)))
+           (when (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 
7)))))
            (list delta "d" rel))
        (list (* n (if (= dir ?-) -1 1)) what rel)))))
 
@@ -16736,23 +17364,14 @@ DEF-FLAG   is t when a double ++ or -- indicates 
shift relative to
 The internal representation needed by the calendar is (month day year).
 This is a wrapper to handle the brain-dead convention in calendar that
 user function argument order change dependent on argument order."
-  (if (boundp 'calendar-date-style)
-      (cond
-       ((eq calendar-date-style 'american)
-       (list arg1 arg2 arg3))
-       ((eq calendar-date-style 'european)
-       (list arg2 arg1 arg3))
-       ((eq calendar-date-style 'iso)
-       (list arg2 arg3 arg1)))
-    (org-no-warnings ;; european-calendar-style is obsolete as of version 23.1
-     (if (org-bound-and-true-p european-calendar-style)
-        (list arg2 arg1 arg3)
-       (list arg1 arg2 arg3)))))
+  (pcase calendar-date-style
+    (`american (list arg1 arg2 arg3))
+    (`european (list arg2 arg1 arg3))
+    (`iso (list arg2 arg3 arg1))))
 
 (defun org-eval-in-calendar (form &optional keepdate)
   "Eval FORM in the calendar window and return to current window.
-When KEEPDATE is non-nil, update `org-ans2' from the cursor date,
-otherwise stick to the current value of `org-ans2'."
+Unless KEEPDATE is non-nil, update `org-ans2' to the cursor date."
   (let ((sf (selected-frame))
        (sw (selected-window)))
     (select-window (get-buffer-window "*Calendar*" t))
@@ -16763,7 +17382,7 @@ otherwise stick to the current value of `org-ans2'."
        (setq org-ans2 (format-time-string "%Y-%m-%d" time))))
     (move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
     (select-window sw)
-    (org-select-frame-set-input-focus sf)))
+    (select-frame-set-input-focus sf)))
 
 (defun org-calendar-select ()
   "Return to `org-read-date' with the date currently selected.
@@ -16773,10 +17392,11 @@ This is used by `org-read-date' in a temporary keymap 
for the calendar buffer."
     (let* ((date (calendar-cursor-to-date))
           (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
       (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
-    (if (active-minibuffer-window) (exit-minibuffer))))
+    (when (active-minibuffer-window) (exit-minibuffer))))
 
 (defun org-insert-time-stamp (time &optional with-hm inactive pre post extra)
   "Insert a date stamp for the date given by the internal TIME.
+See `format-time-string' for the format of TIME.
 WITH-HM means use the stamp format that includes the time of the day.
 INACTIVE means use square brackets instead of angular ones, so that the
 stamp will not contribute to the agenda.
@@ -16785,7 +17405,7 @@ stamp.
 The command returns the inserted time stamp."
   (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
        stamp)
-    (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
+    (when inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
     (insert-before-markers (or pre ""))
     (when (listp extra)
       (setq extra (car extra))
@@ -16808,14 +17428,12 @@ The command returns the inserted time stamp."
   (unless org-display-custom-times
     (let ((p (point-min)) (bmp (buffer-modified-p)))
       (while (setq p (next-single-property-change p 'display))
-       (if (and (get-text-property p 'display)
-                (eq (get-text-property p 'face) 'org-date))
-           (remove-text-properties
-            p (setq p (next-single-property-change p 'display))
-            '(display t))))
+       (when (and (get-text-property p 'display)
+                  (eq (get-text-property p 'face) 'org-date))
+         (remove-text-properties
+          p (setq p (next-single-property-change p 'display))
+          '(display t))))
       (set-buffer-modified-p bmp)))
-  (if (featurep 'xemacs)
-      (remove-text-properties (point-min) (point-max) '(end-glyph t)))
   (org-restart-font-lock)
   (setq org-table-may-need-update t)
   (if org-display-custom-times
@@ -16828,8 +17446,8 @@ The command returns the inserted time stamp."
         t1 w1 with-hm tf time str w2 (off 0))
     (save-match-data
       (setq t1 (org-parse-time-string ts t))
-      (if (string-match "\\(-[0-9]+:[0-9]+\\)?\\( 
[.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)?\\'" ts)
-         (setq off (- (match-end 0) (match-beginning 0)))))
+      (when (string-match "\\(-[0-9]+:[0-9]+\\)?\\( 
[.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)?\\'" ts)
+       (setq off (- (match-end 0) (match-beginning 0)))))
     (setq end (- end off))
     (setq w1 (- end beg)
          with-hm (and (nth 1 t1) (nth 2 t1))
@@ -16840,41 +17458,10 @@ The command returns the inserted time stamp."
                   (substring tf 1 -1) (apply 'encode-time time))
                  nil 'mouse-face 'highlight)
          w2 (length str))
-    (if (not (= w2 w1))
-       (add-text-properties (1+ beg) (+ 2 beg)
-                            (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
-    (if (featurep 'xemacs)
-       (progn
-         (put-text-property beg end 'invisible t)
-         (put-text-property beg end 'end-glyph (make-glyph str)))
-      (put-text-property beg end 'display str))))
-
-(defun org-translate-time (string)
-  "Translate all timestamps in STRING to custom format.
-But do this only if the variable `org-display-custom-times' is set."
-  (when org-display-custom-times
-    (save-match-data
-      (let* ((start 0)
-            (re org-ts-regexp-both)
-            t1 with-hm inactive tf time str beg end)
-       (while (setq start (string-match re string start))
-         (setq beg (match-beginning 0)
-               end (match-end 0)
-               t1 (save-match-data
-                    (org-parse-time-string (substring string beg end) t))
-               with-hm (and (nth 1 t1) (nth 2 t1))
-               inactive (equal (substring string beg (1+ beg)) "[")
-               tf (funcall (if with-hm 'cdr 'car)
-                           org-time-stamp-custom-formats)
-               time (org-fix-decoded-time t1)
-               str (format-time-string
-                    (concat
-                     (if inactive "[" "<") (substring tf 1 -1)
-                     (if inactive "]" ">"))
-                    (apply 'encode-time time))
-               string (replace-match str t t string)
-               start (+ start (length str)))))))
-  string)
+    (unless (= w2 w1)
+      (add-text-properties (1+ beg) (+ 2 beg)
+                          (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
+    (put-text-property beg end 'display str)))
 
 (defun org-fix-decoded-time (time)
   "Set 0 instead of nil for the first 6 elements of time.
@@ -16882,19 +17469,17 @@ Don't touch the rest."
   (let ((n 0))
     (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time)))
 
-(define-obsolete-function-alias 'org-days-to-time 'org-time-stamp-to-now 
"24.4")
-
 (defun org-time-stamp-to-now (timestamp-string &optional seconds)
   "Difference between TIMESTAMP-STRING and now in days.
 If SECONDS is non-nil, return the difference in seconds."
-  (let ((fdiff (if seconds 'float-time 'time-to-days)))
+  (let ((fdiff (if seconds #'float-time #'time-to-days)))
     (- (funcall fdiff (org-time-string-to-time timestamp-string))
        (funcall fdiff (current-time)))))
 
-(defun org-deadline-close (timestamp-string &optional ndays)
+(defun org-deadline-close-p (timestamp-string &optional ndays)
   "Is the time in TIMESTAMP-STRING close to the current date?"
   (setq ndays (or ndays (org-get-wdays timestamp-string)))
-  (and (< (org-time-stamp-to-now timestamp-string) ndays)
+  (and (<= (org-time-stamp-to-now timestamp-string) ndays)
        (not (org-entry-is-done-p))))
 
 (defun org-get-wdays (ts &optional delay zero-delay)
@@ -16930,14 +17515,15 @@ This is used by `org-read-date' in a temporary keymap 
for the calendar buffer."
     (let* ((date (calendar-cursor-to-date))
           (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
       (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
-    (if (active-minibuffer-window) (exit-minibuffer))))
+    (when (active-minibuffer-window) (exit-minibuffer))))
 
 (defun org-check-deadlines (ndays)
   "Check if there are any deadlines due or past due.
 A deadline is considered due if it happens within `org-deadline-warning-days'
 days from today's date.  If the deadline appears in an entry marked DONE,
-it is not shown.  The prefix arg NDAYS can be used to test that many
-days.  If the prefix is a raw \\[universal-argument] prefix, all deadlines are 
shown."
+it is not shown.  A numeric prefix argument NDAYS can be used to test that
+many days.  If the prefix is a raw `\\[universal-argument]', all deadlines \
+are shown."
   (interactive "P")
   (let* ((org-warn-days
          (cond
@@ -16947,8 +17533,7 @@ days.  If the prefix is a raw \\[universal-argument] 
prefix, all deadlines are s
         (case-fold-search nil)
         (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
         (callback
-         (lambda () (org-deadline-close (match-string 1) org-warn-days))))
-
+         (lambda () (org-deadline-close-p (match-string 1) org-warn-days))))
     (message "%d deadlines past-due or due within %d days"
             (org-occur regexp nil callback)
             org-warn-days)))
@@ -16966,39 +17551,61 @@ Allowed values for TYPE are:
 
 When TYPE is nil, fall back on returning a regexp that matches
 both scheduled and deadline timestamps."
-  (cond ((eq type 'all) "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\(?: 
+[^]+0-9>\r\n -]+\\)?\\(?: +[0-9]\\{1,2\\}:[0-9]\\{2\\}\\)?\\)")
-       ((eq type 'active) org-ts-regexp)
-       ((eq type 'inactive) "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} 
?[^\r\n>]*?\\)\\]")
-       ((eq type 'scheduled) (concat "\\<" org-scheduled-string " 
*<\\([^>]+\\)>"))
-       ((eq type 'deadline) (concat "\\<" org-deadline-string " 
*<\\([^>]+\\)>"))
-       ((eq type 'closed) (concat org-closed-string " 
\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]"))
-       ((eq type 'scheduled-or-deadline)
-        (concat "\\<\\(?:" org-deadline-string "\\|" org-scheduled-string "\\) 
*<\\([^>]+\\)>"))))
-
-(defun org-check-before-date (date)
-  "Check if there are deadlines or scheduled entries before DATE."
+  (cl-case type
+    (all org-ts-regexp-both)
+    (active org-ts-regexp)
+    (inactive org-ts-regexp-inactive)
+    (scheduled org-scheduled-time-regexp)
+    (deadline org-deadline-time-regexp)
+    (closed org-closed-time-regexp)
+    (otherwise
+     (concat "\\<"
+            (regexp-opt (list org-deadline-string org-scheduled-string))
+            " *<\\([^>]+\\)>"))))
+
+(defun org-check-before-date (d)
+  "Check if there are deadlines or scheduled entries before date D."
   (interactive (list (org-read-date)))
-  (let ((case-fold-search nil)
-       (regexp (org-re-timestamp org-ts-type))
-       (callback
-        (lambda () (time-less-p
-                    (org-time-string-to-time (match-string 1))
-                    (org-time-string-to-time date)))))
+  (let* ((case-fold-search nil)
+        (regexp (org-re-timestamp org-ts-type))
+        (ts-type org-ts-type)
+        (callback
+         (lambda ()
+           (let ((match (match-string 1)))
+             (and (if (memq ts-type '(active inactive all))
+                      (eq (org-element-type (save-excursion
+                                              (backward-char)
+                                              (org-element-context)))
+                          'timestamp)
+                    (org-at-planning-p))
+                  (time-less-p
+                   (org-time-string-to-time match)
+                   (org-time-string-to-time d)))))))
     (message "%d entries before %s"
-            (org-occur regexp nil callback) date)))
+            (org-occur regexp nil callback)
+            d)))
 
-(defun org-check-after-date (date)
-  "Check if there are deadlines or scheduled entries after DATE."
+(defun org-check-after-date (d)
+  "Check if there are deadlines or scheduled entries after date D."
   (interactive (list (org-read-date)))
-  (let ((case-fold-search nil)
-       (regexp (org-re-timestamp org-ts-type))
-       (callback
-        (lambda () (not
-                    (time-less-p
-                     (org-time-string-to-time (match-string 1))
-                     (org-time-string-to-time date))))))
+  (let* ((case-fold-search nil)
+        (regexp (org-re-timestamp org-ts-type))
+        (ts-type org-ts-type)
+        (callback
+         (lambda ()
+           (let ((match (match-string 1)))
+             (and (if (memq ts-type '(active inactive all))
+                      (eq (org-element-type (save-excursion
+                                              (backward-char)
+                                              (org-element-context)))
+                          'timestamp)
+                    (org-at-planning-p))
+                  (not (time-less-p
+                        (org-time-string-to-time match)
+                        (org-time-string-to-time d))))))))
     (message "%d entries after %s"
-            (org-occur regexp nil callback) date)))
+            (org-occur regexp nil callback)
+            d)))
 
 (defun org-check-dates-range (start-date end-date)
   "Check for deadlines/scheduled entries between START-DATE and END-DATE."
@@ -17007,15 +17614,22 @@ both scheduled and deadline timestamps."
   (let ((case-fold-search nil)
        (regexp (org-re-timestamp org-ts-type))
        (callback
-        (lambda ()
-          (let ((match (match-string 1)))
-            (and
-             (not (time-less-p
-                   (org-time-string-to-time match)
-                   (org-time-string-to-time start-date)))
-             (time-less-p
-              (org-time-string-to-time match)
-              (org-time-string-to-time end-date)))))))
+        (let ((type org-ts-type))
+          (lambda ()
+            (let ((match (match-string 1)))
+              (and
+               (if (memq type '(active inactive all))
+                   (eq (org-element-type (save-excursion
+                                           (backward-char)
+                                           (org-element-context)))
+                       'timestamp)
+                 (org-at-planning-p))
+               (not (time-less-p
+                     (org-time-string-to-time match)
+                     (org-time-string-to-time start-date)))
+               (time-less-p
+                (org-time-string-to-time match)
+                (org-time-string-to-time end-date))))))))
     (message "%d entries between %s and %s"
             (org-occur regexp nil callback) start-date end-date)))
 
@@ -17034,8 +17648,8 @@ days in order to avoid rounding problems."
      (unless (org-at-date-range-p t)
        (goto-char (point-at-bol))
        (re-search-forward org-tr-regexp-both (point-at-eol) t))
-     (if (not (org-at-date-range-p t))
-        (user-error "Not at a time-stamp range, and none found in current 
line")))
+     (unless (org-at-date-range-p t)
+       (user-error "Not at a time-stamp range, and none found in current 
line")))
    (let* ((ts1 (match-string 1))
          (ts2 (match-string 2))
          (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
@@ -17073,27 +17687,31 @@ days in order to avoid rounding problems."
             (setq align t)
             (and (looking-at " *|") (goto-char (match-end 0))))
         (goto-char match-end))
-       (if (looking-at
-           "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
-          (replace-match ""))
-       (if negative (insert " -"))
+       (when (looking-at
+             "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
+        (replace-match ""))
+       (when negative (insert " -"))
        (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
         (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
           (insert " " (format fh h m))))
-       (if align (org-table-align))
+       (when align (org-table-align))
        (message "Time difference inserted")))))
 
 (defun org-make-tdiff-string (y d h m)
   (let ((fmt "")
        (l nil))
-    (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
-                     l (push y l)))
-    (if (> d 0) (setq fmt (concat fmt "%d day"  (if (> d 1) "s" "") " ")
-                     l (push d l)))
-    (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
-                     l (push h l)))
-    (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
-                     l (push m l)))
+    (when (> y 0)
+      (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " "))
+      (push y l))
+    (when (> d 0)
+      (setq fmt (concat fmt "%d day"  (if (> d 1) "s" "") " "))
+      (push d l))
+    (when (> h 0)
+      (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " "))
+      (push h l))
+    (when (> m 0)
+      (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " "))
+      (push m l))
     (apply 'format fmt (nreverse l))))
 
 (defun org-time-string-to-time (s &optional buffer pos)
@@ -17110,28 +17728,40 @@ days in order to avoid rounding problems."
   "Convert a timestamp string to a number of seconds."
   (float-time (org-time-string-to-time s)))
 
-(defun org-time-string-to-absolute (s &optional daynr prefer show-all buffer 
pos)
-  "Convert a time stamp to an absolute day number.
-If there is a specifier for a cyclic time stamp, get the closest
-date to DAYNR.
-PREFER and SHOW-ALL are passed through to `org-closest-date'.
-The variable `date' is bound by the calendar when this is called."
+(org-define-error 'org-diary-sexp-no-match "Unable to match diary sexp")
+
+(defun org-time-string-to-absolute (s &optional daynr prefer buffer pos)
+  "Convert time stamp S to an absolute day number.
+
+If DAYNR in non-nil, and there is a specifier for a cyclic time
+stamp, get the closest date to DAYNR.  If PREFER is
+`past' (respectively `future') return a date past (respectively
+after) or equal to DAYNR.
+
+POS is the location of time stamp S, as a buffer position in
+BUFFER.
+
+Diary sexp timestamps are matched against DAYNR, when non-nil.
+If matching fails or DAYNR is nil, `org-diary-sexp-no-match' is
+signalled."
   (cond
-   ((and daynr (string-match "\\`%%\\((.*)\\)" s))
-    (if (org-diary-sexp-entry (match-string 1 s) "" date)
+   ((string-match "\\`%%\\((.*)\\)" s)
+    ;; Sexp timestamp: try to match DAYNR, if available, since we're
+    ;; only able to match individual dates.  If it fails, raise an
+    ;; error.
+    (if (and daynr
+            (org-diary-sexp-entry
+             (match-string 1 s) "" (calendar-gregorian-from-absolute daynr)))
        daynr
-      (+ daynr 1000)))
-   ((and daynr (string-match "\\+[0-9]+[hdwmy]" s))
-    (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr
-                         (time-to-days (current-time))) (match-string 0 s)
-                         prefer show-all))
+      (signal 'org-diary-sexp-no-match (list s))))
+   (daynr (org-closest-date s daynr prefer))
    (t (time-to-days
        (condition-case errdata
-          (apply 'encode-time (org-parse-time-string s))
+          (apply #'encode-time (org-parse-time-string s))
         (error (error "Bad timestamp `%s'%s\nError was: %s"
-                      s (if (not (and buffer pos))
-                            ""
-                          (format-message " at %d in buffer `%s'" pos buffer))
+                      s
+                      (if (not (and buffer pos)) ""
+                        (format-message " at %d in buffer `%s'" pos buffer))
                       (cdr errdata))))))))
 
 (defun org-days-to-iso-week (days)
@@ -17141,43 +17771,46 @@ The variable `date' is bound by the calendar when 
this is called."
 
 (defun org-small-year-to-year (year)
   "Convert 2-digit years into 4-digit years.
-38-99 are mapped into 1938-1999.  1-37 are mapped into 2001-2037.
-The year 2000 cannot be abbreviated.  Any year larger than 99
-is returned unchanged."
-  (if (< year 38)
-      (setq year (+ 2000 year))
-    (if (< year 100)
-       (setq year (+ 1900 year))))
-  year)
+YEAR is expanded into one of the 30 next years, if possible, or
+into a past one.  Any year larger than 99 is returned unchanged."
+  (if (>= year 100) year
+    (let* ((current (string-to-number (format-time-string "%Y" 
(current-time))))
+          (century (/ current 100))
+          (offset (- year (% current 100))))
+      (cond ((> offset 30) (+ (* (1- century) 100) year))
+           ((> offset -70) (+ (* century 100) year))
+           (t (+ (* (1+ century) 100) year))))))
 
 (defun org-time-from-absolute (d)
   "Return the time corresponding to date D.
 D may be an absolute day number, or a calendar-type list (month day year)."
-  (if (numberp d) (setq d (calendar-gregorian-from-absolute d)))
+  (when (numberp d) (setq d (calendar-gregorian-from-absolute d)))
   (encode-time 0 0 0 (nth 1 d) (car d) (nth 2 d)))
 
+(defvar org-agenda-current-date)
 (defun org-calendar-holiday ()
-  "List of holidays, for Diary display in Org-mode."
+  "List of holidays, for Diary display in Org mode."
   (require 'holidays)
-  (let ((hl (funcall
-            (if (fboundp 'calendar-check-holidays)
-                'calendar-check-holidays 'check-calendar-holidays) date)))
-    (if hl (mapconcat 'identity hl "; "))))
+  (let ((hl (calendar-check-holidays org-agenda-current-date)))
+    (and hl (mapconcat #'identity hl "; "))))
 
-(defun org-diary-sexp-entry (sexp entry date)
-  "Process a SEXP diary ENTRY for DATE."
+(defun org-diary-sexp-entry (sexp entry d)
+  "Process a SEXP diary ENTRY for date D."
   (require 'diary-lib)
-  (let ((result (if calendar-debug-sexp
-                    (let ((stack-trace-on-error t))
-                      (eval (car (read-from-string sexp))))
-                  (condition-case nil
-                      (eval (car (read-from-string sexp)))
-                    (error
-                     (beep)
-                     (message "Bad sexp at line %d in %s: %s"
-                             (org-current-line)
-                             (buffer-file-name) sexp)
-                     (sleep-for 2))))))
+  ;; `org-anniversary' and alike expect ENTRY and DATE to be bound
+  ;; dynamically.
+  (let* ((sexp `(let ((entry ,entry)
+                     (date ',d))
+                 ,(car (read-from-string sexp))))
+        (result (if calendar-debug-sexp (eval sexp)
+                  (condition-case nil
+                      (eval sexp)
+                    (error
+                     (beep)
+                     (message "Bad sexp at line %d in %s: %s"
+                              (org-current-line)
+                              (buffer-file-name) sexp)
+                     (sleep-for 2))))))
     (cond ((stringp result) (split-string result "; "))
          ((and (consp result)
                (not (consp (cdr result)))
@@ -17189,9 +17822,7 @@ D may be an absolute day number, or a calendar-type 
list (month day year)."
 (defun org-diary-to-ical-string (frombuf)
   "Get iCalendar entries from diary entries in buffer FROMBUF.
 This uses the icalendar.el library."
-  (let* ((tmpdir (if (featurep 'xemacs)
-                    (temp-directory)
-                  temporary-file-directory))
+  (let* ((tmpdir temporary-file-directory)
         (tmpfile (make-temp-name
                   (expand-file-name "orgics" tmpdir)))
         buf rtn b e)
@@ -17200,125 +17831,146 @@ This uses the icalendar.el library."
       (setq buf (find-buffer-visiting tmpfile))
       (set-buffer buf)
       (goto-char (point-min))
-      (if (re-search-forward "^BEGIN:VEVENT" nil t)
-         (setq b (match-beginning 0)))
+      (when (re-search-forward "^BEGIN:VEVENT" nil t)
+       (setq b (match-beginning 0)))
       (goto-char (point-max))
-      (if (re-search-backward "^END:VEVENT" nil t)
-         (setq e (match-end 0)))
+      (when (re-search-backward "^END:VEVENT" nil t)
+       (setq e (match-end 0)))
       (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") "")))
     (kill-buffer buf)
     (delete-file tmpfile)
     rtn))
 
-(defun org-closest-date (start current change prefer show-all)
-  "Find the date closest to CURRENT that is consistent with START and CHANGE.
-When PREFER is `past', return a date that is either CURRENT or past.
-When PREFER is `future', return a date that is either CURRENT or future.
-When SHOW-ALL is nil, only return the current occurrence of a time stamp."
-  ;; Make the proper lists from the dates
-  (catch 'exit
-    (let ((a1 '(("h" . hour)
-               ("d" . day)
-               ("w" . week)
-               ("m" . month)
-               ("y" . year)))
-         (shour (nth 2 (org-parse-time-string start)))
-         dn dw sday cday n1 n2 n0
-         d m y y1 y2 date1 date2 nmonths nm ny m2)
-
-      (setq start (org-date-to-gregorian start)
-           current (org-date-to-gregorian
-                    (if show-all
-                        current
-                      (time-to-days (current-time))))
-           sday (calendar-absolute-from-gregorian start)
-           cday  (calendar-absolute-from-gregorian current))
-
-      (if (<= cday sday) (throw 'exit sday))
-
-      (if (string-match "\\(\\+[0-9]+\\)\\([hdwmy]\\)" change)
-         (setq dn (string-to-number (match-string 1 change))
-               dw (cdr (assoc (match-string 2 change) a1)))
-       (user-error "Invalid change specifier: %s" change))
-      (if (eq dw 'week) (setq dw 'day dn (* 7 dn)))
-      (cond
-       ((eq dw 'hour)
-       (let ((missing-hours
-              (mod (+ (- (* 24 (- cday sday)) shour) org-extend-today-until)
-                   dn)))
-         (setq n1 (if (zerop missing-hours) cday
-                    (- cday (1+ (floor (/ missing-hours 24)))))
-               n2 (+ cday (floor (/ (- dn missing-hours) 24))))))
-       ((eq dw 'day)
-       (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn))))
-             n2 (+ n1 dn)))
-       ((eq dw 'year)
-       (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current))
-       (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1))
-       (setq date1 (list m d y1)
-             n1 (calendar-absolute-from-gregorian date1)
-             date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn)))
-             n2 (calendar-absolute-from-gregorian date2)))
-       ((eq dw 'month)
-       ;; approx number of month between the two dates
-       (setq nmonths (floor (/ (- cday sday) 30.436875)))
-       ;; How often does dn fit in there?
-       (setq d (nth 1 start) m (car start) y (nth 2 start)
-             nm (* dn (max 0 (1- (floor (/ nmonths dn)))))
-             m (+ m nm)
-             ny (floor (/ m 12))
-             y (+ y ny)
-             m (- m (* ny 12)))
-       (while (> m 12) (setq m (- m 12) y (1+ y)))
-       (setq n1 (calendar-absolute-from-gregorian (list m d y)))
-       (setq m2 (+ m dn) y2 y)
-       (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
-       (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))
-       (while (<= n2 cday)
-         (setq n1 n2 m m2 y y2)
-         (setq m2 (+ m dn) y2 y)
-         (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
-         (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))))))
-      ;; Make sure n1 is the earlier date
-      (setq n0 n1  n1 (min n1 n2)  n2 (max n0 n2))
-      (if show-all
-         (cond
-          ((eq prefer 'past)   (if (= cday n2) n2 n1))
-          ((eq prefer 'future) (if (= cday n1) n1 n2))
-          (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1)))
-       (cond
-        ((eq prefer 'past)   (if (= cday n2) n2 n1))
-        ((eq prefer 'future) (if (= cday n1) n1 n2))
-        (t (if (= cday n1) n1 n2)))))))
-
-(defun org-date-to-gregorian (date)
-  "Turn any specification of DATE into a Gregorian date for the calendar."
-  (cond ((integerp date) (calendar-gregorian-from-absolute date))
-       ((and (listp date) (= (length date) 3)) date)
-       ((stringp date)
-        (setq date (org-parse-time-string date))
-        (list (nth 4 date) (nth 3 date) (nth 5 date)))
-       ((listp date)
-        (list (nth 4 date) (nth 3 date) (nth 5 date)))))
-
-(defun org-parse-time-string (s &optional nodefault)
-  "Parse the standard Org-mode time string.
+(defun org-closest-date (start current prefer)
+  "Return closest date to CURRENT starting from START.
+
+CURRENT and START are both time stamps.
+
+When PREFER is `past', return a date that is either CURRENT or
+past.  When PREFER is `future', return a date that is either
+CURRENT or future.
+
+Only time stamps with a repeater are modified.  Any other time
+stamp stay unchanged.  In any case, return value is an absolute
+day number."
+  (if (not (string-match "\\+\\([0-9]+\\)\\([hdwmy]\\)" start))
+      ;; No repeater.  Do not shift time stamp.
+      (time-to-days (apply #'encode-time (org-parse-time-string start)))
+    (let ((value (string-to-number (match-string 1 start)))
+         (type (match-string 2 start)))
+      (if (= 0 value)
+         ;; Repeater with a 0-value is considered as void.
+         (time-to-days (apply #'encode-time (org-parse-time-string start)))
+       (let* ((base (org-date-to-gregorian start))
+              (target (org-date-to-gregorian current))
+              (sday (calendar-absolute-from-gregorian base))
+              (cday (calendar-absolute-from-gregorian target))
+              n1 n2)
+         ;; If START is already past CURRENT, just return START.
+         (if (<= cday sday) sday
+           ;; Compute closest date before (N1) and closest date past
+           ;; (N2) CURRENT.
+           (pcase type
+             ("h"
+              (let ((missing-hours
+                     (mod (+ (- (* 24 (- cday sday))
+                                (nth 2 (org-parse-time-string start)))
+                             org-extend-today-until)
+                          value)))
+                (setf n1 (if (= missing-hours 0) cday
+                           (- cday (1+ (/ missing-hours 24)))))
+                (setf n2 (+ cday (/ (- value missing-hours) 24)))))
+             ((or "d" "w")
+              (let ((value (if (equal type "w") (* 7 value) value)))
+                (setf n1 (+ sday (* value (/ (- cday sday) value))))
+                (setf n2 (+ n1 value))))
+             ("m"
+              (let* ((add-months
+                      (lambda (d n)
+                        ;; Add N months to gregorian date D, i.e.,
+                        ;; a list (MONTH DAY YEAR).  Return a valid
+                        ;; gregorian date.
+                        (let ((m (+ (nth 0 d) n)))
+                          (list (mod m 12)
+                                (nth 1 d)
+                                (+ (/ m 12) (nth 2 d))))))
+                     (months           ; Complete months to TARGET.
+                      (* (/ (+ (* 12 (- (nth 2 target) (nth 2 base)))
+                               (- (nth 0 target) (nth 0 base))
+                               ;; If START's day is greater than
+                               ;; TARGET's, remove incomplete month.
+                               (if (> (nth 1 target) (nth 1 base)) 0 -1))
+                            value)
+                         value))
+                     (before (funcall add-months base months)))
+                (setf n1 (calendar-absolute-from-gregorian before))
+                (setf n2
+                      (calendar-absolute-from-gregorian
+                       (funcall add-months before value)))))
+             (_
+              (let* ((d (nth 1 base))
+                     (m (nth 0 base))
+                     (y (nth 2 base))
+                     (years            ; Complete years to TARGET.
+                      (* (/ (- (nth 2 target)
+                               y
+                               ;; If START's month and day are
+                               ;; greater than TARGET's, remove
+                               ;; incomplete year.
+                               (if (or (> (nth 0 target) m)
+                                       (and (= (nth 0 target) m)
+                                            (> (nth 1 target) d)))
+                                   0
+                                 1))
+                            value)
+                         value))
+                     (before (list m d (+ y years))))
+                (setf n1 (calendar-absolute-from-gregorian before))
+                (setf n2 (calendar-absolute-from-gregorian
+                          (list m d (+ (nth 2 before) value)))))))
+           ;; Handle PREFER parameter, if any.
+           (cond
+            ((eq prefer 'past)   (if (= cday n2) n2 n1))
+            ((eq prefer 'future) (if (= cday n1) n1 n2))
+            (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1)))))))))
+
+(defun org-date-to-gregorian (d)
+  "Turn any specification of date D into a Gregorian date for the calendar."
+  (cond ((integerp d) (calendar-gregorian-from-absolute d))
+       ((and (listp d) (= (length d) 3)) d)
+       ((stringp d)
+        (let ((d (org-parse-time-string d)))
+          (list (nth 4 d) (nth 3 d) (nth 5 d))))
+       ((listp d) (list (nth 4 d) (nth 3 d) (nth 5 d)))))
+
+(defun org-parse-time-string (s &optional nodefault zone)
+  "Parse the standard Org time string.
+
 This should be a lot faster than the normal `parse-time-string'.
-If time is not given, defaults to 0:00.  However, with optional NODEFAULT,
-hour and minute fields will be nil if not given."
+
+If time is not given, defaults to 0:00.  However, with optional
+NODEFAULT, hour and minute fields will be nil if not given.
+
+The optional ZONE is omitted or nil for Emacs local time, t for
+Universal Time, ‘wall’ for system wall clock time, or a string as
+in the TZ environment variable."
   (cond ((string-match org-ts-regexp0 s)
         (list 0
-              (if (or (match-beginning 8) (not nodefault))
-                  (string-to-number (or (match-string 8 s) "0")))
-              (if (or (match-beginning 7) (not nodefault))
-                  (string-to-number (or (match-string 7 s) "0")))
+              (when (or (match-beginning 8) (not nodefault))
+                (string-to-number (or (match-string 8 s) "0")))
+              (when (or (match-beginning 7) (not nodefault))
+                (string-to-number (or (match-string 7 s) "0")))
               (string-to-number (match-string 4 s))
               (string-to-number (match-string 3 s))
               (string-to-number (match-string 2 s))
-              nil nil nil))
+              nil nil zone))
        ((string-match "^<[^>]+>$" s)
+        ;; FIXME: `decode-time' needs to be called with ZONE as its
+        ;; second argument.  However, this requires at least Emacs
+        ;; 25.1.  We can do it when we switch to this version as our
+        ;; minimal requirement.
         (decode-time (seconds-to-time (org-matcher-time s))))
-       (t (error "Not a standard Org-mode time string: %s" s))))
+       (t (error "Not a standard Org time string: %s" s))))
 
 (defun org-timestamp-up (&optional arg)
   "Increase the date item at the cursor by one.
@@ -17355,14 +18007,21 @@ With prefix ARG, change that many days."
     (org-timestamp-change (- (prefix-numeric-value arg)) 'day) 'updown))
 
 (defun org-at-timestamp-p (&optional inactive-ok)
-  "Determine if the cursor is in or at a timestamp."
+  "Non-nil if point is inside a timestamp.
+
+When optional argument INACTIVE-OK is non-nil, also consider
+inactive timestamps.
+
+When this function returns a non-nil value, match data is set
+according to `org-ts-regexp3' or `org-ts-regexp2', depending on
+INACTIVE-OK."
   (interactive)
   (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
         (pos (point))
         (ans (or (looking-at tsr)
                  (save-excursion
                    (skip-chars-backward "^[<\n\r\t")
-                   (if (> (point) (point-min)) (backward-char 1))
+                   (when (> (point) (point-min)) (backward-char 1))
                    (and (looking-at tsr)
                         (> (- (match-end 0) pos) -1))))))
     (and ans
@@ -17403,8 +18062,8 @@ With prefix ARG, change that many days."
 (defun org-at-clock-log-p nil
   "Is the cursor on the clock log line?"
   (save-excursion
-    (move-beginning-of-line 1)
-    (looking-at "^[ \t]*CLOCK:")))
+    (beginning-of-line)
+    (looking-at org-clock-line-re)))
 
 (defvar org-clock-history)                     ; defined in org-clock.el
 (defvar org-clock-adjust-closest nil)          ; defined in org-clock.el
@@ -17420,19 +18079,19 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
        org-ts-what
        extra rem
        ts time time0 fixnext clrgx)
-    (if (not (org-at-timestamp-p t))
-       (user-error "Not at a timestamp"))
+    (unless (org-at-timestamp-p t)
+      (user-error "Not at a timestamp"))
     (if (and (not what) (eq org-ts-what 'bracket))
        (org-toggle-timestamp-type)
       ;; Point isn't on brackets.  Remember the part of the time-stamp
       ;; the point was in.  Indeed, size of time-stamps may change,
       ;; but point must be kept in the same category nonetheless.
       (setq origin-cat org-ts-what)
-      (if (and (not what) (not (eq org-ts-what 'day))
-              org-display-custom-times
-              (get-text-property (point) 'display)
-              (not (get-text-property (1- (point)) 'display)))
-         (setq org-ts-what 'day))
+      (when (and (not what) (not (eq org-ts-what 'day))
+                org-display-custom-times
+                (get-text-property (point) 'display)
+                (not (get-text-property (1- (point)) 'display)))
+       (setq org-ts-what 'day))
       (setq org-ts-what (or what org-ts-what)
            inactive (= (char-after (match-beginning 0)) ?\[)
            ts (match-string 0))
@@ -17441,26 +18100,28 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
             "\\(\\(-[012][0-9]:[0-5][0-9]\\)?\\( 
+[.+]?-?[-+][0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)*\\)[]>]"
             ts)
        (setq extra (match-string 1 ts))
-       (if suppress-tmp-delay
-           (setq extra (replace-regexp-in-string " --[0-9]+[hdwmy]" "" 
extra))))
-      (if (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts)
-         (setq with-hm t))
+       (when suppress-tmp-delay
+         (setq extra (replace-regexp-in-string " --[0-9]+[hdwmy]" "" extra))))
+      (when (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts)
+       (setq with-hm t))
       (setq time0 (org-parse-time-string ts))
       (when (and updown
                 (eq org-ts-what 'minute)
                 (not current-prefix-arg))
        ;; This looks like s-up and s-down.  Change by one rounding step.
        (setq n (* dm (cond ((> n 0) 1) ((< n 0) -1) (t 0))))
-       (when (not (= 0 (setq rem (% (nth 1 time0) dm))))
+       (unless (= 0 (setq rem (% (nth 1 time0) dm)))
          (setcar (cdr time0) (+ (nth 1 time0)
                                 (if (> n 0) (- rem) (- dm rem))))))
       (setq time
-           (encode-time (or (car time0) 0)
-                        (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0))
-                        (+ (if (eq org-ts-what 'hour) n 0)   (nth 2 time0))
-                        (+ (if (eq org-ts-what 'day) n 0)    (nth 3 time0))
-                        (+ (if (eq org-ts-what 'month) n 0)  (nth 4 time0))
-                        (+ (if (eq org-ts-what 'year) n 0)   (nth 5 time0))))
+           (apply #'encode-time
+                  (or (car time0) 0)
+                  (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0))
+                  (+ (if (eq org-ts-what 'hour) n 0)   (nth 2 time0))
+                  (+ (if (eq org-ts-what 'day) n 0)    (nth 3 time0))
+                  (+ (if (eq org-ts-what 'month) n 0)  (nth 4 time0))
+                  (+ (if (eq org-ts-what 'year) n 0)   (nth 5 time0))
+                  (nthcdr 6 time0)))
       (when (and (member org-ts-what '(hour minute))
                 extra
                 (string-match "-\\([012][0-9]\\):\\([0-5][0-9]\\)" extra))
@@ -17470,15 +18131,15 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
                     n dm)))
       (when (integerp org-ts-what)
        (setq extra (org-modify-ts-extra extra org-ts-what n dm)))
-      (if (eq what 'calendar)
-         (let ((cal-date (org-get-date-from-calendar)))
-           (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
-           (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
-           (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
-           (setcar time0 (or (car time0) 0))
-           (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
-           (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
-           (setq time (apply 'encode-time time0))))
+      (when (eq what 'calendar)
+       (let ((cal-date (org-get-date-from-calendar)))
+         (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
+         (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
+         (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
+         (setcar time0 (or (car time0) 0))
+         (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
+         (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
+         (setq time (apply 'encode-time time0))))
       ;; Insert the new time-stamp, and ensure point stays in the same
       ;; category as before (i.e. not after the last position in that
       ;; category).
@@ -17489,17 +18150,21 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
        (goto-char pos))
       (save-match-data
        (looking-at org-ts-regexp3)
-       (goto-char (cond
-                   ;; `day' category ends before `hour' if any, or at
-                   ;; the end of the day name.
-                   ((eq origin-cat 'day)
-                    (min (or (match-beginning 7) (1- (match-end 5))) origin))
-                   ((eq origin-cat 'hour) (min (match-end 7) origin))
-                   ((eq origin-cat 'minute) (min (1- (match-end 8)) origin))
-                   ((integerp origin-cat) (min (1- (match-end 0)) origin))
-                   ;; `year' and `month' have both fixed size: point
-                   ;; couldn't have moved into another part.
-                   (t origin))))
+       (goto-char
+        (pcase origin-cat
+          ;; `day' category ends before `hour' if any, or at the end
+          ;; of the day name.
+          (`day (min (or (match-beginning 7) (1- (match-end 5))) origin))
+          (`hour (min (match-end 7) origin))
+          (`minute (min (1- (match-end 8)) origin))
+          ((pred integerp) (min (1- (match-end 0)) origin))
+          ;; Point was right after the time-stamp.  However, the
+          ;; time-stamp length might have changed, so refer to
+          ;; (match-end 0) instead.
+          (`after (match-end 0))
+          ;; `year' and `month' have both fixed size: point couldn't
+          ;; have moved into another part.
+          (_ origin))))
       ;; Update clock if on a CLOCK line.
       (org-clock-update-time-maybe)
       ;; Maybe adjust the closest clock in `org-clock-history'
@@ -17508,11 +18173,12 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
                      (< 1 (length (delq nil (mapcar 'marker-position
                                                     org-clock-history))))))
            (message "No clock to adjust")
-         (cond ((save-excursion ; fix previous clock?
+         (cond ((save-excursion        ; fix previous clock?
                   (re-search-backward org-ts-regexp0 nil t)
-                  (org-looking-back (concat org-clock-string " \\[")))
+                  (looking-back (concat org-clock-string " \\[")
+                                (line-beginning-position)))
                 (setq fixnext 1 clrgx (concat org-ts-regexp0 "\\] =>.*$")))
-               ((save-excursion ; fix next clock?
+               ((save-excursion        ; fix next clock?
                   (re-search-backward org-ts-regexp0 nil t)
                   (looking-at (concat org-ts-regexp0 "\\] =>")))
                 (setq fixnext -1 clrgx (concat org-clock-string " \\[" 
org-ts-regexp0))))
@@ -17521,8 +18187,8 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
            (let* ((p (save-excursion (org-back-to-heading t)))
                   (cl (mapcar (lambda(c) (abs (- (marker-position c) p))) 
org-clock-history))
                   (clfixnth
-                   (+ fixnext (- (length cl) (or (length (member (apply #'min 
cl) cl)) 100))))
-                  (clfixpos (if (> 0 clfixnth) nil (nth clfixnth 
org-clock-history))))
+                   (+ fixnext (- (length cl) (or (length (member (apply 'min 
cl) cl)) 100))))
+                  (clfixpos (unless (> 0 clfixnth) (nth clfixnth 
org-clock-history))))
              (if (not clfixpos)
                  (message "No clock to adjust")
                (save-excursion
@@ -17536,10 +18202,10 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
                             (file-name-nondirectory (buffer-file-name))
                             (org-get-heading t t)))))))))
       ;; Try to recenter the calendar window, if any.
-      (if (and org-calendar-follow-timestamp-change
-              (get-buffer-window "*Calendar*" t)
-              (memq org-ts-what '(day month year)))
-         (org-recenter-calendar (time-to-days time))))))
+      (when (and org-calendar-follow-timestamp-change
+                (get-buffer-window "*Calendar*" t)
+                (memq org-ts-what '(day month year)))
+       (org-recenter-calendar (time-to-days time))))))
 
 (defun org-modify-ts-extra (s pos n dm)
   "Change the different parts of the lead-time and repeat fields in timestamp."
@@ -17553,13 +18219,13 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
              h (string-to-number (match-string 2 s)))
        (if (org-pos-in-match-range pos 2)
            (setq h (+ h n))
-         (setq n (* dm (org-no-warnings (signum n))))
-         (when (not (= 0 (setq rem (% m dm))))
+         (setq n (* dm (with-no-warnings (signum n))))
+         (unless (= 0 (setq rem (% m dm)))
            (setq m (+ m (if (> n 0) (- rem) (- dm rem)))))
          (setq m (+ m n)))
-       (if (< m 0) (setq m (+ m 60) h (1- h)))
-       (if (> m 59) (setq m (- m 60) h (1+ h)))
-       (setq h (min 24 (max 0 h)))
+       (when (< m 0) (setq m (+ m 60) h (1- h)))
+       (when (> m 59) (setq m (- m 60) h (1+ h)))
+       (setq h (mod h 24))
        (setq ng 1 new (format "-%02d:%02d" h m)))
        ((org-pos-in-match-range pos 6)
        (setq ng 6 new (car (rassoc (+ n (cdr (assoc (match-string 6 s) idx))) 
idx))))
@@ -17578,14 +18244,14 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like \"--2d\"."
                 (substring s (match-end ng))))))
     s))
 
-(defun org-recenter-calendar (date)
-  "If the calendar is visible, recenter it to DATE."
+(defun org-recenter-calendar (d)
+  "If the calendar is visible, recenter it to date D."
   (let ((cwin (get-buffer-window "*Calendar*" t)))
     (when cwin
       (let ((calendar-move-hook nil))
        (with-selected-window cwin
-         (calendar-goto-date (if (listp date) date
-                               (calendar-gregorian-from-absolute date))))))))
+         (calendar-goto-date
+          (if (listp d) d (calendar-gregorian-from-absolute d))))))))
 
 (defun org-goto-calendar (&optional arg)
   "Go to the Emacs calendar at the current date.
@@ -17596,17 +18262,17 @@ A prefix ARG can be used to force the current date."
        (calendar-move-hook nil)
        (calendar-view-holidays-initially-flag nil)
        (calendar-view-diary-initially-flag nil))
-    (if (or (org-at-timestamp-p)
-           (save-excursion
-             (beginning-of-line 1)
-             (looking-at (concat ".*" tsr))))
-       (let ((d1 (time-to-days (current-time)))
-             (d2 (time-to-days
-                  (org-time-string-to-time (match-string 1)))))
-         (setq diff (- d2 d1))))
+    (when (or (org-at-timestamp-p)
+             (save-excursion
+               (beginning-of-line 1)
+               (looking-at (concat ".*" tsr))))
+      (let ((d1 (time-to-days (current-time)))
+           (d2 (time-to-days
+                (org-time-string-to-time (match-string 1)))))
+       (setq diff (- d2 d1))))
     (calendar)
     (calendar-goto-today)
-    (if (and diff (not arg)) (calendar-forward-day diff))))
+    (when (and diff (not arg)) (calendar-forward-day diff))))
 
 (defun org-get-date-from-calendar ()
   "Return a list (month day year) of date at point in calendar."
@@ -17625,7 +18291,8 @@ If there is already a time stamp at the cursor 
position, update it."
        (encode-time 0 0 0 (nth 1 cal-date) (car cal-date) (nth 2 cal-date))))))
 
 (defcustom org-effort-durations
-  `(("h" . 60)
+  `(("min" . 1)
+    ("h" . 60)
     ("d" . ,(* 60 8))
     ("w" . ,(* 60 8 5))
     ("m" . ,(* 60 8 5 4))
@@ -17641,7 +18308,8 @@ minutes.
 For example, if the value of this variable is ((\"hours\" . 60)), then an
 effort string \"2hours\" is equivalent to 120 minutes."
   :group 'org-agenda
-  :version "24.1"
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(alist :key-type (string :tag "Modifier")
                :value-type (number :tag "Minutes")))
 
@@ -17734,10 +18402,6 @@ The format is determined by `org-time-clocksum-format',
        ;; return formatted time duration
        clocksum))))
 
-(defalias 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string)
-(make-obsolete 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string
-              "Org mode version 8.0")
-
 (defun org-hours-to-clocksum-string (n)
   (org-minutes-to-clocksum-string (* n 60)))
 
@@ -17793,19 +18457,21 @@ tables are not re-aligned, etc."
   :version "24.3"
   :group 'org-agenda)
 
-(defcustom org-agenda-ignore-drawer-properties nil
+(defcustom org-agenda-ignore-properties nil
   "Avoid updating text properties when building the agenda.
-Properties are used to prepare buffers for effort estimates, appointments,
-and subtree-local categories.
-If you don't use these in the agenda, you can add them to this list and
-agenda building will be a bit faster.
+Properties are used to prepare buffers for effort estimates,
+appointments, statistics and subtree-local categories.
+If you don't use these in the agenda, you can add them to this
+list and agenda building will be a bit faster.
 The value is a list, with zero or more of the symbols `effort', `appt',
-or `category'."
+`stats' or `category'."
   :type '(set :greedy t
              (const effort)
              (const appt)
+             (const stats)
              (const category))
-  :version "24.3"
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :group 'org-agenda)
 
 (defun org-duration-string-to-minutes (s &optional output-to-string)
@@ -17821,25 +18487,25 @@ Entries containing a colon are interpreted as H:MM by
                    (regexp-opt (mapcar 'car org-effort-durations))
                    "\\)")))
     (while (string-match re s)
-      (incf result (* (cdr (assoc (match-string 2 s) org-effort-durations))
-                     (string-to-number (match-string 1 s))))
+      (cl-incf result (* (cdr (assoc (match-string 2 s) org-effort-durations))
+                        (string-to-number (match-string 1 s))))
       (setq s (replace-match "" nil t s)))
     (setq result (floor result))
-    (incf result (org-hh:mm-string-to-minutes s))
+    (cl-incf result (org-hh:mm-string-to-minutes s))
     (if output-to-string (number-to-string result) result)))
 
 ;;;; Files
 
 (defun org-save-all-org-buffers ()
-  "Save all Org-mode buffers without user confirmation."
+  "Save all Org buffers without user confirmation."
   (interactive)
-  (message "Saving all Org-mode buffers...")
+  (message "Saving all Org buffers...")
   (save-some-buffers t (lambda () (derived-mode-p 'org-mode)))
   (when (featurep 'org-id) (org-id-locations-save))
-  (message "Saving all Org-mode buffers... done"))
+  (message "Saving all Org buffers... done"))
 
 (defun org-revert-all-org-buffers ()
-  "Revert all Org-mode buffers.
+  "Revert all Org buffers.
 Prompt for confirmation when there are unsaved changes.
 Be sure you know what you are doing before letting this function
 overwrite your changes.
@@ -17856,13 +18522,11 @@ changes from another.  I believe the procedure must 
be like this:
     (user-error "Abort"))
   (save-excursion
     (save-window-excursion
-      (mapc
-       (lambda (b)
-        (when (and (with-current-buffer b (derived-mode-p 'org-mode))
-                   (with-current-buffer b buffer-file-name))
-          (org-pop-to-buffer-same-window b)
-          (revert-buffer t 'no-confirm)))
-       (buffer-list))
+      (dolist (b (buffer-list))
+       (when (and (with-current-buffer b (derived-mode-p 'org-mode))
+                  (with-current-buffer b buffer-file-name))
+         (pop-to-buffer-same-window b)
+         (revert-buffer t 'no-confirm)))
       (when (and (featurep 'org-id) org-id-track-globally)
        (org-id-locations-load)))))
 
@@ -17871,29 +18535,19 @@ changes from another.  I believe the procedure must 
be like this:
 ;;;###autoload
 (defun org-switchb (&optional arg)
   "Switch between Org buffers.
-With one prefix argument, restrict available buffers to files.
-With two prefix arguments, restrict available buffers to agenda files.
 
-Defaults to `iswitchb' for buffer name completion.
-Set `org-completion-use-ido' to make it use ido instead."
+With `\\[universal-argument]' prefix, restrict available buffers to files.
+
+With `\\[universal-argument] \\[universal-argument]' \
+prefix, restrict available buffers to agenda files."
   (interactive "P")
-  (let ((blist (cond ((equal arg '(4))  (org-buffer-list 'files))
-                     ((equal arg '(16)) (org-buffer-list 'agenda))
-                     (t                 (org-buffer-list))))
-       (org-completion-use-iswitchb org-completion-use-iswitchb)
-       (org-completion-use-ido org-completion-use-ido))
-    (unless (or org-completion-use-ido org-completion-use-iswitchb)
-      (setq org-completion-use-iswitchb t))
-    (org-pop-to-buffer-same-window
-     (org-icompleting-read "Org buffer: "
-                          (mapcar 'list (mapcar 'buffer-name blist))
-                          nil t))))
-
-;;; Define some older names previously used for this functionality
-;;;###autoload
-(defalias 'org-ido-switchb 'org-switchb)
-;;;###autoload
-(defalias 'org-iswitchb 'org-switchb)
+  (let ((blist (org-buffer-list
+               (cond ((equal arg '(4))  'files)
+                     ((equal arg '(16)) 'agenda)))))
+    (pop-to-buffer-same-window
+     (completing-read "Org buffer: "
+                     (mapcar #'list (mapcar #'buffer-name blist))
+                     nil t))))
 
 (defun org-buffer-list (&optional predicate exclude-tmp)
   "Return a list of Org buffers.
@@ -17968,8 +18622,10 @@ used by the agenda files.  If ARCHIVE is `ifmode', do 
this only if
   "Return non-nil, if FILE is an agenda file.
 If FILE is omitted, use the file associated with the current
 buffer."
-  (member (or file (buffer-file-name))
-          (org-agenda-files t)))
+  (let ((fname (or file (buffer-file-name))))
+    (and fname
+         (member (file-truename fname)
+                 (mapcar #'file-truename (org-agenda-files t))))))
 
 (defun org-edit-agenda-file-list ()
   "Edit the list of agenda files.
@@ -17981,15 +18637,15 @@ the buffer and restores the previous window 
configuration."
   (if (stringp org-agenda-files)
       (let ((cw (current-window-configuration)))
        (find-file org-agenda-files)
-       (org-set-local 'org-window-configuration cw)
-       (org-add-hook 'after-save-hook
-                     (lambda ()
-                       (set-window-configuration
-                        (prog1 org-window-configuration
-                          (kill-buffer (current-buffer))))
-                       (org-install-agenda-files-menu)
-                       (message "New agenda file list installed"))
-                     nil 'local)
+       (setq-local org-window-configuration cw)
+       (add-hook 'after-save-hook
+                 (lambda ()
+                   (set-window-configuration
+                    (prog1 org-window-configuration
+                      (kill-buffer (current-buffer))))
+                   (org-install-agenda-files-menu)
+                   (message "New agenda file list installed"))
+                 nil 'local)
        (message "%s" (substitute-command-keys
                       "Edit list and finish with \\[save-buffer]")))
     (customize-variable 'org-agenda-files)))
@@ -18039,19 +18695,16 @@ un-expanded file names."
 If the current buffer visits an agenda file, find the next one in the list.
 If the current buffer does not, find the first agenda file."
   (interactive)
-  (let* ((fs (org-agenda-files t))
-        (files (append fs (list (car fs))))
-        (tcf (if buffer-file-name (file-truename buffer-file-name)))
+  (let* ((fs (or (org-agenda-files t)
+                (user-error "No agenda files")))
+        (files (copy-sequence fs))
+        (tcf (and buffer-file-name (file-truename buffer-file-name)))
         file)
-    (unless files (user-error "No agenda files"))
-    (catch 'exit
-      (dolist (file files)
-       (if (equal (file-truename file) tcf)
-           (when (car files)
-             (find-file (car files))
-             (throw 'exit t))))
-      (find-file (car fs)))
-    (if (buffer-base-buffer) (org-pop-to-buffer-same-window 
(buffer-base-buffer)))))
+    (when tcf
+      (while (and (setq file (pop files))
+                 (not (equal (file-truename file) tcf)))))
+    (find-file (car (or files fs)))
+    (when (buffer-base-buffer) (pop-to-buffer-same-window 
(buffer-base-buffer)))))
 
 (defun org-agenda-file-to-front (&optional to-end)
   "Move/add the current file to the top of the agenda file list.
@@ -18069,7 +18722,7 @@ end of the list."
        x had)
     (setq x (assoc ctf file-alist) had x)
 
-    (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
+    (unless x (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
     (if to-end
        (setq file-alist (append (delq x file-alist) (list x)))
       (setq file-alist (cons x (delq x file-alist))))
@@ -18090,15 +18743,15 @@ Optional argument FILE means use this file instead of 
the current."
         (afile (abbreviate-file-name file))
         (files (delq nil (mapcar
                           (lambda (x)
-                            (if (equal true-file
-                                       (file-truename x))
-                                nil x))
+                            (unless (equal true-file
+                                           (file-truename x))
+                              x))
                           (org-agenda-files t)))))
     (if (not (= (length files) (length (org-agenda-files t))))
        (progn
          (org-store-new-agenda-file-list files)
          (org-install-agenda-files-menu)
-         (message "Removed file: %s" afile))
+         (message "Removed from Org Agenda list: %s" afile))
       (message "File was not in list: %s (not removed)" afile))))
 
 (defun org-file-menu-entry (file)
@@ -18106,7 +18759,7 @@ Optional argument FILE means use this file instead of 
the current."
 
 (defun org-check-agenda-file (file)
   "Make sure FILE exists.  If not, ask user what to do."
-  (when (not (file-exists-p file))
+  (unless (file-exists-p file)
     (message "Non-existent agenda file %s.  [R]emove from list or [A]bort?"
             (abbreviate-file-name file))
     (let ((r (downcase (read-char-exclusive))))
@@ -18114,17 +18767,18 @@ Optional argument FILE means use this file instead of 
the current."
        ((equal r ?r)
        (org-remove-file file)
        (throw 'nextfile t))
-       (t (error "Abort"))))))
+       (t (user-error "Abort"))))))
 
 (defun org-get-agenda-file-buffer (file)
-  "Get a buffer visiting FILE.  If the buffer needs to be created, add
-it to the list of buffers which might be released later."
+  "Get an agenda buffer visiting FILE.
+If the buffer needs to be created, add it to the list of buffers
+which might be released later."
   (let ((buf (org-find-base-buffer-visiting file)))
     (if buf
        buf ; just return it
       ;; Make a new buffer and remember it
       (setq buf (find-file-noselect file))
-      (if buf (push buf org-agenda-new-buffers))
+      (when buf (push buf org-agenda-new-buffers))
       buf)))
 
 (defun org-release-buffers (blist)
@@ -18149,7 +18803,7 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
        (inhibit-read-only t)
        (org-inhibit-startup org-agenda-inhibit-startup)
        (rea (concat ":" org-archive-tag ":"))
-       file re pos)
+       re pos)
     (setq org-tag-alist-for-agenda nil
          org-tag-groups-alist-for-agenda nil)
     (save-excursion
@@ -18161,20 +18815,15 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
              (org-check-agenda-file file)
              (set-buffer (org-get-agenda-file-buffer file)))
            (widen)
-           (org-set-regexps-and-options-for-tags)
+           (org-set-regexps-and-options 'tags-only)
            (setq pos (point))
-           (goto-char (point-min))
-           (let ((case-fold-search t))
-             (when (search-forward "#+setupfile" nil t)
-               ;; Don't set all regexps and options systematically as
-               ;; this is only run for setting agenda tags from setup
-               ;; file
-               (org-set-regexps-and-options)))
-           (or (memq 'category org-agenda-ignore-drawer-properties)
+           (or (memq 'category org-agenda-ignore-properties)
                (org-refresh-category-properties))
-           (or (memq 'effort org-agenda-ignore-drawer-properties)
-               (org-refresh-properties org-effort-property 'org-effort))
-           (or (memq 'appt org-agenda-ignore-drawer-properties)
+           (or (memq 'stats org-agenda-ignore-properties)
+               (org-refresh-stats-properties))
+           (or (memq 'effort org-agenda-ignore-properties)
+               (org-refresh-effort-properties))
+           (or (memq 'appt org-agenda-ignore-properties)
                (org-refresh-properties "APPT_WARNTIME" 'org-appt-warntime))
            (setq org-todo-keywords-for-agenda
                  (append org-todo-keywords-for-agenda org-todo-keywords-1))
@@ -18182,31 +18831,32 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
                  (append org-done-keywords-for-agenda org-done-keywords))
            (setq org-todo-keyword-alist-for-agenda
                  (append org-todo-keyword-alist-for-agenda org-todo-key-alist))
-           (setq org-drawers-for-agenda
-                 (append org-drawers-for-agenda org-drawers))
            (setq org-tag-alist-for-agenda
                  (org-uniquify
                   (append org-tag-alist-for-agenda
-                          org-tag-alist
-                          org-tag-persistent-alist)))
-           (if org-group-tags
-               (setq org-tag-groups-alist-for-agenda
-                     (org-uniquify-alist
-                      (append org-tag-groups-alist-for-agenda 
org-tag-groups-alist))))
+                          org-current-tag-alist)))
+           ;; Merge current file's tag groups into global
+           ;; `org-tag-groups-alist-for-agenda'.
+           (when org-group-tags
+             (dolist (alist org-tag-groups-alist)
+               (let ((old (assoc (car alist) org-tag-groups-alist-for-agenda)))
+                 (if old
+                     (setcdr old (org-uniquify (append (cdr old) (cdr alist))))
+                   (push alist org-tag-groups-alist-for-agenda)))))
            (org-with-silent-modifications
             (save-excursion
               (remove-text-properties (point-min) (point-max) pall)
               (when org-agenda-skip-archived-trees
                 (goto-char (point-min))
                 (while (re-search-forward rea nil t)
-                  (if (org-at-heading-p t)
-                      (add-text-properties (point-at-bol) (org-end-of-subtree 
t) pa))))
+                  (when (org-at-heading-p t)
+                    (add-text-properties (point-at-bol) (org-end-of-subtree t) 
pa))))
               (goto-char (point-min))
-              (setq re (format org-heading-keyword-regexp-format
-                               org-comment-string))
+              (setq re (format "^\\*+ .*\\<%s\\>" org-comment-string))
               (while (re-search-forward re nil t)
-                (add-text-properties
-                 (match-beginning 0) (org-end-of-subtree t) pc))))
+                (when (save-match-data (org-in-commented-heading-p t))
+                  (add-text-properties
+                   (match-beginning 0) (org-end-of-subtree t) pc)))))
            (goto-char pos)))))
     (setq org-todo-keywords-for-agenda
           (org-uniquify org-todo-keywords-for-agenda))
@@ -18223,7 +18873,7 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
 (org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
 (org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
 (org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
-(org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
+(org-defkey org-cdlatex-mode-map "\C-c{" 'org-cdlatex-environment-indent)
 
 (defvar org-cdlatex-texmathp-advice-is-done nil
   "Flag remembering if we have applied the advice to texmathp already.")
@@ -18231,7 +18881,7 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
 (define-minor-mode org-cdlatex-mode
   "Toggle the minor `org-cdlatex-mode'.
 This mode supports entering LaTeX environment and math in LaTeX fragments
-in Org-mode.
+in Org mode.
 \\{org-cdlatex-mode-map}"
   nil " OCDL" nil
   (when org-cdlatex-mode
@@ -18241,11 +18891,11 @@ in Org-mode.
   (unless org-cdlatex-texmathp-advice-is-done
     (setq org-cdlatex-texmathp-advice-is-done t)
     (defadvice texmathp (around org-math-always-on activate)
-      "Always return t in org-mode buffers.
+      "Always return t in Org buffers.
 This is because we want to insert math symbols without dollars even outside
-the LaTeX math segments.  If Orgmode thinks that point is actually inside
-an embedded LaTeX fragment, let texmathp do its job.
-\\[org-cdlatex-mode-map]"
+the LaTeX math segments.  If Org mode thinks that point is actually inside
+an embedded LaTeX fragment, let `texmathp' do its job.
+`\\[org-cdlatex-mode-map]'"
       (interactive)
       (let (p)
        (cond
@@ -18257,8 +18907,8 @@ an embedded LaTeX fragment, let texmathp do its job.
          (let ((p (org-inside-LaTeX-fragment-p)))
            (if (and p (member (car p) (plist-get org-format-latex-options 
:matchers)))
                (setq ad-return-value t
-                     texmathp-why '("Org-mode embedded math" . 0))
-             (if p ad-do-it)))))))))
+                     texmathp-why '("Org mode embedded math" . 0))
+             (when p ad-do-it)))))))))
 
 (defun turn-on-org-cdlatex ()
   "Unconditionally turn on `org-cdlatex-mode'."
@@ -18283,7 +18933,7 @@ It makes sense to do so if `org-cdlatex-mode' is active 
and if the cursor is
       (cdlatex-tab) t)
      ((org-inside-LaTeX-fragment-p) (cdlatex-tab) t))))
 
-(defun org-cdlatex-underscore-caret (&optional arg)
+(defun org-cdlatex-underscore-caret (&optional _arg)
   "Execute `cdlatex-sub-superscript' in LaTeX fragments.
 Revert to the normal definition outside of these fragments."
   (interactive "P")
@@ -18292,7 +18942,7 @@ Revert to the normal definition outside of these 
fragments."
     (let (org-cdlatex-mode)
       (call-interactively (key-binding (vector last-input-event))))))
 
-(defun org-cdlatex-math-modify (&optional arg)
+(defun org-cdlatex-math-modify (&optional _arg)
   "Execute `cdlatex-math-modify' in LaTeX fragments.
 Revert to the normal definition outside of these fragments."
   (interactive "P")
@@ -18301,21 +18951,66 @@ Revert to the normal definition outside of these 
fragments."
     (let (org-cdlatex-mode)
       (call-interactively (key-binding (vector last-input-event))))))
 
+(defun org-cdlatex-environment-indent (&optional environment item)
+  "Execute `cdlatex-environment' and indent the inserted environment.
+
+ENVIRONMENT and ITEM are passed to `cdlatex-environment'.
+
+The inserted environment is indented to current indentation
+unless point is at the beginning of the line, in which the
+environment remains unintended."
+  (interactive)
+  ;; cdlatex-environment always return nil.  Therefore, capture output
+  ;; first and determine if an environment was selected.
+  (let* ((beg (point-marker))
+        (end (copy-marker (point) t))
+        (inserted (progn
+                    (ignore-errors (cdlatex-environment environment item))
+                    (< beg end)))
+        ;; Figure out how many lines to move forward after the
+        ;; environment has been inserted.
+        (lines (when inserted
+                 (save-excursion
+                   (- (cl-loop while (< beg (point))
+                               with x = 0
+                               do (forward-line -1)
+                               (cl-incf x)
+                               finally return x)
+                      (if (progn (goto-char beg)
+                                 (and (progn (skip-chars-forward " \t") (eolp))
+                                      (progn (skip-chars-backward " \t") 
(bolp))))
+                          1 0)))))
+        (env (org-trim (delete-and-extract-region beg end))))
+    (when inserted
+      ;; Get indentation of next line unless at column 0.
+      (let ((ind (if (bolp) 0
+                  (save-excursion
+                    (org-return-indent)
+                    (prog1 (org-get-indentation)
+                      (when (progn (skip-chars-forward " \t") (eolp))
+                        (delete-region beg (point)))))))
+           (bol (progn (skip-chars-backward " \t") (bolp))))
+       ;; Insert a newline before environment unless at column zero
+       ;; to "escape" the current line.  Insert a newline if
+       ;; something is one the same line as \end{ENVIRONMENT}.
+       (insert
+        (concat (unless bol "\n") env
+                (when (and (skip-chars-forward " \t") (not (eolp))) "\n")))
+       (unless (zerop ind)
+         (save-excursion
+           (goto-char beg)
+           (while (< (point) end)
+             (unless (eolp) (indent-line-to ind))
+             (forward-line))))
+       (goto-char beg)
+       (forward-line lines)
+       (indent-line-to ind)))
+    (set-marker beg nil)
+    (set-marker end nil)))
 
 
 ;;;; LaTeX fragments
 
-(defvar org-latex-regexps
-  '(("begin" "^[ 
\t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
-    ;; ("$" "\\([      (]\\|^\\)\\(\\(\\([$]\\)\\([^   
\r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^       \r\n,.$]\\)\\4\\)\\)\\([        
.,?;:'\")]\\|$\\)" 2 nil)
-    ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
-    ("$1" "\\([^$]\\|^\\)\\(\\$[^      \r\n,;.$]\\$\\)\\([-    
.,?;:'\")\000]\\|$\\)" 2 nil)
-    ("$" "\\([^$]\\|^\\)\\(\\(\\$\\([^         
\r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^        
\r\n,.$]\\)\\$\\)\\)\\([-       .,?;:'\")\000]\\|$\\)" 2 nil)
-    ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
-    ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 nil)
-    ("$$" "\\$\\$[^\000]*?\\$\\$" 0 nil))
-  "Regular expressions for matching embedded LaTeX.")
-
 (defun org-inside-LaTeX-fragment-p ()
   "Test if point is inside a LaTeX fragment.
 I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
@@ -18358,7 +19053,7 @@ looks only before point, not after."
        (while (re-search-backward "\\$\\$" lim t)
          (setq dd-on (not dd-on)))
        (goto-char pos)
-       (if dd-on (cons "$$" m))))))
+       (when dd-on (cons "$$" m))))))
 
 (defun org-inside-latex-macro-p ()
   "Is point inside a LaTeX macro or its arguments?"
@@ -18366,179 +19061,226 @@ looks only before point, not after."
     (org-in-regexp
      "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")))
 
-(defvar org-latex-fragment-image-overlays nil
-  "List of overlays carrying the images of latex fragments.")
-(make-variable-buffer-local 'org-latex-fragment-image-overlays)
+(defun org--format-latex-make-overlay (beg end image &optional imagetype)
+  "Build an overlay between BEG and END using IMAGE file.
+Argument IMAGETYPE is the extension of the displayed image,
+as a string.  It defaults to \"png\"."
+  (let ((ov (make-overlay beg end))
+       (imagetype (or (intern imagetype) 'png)))
+    (overlay-put ov 'org-overlay-type 'org-latex-overlay)
+    (overlay-put ov 'evaporate t)
+    (overlay-put ov
+                'modification-hooks
+                (list (lambda (o _flag _beg _end &optional _l)
+                        (delete-overlay o))))
+    (overlay-put ov
+                'display
+                (list 'image :type imagetype :file image :ascent 'center))))
+
+(defun org--list-latex-overlays (&optional beg end)
+  "List all Org LaTeX overlays in current buffer.
+Limit to overlays between BEG and END when those are provided."
+  (cl-remove-if-not
+   (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay))
+   (overlays-in (or beg (point-min)) (or end (point-max)))))
+
+(defun org-remove-latex-fragment-image-overlays (&optional beg end)
+  "Remove all overlays with LaTeX fragment images in current buffer.
+When optional arguments BEG and END are non-nil, remove all
+overlays between them instead.  Return a non-nil value when some
+overlays were removed, nil otherwise."
+  (let ((overlays (org--list-latex-overlays beg end)))
+    (mapc #'delete-overlay overlays)
+    overlays))
+
+(defun org-toggle-latex-fragment (&optional arg)
+  "Preview the LaTeX fragment at point, or all locally or globally.
 
-(defun org-remove-latex-fragment-image-overlays ()
-  "Remove all overlays with LaTeX fragment images in current buffer."
-  (mapc 'delete-overlay org-latex-fragment-image-overlays)
-  (setq org-latex-fragment-image-overlays nil))
+If the cursor is on a LaTeX fragment, create the image and overlay
+it over the source code, if there is none.  Remove it otherwise.
+If there is no fragment at point, display all fragments in the
+current section.
 
-(defun org-preview-latex-fragment (&optional subtree)
-  "Preview the LaTeX fragment at point, or all locally or globally.
-If the cursor is in a LaTeX fragment, create the image and overlay
-it over the source code.  If there is no fragment at point, display
-all fragments in the current text, from one headline to the next.  With
-prefix SUBTREE, display all fragments in the current subtree.  With a
-double prefix arg \\[universal-argument] \\[universal-argument], or when \
-the cursor is before the first headline,
-display all fragments in the buffer.
-The images can be removed again with \\[org-ctrl-c-ctrl-c]."
+With prefix ARG, preview or clear image for all fragments in the
+current subtree or in the whole buffer when used before the first
+headline.  With a prefix ARG `\\[universal-argument] \
+\\[universal-argument]' preview or clear images
+for all fragments in the buffer."
   (interactive "P")
-  (unless buffer-file-name
-    (user-error "Can't preview LaTeX fragment in a non-file buffer"))
   (when (display-graphic-p)
-    (org-remove-latex-fragment-image-overlays)
-    (save-excursion
-      (save-restriction
-       (let (beg end at msg)
+    (catch 'exit
+      (save-excursion
+       (let (beg end msg)
          (cond
-          ((or (equal subtree '(16))
-               (not (save-excursion
-                      (re-search-backward org-outline-regexp-bol nil t))))
-           (setq beg (point-min) end (point-max)
-                 msg "Creating images for buffer...%s"))
-          ((equal subtree '(4))
-           (org-back-to-heading)
-           (setq beg (point) end (org-end-of-subtree t)
-                 msg "Creating images for subtree...%s"))
+          ((or (equal arg '(16))
+               (and (equal arg '(4))
+                    (org-with-limited-levels (org-before-first-heading-p))))
+           (if (org-remove-latex-fragment-image-overlays)
+               (progn (message "LaTeX fragments images removed from buffer")
+                      (throw 'exit nil))
+             (setq msg "Creating images for buffer...")))
+          ((equal arg '(4))
+           (org-with-limited-levels (org-back-to-heading t))
+           (setq beg (point))
+           (setq end (progn (org-end-of-subtree t) (point)))
+           (if (org-remove-latex-fragment-image-overlays beg end)
+               (progn
+                 (message "LaTeX fragment images removed from subtree")
+                 (throw 'exit nil))
+             (setq msg "Creating images for subtree...")))
+          ((let ((datum (org-element-context)))
+             (when (memq (org-element-type datum)
+                         '(latex-environment latex-fragment))
+               (setq beg (org-element-property :begin datum))
+               (setq end (org-element-property :end datum))
+               (if (org-remove-latex-fragment-image-overlays beg end)
+                   (progn (message "LaTeX fragment image removed")
+                          (throw 'exit nil))
+                 (setq msg "Creating image...")))))
           (t
-           (if (setq at (org-inside-LaTeX-fragment-p))
-               (goto-char (max (point-min) (- (cdr at) 2)))
-             (org-back-to-heading))
-           (setq beg (point) end (progn (outline-next-heading) (point))
-                 msg (if at "Creating image...%s"
-                       "Creating images for entry...%s"))))
-         (message msg "")
-         (narrow-to-region beg end)
-         (goto-char beg)
-         (org-format-latex
-          (concat org-latex-preview-ltxpng-directory (file-name-sans-extension
-                                                      (file-name-nondirectory
-                                                       buffer-file-name)))
-          default-directory 'overlays msg at 'forbuffer
-          org-latex-create-formula-image-program)
-         (message msg "done.  Use `C-c C-c' to remove images."))))))
-
-(defun org-format-latex (prefix &optional dir overlays msg at
-                               forbuffer processing-type)
-  "Replace LaTeX fragments with links to an image, and produce images.
+           (org-with-limited-levels
+            (setq beg (if (org-at-heading-p) (line-beginning-position)
+                        (outline-previous-heading)
+                        (point)))
+            (setq end (progn (outline-next-heading) (point)))
+            (if (org-remove-latex-fragment-image-overlays beg end)
+                (progn
+                  (message "LaTeX fragment images removed from section")
+                  (throw 'exit nil))
+              (setq msg "Creating images for section...")))))
+         (let ((file (buffer-file-name (buffer-base-buffer))))
+           (org-format-latex
+            (concat org-preview-latex-image-directory "org-ltximg")
+            beg end
+            ;; Emacs cannot overlay images from remote hosts.  Create
+            ;; it in `temporary-file-directory' instead.
+            (if (or (not file) (file-remote-p file))
+                temporary-file-directory
+              default-directory)
+            'overlays msg 'forbuffer org-preview-latex-default-process))
+         (message (concat msg "done")))))))
+
+(defun org-format-latex
+    (prefix &optional beg end dir overlays msg forbuffer processing-type)
+  "Replace LaTeX fragments with links to an image.
+
+The function takes care of creating the replacement image.
+
+Only consider fragments between BEG and END when those are
+provided.
+
+When optional argument OVERLAYS is non-nil, display the image on
+top of the fragment instead of replacing it.
+
+PROCESSING-TYPE is the conversion method to use, as a symbol.
+
 Some of the options can be changed using the variable
-`org-format-latex-options'."
-  (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
-  (let* ((prefixnodir (file-name-nondirectory prefix))
-        (absprefix (expand-file-name prefix dir))
-        (todir (file-name-directory absprefix))
-        (opt org-format-latex-options)
-        (optnew org-format-latex-options)
-        (matchers (plist-get opt :matchers))
-        (re-list org-latex-regexps)
-        (cnt 0) txt hash link beg end re checkdir
-        string
-        m n block-type block linkfile movefile ov)
-    ;; Check the different regular expressions
-    (dolist (e re-list)
-      (setq m (car e) re (nth 1 e) n (nth 2 e) block-type (nth 3 e)
-           block (if block-type "\n\n" ""))
-      (when (member m matchers)
-       (goto-char (point-min))
-       (while (re-search-forward re nil t)
-         (when (and (or (not at) (equal (cdr at) (match-beginning n)))
-                    (or (not overlays)
-                        (not (eq (get-char-property (match-beginning n)
-                                                    'org-overlay-type)
-                                 'org-latex-overlay))))
-           (cond
-            ((eq processing-type 'verbatim))
-            ((eq processing-type 'mathjax)
-             ;; Prepare for MathJax processing.
-             (setq string (match-string n))
-             (when (member m '("$" "$1"))
-               (save-excursion
-                 (delete-region (match-beginning n) (match-end n))
-                 (goto-char (match-beginning n))
-                 (insert (concat "\\(" (substring string 1 -1) "\\)")))))
-            ((or (eq processing-type 'dvipng)
-                 (eq processing-type 'imagemagick))
-             ;; Process to an image.
-             (setq txt (match-string n)
-                   beg (match-beginning n) end (match-end n)
-                   cnt (1+ cnt))
-             (let ((face (face-at-point))
-                   (fg (plist-get opt :foreground))
-                   (bg (plist-get opt :background))
-                   ;; Ensure full list is printed.
-                   print-length print-level)
-               (when forbuffer
-                 ;; Get the colors from the face at point.
+`org-format-latex-options', which see."
+  (when (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
+  (unless (eq processing-type 'verbatim)
+    (let* ((math-regexp "\\$\\|\\\\[([]\\|^[ \t]*\\\\begin{[A-Za-z0-9*]+}")
+          (cnt 0)
+          checkdir-flag)
+      (goto-char (or beg (point-min)))
+      ;; Optimize overlay creation: (info "(elisp) Managing Overlays").
+      (when (and overlays (memq processing-type '(dvipng imagemagick)))
+       (overlay-recenter (or end (point-max))))
+      (while (re-search-forward math-regexp end t)
+       (unless (and overlays
+                    (eq (get-char-property (point) 'org-overlay-type)
+                        'org-latex-overlay))
+         (let* ((context (org-element-context))
+                (type (org-element-type context)))
+           (when (memq type '(latex-environment latex-fragment))
+             (let ((block-type (eq type 'latex-environment))
+                   (value (org-element-property :value context))
+                   (beg (org-element-property :begin context))
+                   (end (save-excursion
+                          (goto-char (org-element-property :end context))
+                          (skip-chars-backward " \r\t\n")
+                          (point))))
+               (cond
+                ((eq processing-type 'mathjax)
+                 ;; Prepare for MathJax processing.
+                 (if (not (string-match "\\`\\$\\$?" value))
+                     (goto-char end)
+                   (delete-region beg end)
+                   (if (string= (match-string 0 value) "$$")
+                       (insert "\\[" (substring value 2 -2) "\\]")
+                     (insert "\\(" (substring value 1 -1) "\\)"))))
+                ((assq processing-type org-preview-latex-process-alist)
+                 ;; Process to an image.
+                 (cl-incf cnt)
                  (goto-char beg)
-                 (when (eq fg 'auto)
-                   (setq fg (face-attribute face :foreground nil 'default)))
-                 (when (eq bg 'auto)
-                   (setq bg (face-attribute face :background nil 'default)))
-                 (setq optnew (copy-sequence opt))
-                 (plist-put optnew :foreground fg)
-                 (plist-put optnew :background bg))
-               (setq hash (sha1 (prin1-to-string
-                                 (list org-format-latex-header
-                                       org-latex-default-packages-alist
-                                       org-latex-packages-alist
-                                       org-format-latex-options
-                                       forbuffer txt fg bg)))
-                     linkfile (format "%s_%s.png" prefix hash)
-                     movefile (format "%s_%s.png" absprefix hash)))
-             (setq link (concat block "[[file:" linkfile "]]" block))
-             (if msg (message msg cnt))
-             (goto-char beg)
-             (unless checkdir        ; Ensure the directory exists.
-               (setq checkdir t)
-               (or (file-directory-p todir) (make-directory todir t)))
-             (unless (file-exists-p movefile)
-               (org-create-formula-image
-                txt movefile optnew forbuffer processing-type))
-             (if overlays
-                 (progn
-                   (mapc (lambda (o)
-                           (if (eq (overlay-get o 'org-overlay-type)
-                                   'org-latex-overlay)
-                               (delete-overlay o)))
-                         (overlays-in beg end))
-                   (setq ov (make-overlay beg end))
-                   (overlay-put ov 'org-overlay-type 'org-latex-overlay)
-                   (if (featurep 'xemacs)
+                 (let* ((processing-info
+                         (cdr (assq processing-type 
org-preview-latex-process-alist)))
+                        (face (face-at-point))
+                        ;; Get the colors from the face at point.
+                        (fg
+                         (let ((color (plist-get org-format-latex-options
+                                                 :foreground)))
+                           (if (and forbuffer (eq color 'auto))
+                               (face-attribute face :foreground nil 'default)
+                             color)))
+                        (bg
+                         (let ((color (plist-get org-format-latex-options
+                                                 :background)))
+                           (if (and forbuffer (eq color 'auto))
+                               (face-attribute face :background nil 'default)
+                             color)))
+                        (hash (sha1 (prin1-to-string
+                                     (list org-format-latex-header
+                                           org-latex-default-packages-alist
+                                           org-latex-packages-alist
+                                           org-format-latex-options
+                                           forbuffer value fg bg))))
+                        (imagetype (or (plist-get processing-info 
:image-output-type) "png"))
+                        (absprefix (expand-file-name prefix dir))
+                        (linkfile (format "%s_%s.%s" prefix hash imagetype))
+                        (movefile (format "%s_%s.%s" absprefix hash imagetype))
+                        (sep (and block-type "\n\n"))
+                        (link (concat sep "[[file:" linkfile "]]" sep))
+                        (options
+                         (org-combine-plists
+                          org-format-latex-options
+                          `(:foreground ,fg :background ,bg))))
+                   (when msg (message msg cnt))
+                   (unless checkdir-flag ; Ensure the directory exists.
+                     (setq checkdir-flag t)
+                     (let ((todir (file-name-directory absprefix)))
+                       (unless (file-directory-p todir)
+                         (make-directory todir t))))
+                   (unless (file-exists-p movefile)
+                     (org-create-formula-image
+                      value movefile options forbuffer processing-type))
+                   (if overlays
                        (progn
-                         (overlay-put ov 'invisible t)
-                         (overlay-put
-                          ov 'end-glyph
-                          (make-glyph (vector 'png :file movefile))))
-                     (overlay-put
-                      ov 'display
-                      (list 'image :type 'png :file movefile :ascent 'center)))
-                   (push ov org-latex-fragment-image-overlays)
-                   (goto-char end))
-               (delete-region beg end)
-               (insert (org-add-props link
-                           (list 'org-latex-src
-                                 (replace-regexp-in-string
-                                  "\"" "" txt)
-                                 'org-latex-src-embed-type
-                                 (if block-type 'paragraph 'character))))))
-            ((eq processing-type 'mathml)
-             ;; Process to MathML
-             (unless (save-match-data (org-format-latex-mathml-available-p))
-               (user-error "LaTeX to MathML converter not configured"))
-             (setq txt (match-string n)
-                   beg (match-beginning n) end (match-end n)
-                   cnt (1+ cnt))
-             (if msg (message msg cnt))
-             (goto-char beg)
-             (delete-region beg end)
-             (insert (org-format-latex-as-mathml
-                      txt block-type prefix dir)))
-            (t
-             (error "Unknown conversion type %s for LaTeX fragments"
-                    processing-type)))))))))
+                         (dolist (o (overlays-in beg end))
+                           (when (eq (overlay-get o 'org-overlay-type)
+                                     'org-latex-overlay)
+                             (delete-overlay o)))
+                         (org--format-latex-make-overlay beg end movefile 
imagetype)
+                         (goto-char end))
+                     (delete-region beg end)
+                     (insert
+                      (org-add-props link
+                          (list 'org-latex-src
+                                (replace-regexp-in-string "\"" "" value)
+                                'org-latex-src-embed-type
+                                (if block-type 'paragraph 'character)))))))
+                ((eq processing-type 'mathml)
+                 ;; Process to MathML.
+                 (unless (org-format-latex-mathml-available-p)
+                   (user-error "LaTeX to MathML converter not configured"))
+                 (cl-incf cnt)
+                 (when msg (message msg cnt))
+                 (goto-char beg)
+                 (delete-region beg end)
+                 (insert (org-format-latex-as-mathml
+                          value block-type prefix dir)))
+                (t
+                 (error "Unknown conversion process %s for LaTeX fragments"
+                        processing-type)))))))))))
 
 (defun org-create-math-formula (latex-frag &optional mathml-file)
   "Convert LATEX-FRAG to MathML and store it in MATHML-FILE.
@@ -18553,20 +19295,25 @@ inspection."
                                   (buffer-substring-no-properties
                                    (region-beginning) (region-end)))))
                       (read-string "LaTeX Fragment: " frag nil frag))))
-  (unless latex-frag (error "Invalid LaTeX fragment"))
-  (let* ((tmp-in-file (file-relative-name
-                      (make-temp-name (expand-file-name "ltxmathml-in"))))
-        (ignore (write-region latex-frag nil tmp-in-file))
+  (unless latex-frag (user-error "Invalid LaTeX fragment"))
+  (let* ((tmp-in-file
+         (let ((file (file-relative-name
+                      (make-temp-name (expand-file-name "ltxmathml-in")))))
+           (write-region latex-frag nil file)
+           file))
         (tmp-out-file (file-relative-name
                        (make-temp-name (expand-file-name  "ltxmathml-out"))))
         (cmd (format-spec
               org-latex-to-mathml-convert-command
-              `((?j . ,(shell-quote-argument
-                        (expand-file-name org-latex-to-mathml-jar-file)))
+              `((?j . ,(and org-latex-to-mathml-jar-file
+                            (shell-quote-argument
+                             (expand-file-name
+                              org-latex-to-mathml-jar-file))))
                 (?I . ,(shell-quote-argument tmp-in-file))
+                (?i . ,latex-frag)
                 (?o . ,(shell-quote-argument tmp-out-file)))))
         mathml shell-command-output)
-    (when (org-called-interactively-p 'any)
+    (when (called-interactively-p 'any)
       (unless (org-format-latex-mathml-available-p)
        (user-error "LaTeX to MathML converter not configured")))
     (message "Running %s" cmd)
@@ -18576,11 +19323,10 @@ inspection."
            (with-current-buffer (find-file-noselect tmp-out-file t)
              (goto-char (point-min))
              (when (re-search-forward
-                    (concat
-                     (regexp-quote
-                      "<math xmlns=\"http://www.w3.org/1998/Math/MathML\";>")
-                     "\\(.\\|\n\\)*"
-                     (regexp-quote "</math>")) nil t)
+                    (format "<math[^>]*?%s[^>]*?>\\(.\\|\n\\)*</math>"
+                            (regexp-quote
+                             "xmlns=\"http://www.w3.org/1998/Math/MathML\"";))
+                    nil t)
                (prog1 (match-string 0) (kill-buffer))))))
     (cond
      (mathml
@@ -18588,7 +19334,7 @@ inspection."
            (concat "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" mathml))
       (when mathml-file
        (write-region mathml nil mathml-file))
-      (when (org-called-interactively-p 'any)
+      (when (called-interactively-p 'any)
        (message mathml)))
      ((message "LaTeX to MathML conversion failed")
       (message shell-command-output)))
@@ -18627,186 +19373,117 @@ inspection."
       ;; Failed conversion.  Return the LaTeX fragment verbatim
       latex-frag)))
 
-(defun org-create-formula-image (string tofile options buffer &optional type)
-  "Create an image from LaTeX source using dvipng or convert.
-This function calls either `org-create-formula-image-with-dvipng'
-or `org-create-formula-image-with-imagemagick' depending on the
-value of `org-latex-create-formula-image-program' or on the value
-of the optional TYPE variable.
-
-Note: ultimately these two function should be combined as they
-share a good deal of logic."
-  (org-check-external-command
-   "latex" "needed to convert LaTeX fragments to images")
-  (funcall
-   (case (or type org-latex-create-formula-image-program)
-     ('dvipng
-      (org-check-external-command
-       "dvipng" "needed to convert LaTeX fragments to images")
-      #'org-create-formula-image-with-dvipng)
-     ('imagemagick
-      (org-check-external-command
-       "convert" "you need to install imagemagick")
-      #'org-create-formula-image-with-imagemagick)
-     (t (error
-         "Invalid value of `org-latex-create-formula-image-program'")))
-   string tofile options buffer))
-
-(declare-function org-export-get-backend "ox" (name))
-(declare-function org-export--get-global-options "ox" (&optional backend))
-(declare-function org-export--get-inbuffer-options "ox" (&optional backend))
-(declare-function org-latex-guess-inputenc "ox-latex" (header))
-(declare-function org-latex-guess-babel-language "ox-latex" (header info))
-(defun org-create-formula--latex-header ()
-  "Return LaTeX header appropriate for previewing a LaTeX snippet."
-  (let ((info (org-combine-plists (org-export--get-global-options
-                                  (org-export-get-backend 'latex))
-                                 (org-export--get-inbuffer-options
-                                  (org-export-get-backend 'latex)))))
-    (org-latex-guess-babel-language
-     (org-latex-guess-inputenc
-      (org-splice-latex-header
-       org-format-latex-header
-       org-latex-default-packages-alist
-       org-latex-packages-alist t
-       (plist-get info :latex-header)))
-     info)))
-
-;; This function borrows from Ganesh Swami's latex2png.el
-(defun org-create-formula-image-with-dvipng (string tofile options buffer)
-  "This calls dvipng."
-  (require 'ox-latex)
-  (let* ((tmpdir (if (featurep 'xemacs)
-                    (temp-directory)
-                  temporary-file-directory))
+(defun org--get-display-dpi ()
+  "Get the DPI of the display.
+The function assumes that the display has the same pixel width in
+the horizontal and vertical directions."
+  (if (display-graphic-p)
+      (round (/ (display-pixel-height)
+               (/ (display-mm-height) 25.4)))
+    (error "Attempt to calculate the dpi of a non-graphic display")))
+
+(defun org-create-formula-image
+    (string tofile options buffer &optional processing-type)
+  "Create an image from LaTeX source using external processes.
+
+The LaTeX STRING is saved to a temporary LaTeX file, then
+converted to an image file by process PROCESSING-TYPE defined in
+`org-preview-latex-process-alist'.  A nil value defaults to
+`org-preview-latex-default-process'.
+
+The generated image file is eventually moved to TOFILE.
+
+The OPTIONS argument controls the size, foreground color and
+background color of the generated image.
+
+When BUFFER non-nil, this function is used for LaTeX previewing.
+Otherwise, it is used to deal with LaTeX snippets showed in
+a HTML file."
+  (let* ((processing-type (or processing-type
+                             org-preview-latex-default-process))
+        (processing-info
+         (cdr (assq processing-type org-preview-latex-process-alist)))
+        (programs (plist-get processing-info :programs))
+        (error-message (or (plist-get processing-info :message) ""))
+        (use-xcolor (plist-get processing-info :use-xcolor))
+        (image-input-type (plist-get processing-info :image-input-type))
+        (image-output-type (plist-get processing-info :image-output-type))
+        (post-clean (or (plist-get processing-info :post-clean)
+                        '(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log"
+                          ".svg" ".png" ".jpg" ".jpeg" ".out")))
+        (latex-header
+         (or (plist-get processing-info :latex-header)
+             (org-latex-make-preamble
+              (org-export-get-environment (org-export-get-backend 'latex))
+              org-format-latex-header
+              'snippet)))
+        (latex-compiler (plist-get processing-info :latex-compiler))
+        (image-converter (plist-get processing-info :image-converter))
+        (tmpdir temporary-file-directory)
         (texfilebase (make-temp-name
                       (expand-file-name "orgtex" tmpdir)))
         (texfile (concat texfilebase ".tex"))
-        (dvifile (concat texfilebase ".dvi"))
-        (pngfile (concat texfilebase ".png"))
-        (fnh (if (featurep 'xemacs)
-                  (font-height (face-font 'default))
-                (face-attribute 'default :height nil)))
-        (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
-        (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
+        (image-size-adjust (or (plist-get processing-info :image-size-adjust)
+                               '(1.0 . 1.0)))
+        (scale (* (if buffer (car image-size-adjust) (cdr image-size-adjust))
+                  (or (plist-get options (if buffer :scale :html-scale)) 1.0)))
+        (dpi (* scale (if buffer (org--get-display-dpi) 140.0)))
         (fg (or (plist-get options (if buffer :foreground :html-foreground))
                 "Black"))
         (bg (or (plist-get options (if buffer :background :html-background))
-                "Transparent")))
-    (if (eq fg 'default) (setq fg (org-dvipng-color :foreground))
-      (unless (string= fg "Transparent") (setq fg (org-dvipng-color-format 
fg))))
-    (if (eq bg 'default) (setq bg (org-dvipng-color :background))
-      (unless (string= bg "Transparent") (setq bg (org-dvipng-color-format 
bg))))
-    (let ((latex-header (org-create-formula--latex-header)))
+                "Transparent"))
+        (log-buf (get-buffer-create "*Org Preview LaTeX Output*"))
+        (resize-mini-windows nil)) ;Fix Emacs flicker when creating image.
+    (dolist (program programs)
+      (org-check-external-command program error-message))
+    (if use-xcolor
+       (progn (if (eq fg 'default)
+                  (setq fg (org-latex-color :foreground))
+                (setq fg (org-latex-color-format fg)))
+              (if (eq bg 'default)
+                  (setq bg (org-latex-color :background))
+                (setq bg (org-latex-color-format
+                          (if (string= bg "Transparent") "white" bg))))
+              (with-temp-file texfile
+                (insert latex-header)
+                (insert "\n\\begin{document}\n"
+                        "\\definecolor{fg}{rgb}{" fg "}\n"
+                        "\\definecolor{bg}{rgb}{" bg "}\n"
+                        "\n\\pagecolor{bg}\n"
+                        "\n{\\color{fg}\n"
+                        string
+                        "\n}\n"
+                        "\n\\end{document}\n")))
+      (if (eq fg 'default)
+         (setq fg (org-dvipng-color :foreground))
+       (unless (string= fg "Transparent")
+         (setq fg (org-dvipng-color-format fg))))
+      (if (eq bg 'default)
+         (setq bg (org-dvipng-color :background))
+       (unless (string= bg "Transparent")
+         (setq bg (org-dvipng-color-format bg))))
       (with-temp-file texfile
        (insert latex-header)
        (insert "\n\\begin{document}\n" string "\n\\end{document}\n")))
-    (let ((dir default-directory))
-      (condition-case nil
-         (progn
-           (cd tmpdir)
-           (call-process "latex" nil nil nil texfile))
-       (error nil))
-      (cd dir))
-    (if (not (file-exists-p dvifile))
-       (progn (message "Failed to create dvi file from %s" texfile) nil)
-      (condition-case nil
-         (if (featurep 'xemacs)
-             (call-process "dvipng" nil nil nil
-                           "-fg" fg "-bg" bg
-                           "-T" "tight"
-                           "-o" pngfile
-                           dvifile)
-           (call-process "dvipng" nil nil nil
-                         "-fg" fg "-bg" bg
-                         "-D" dpi
-                         ;;"-x" scale "-y" scale
-                         "-T" "tight"
-                         "-o" pngfile
-                         dvifile))
-       (error nil))
-      (if (not (file-exists-p pngfile))
-         (if org-format-latex-signal-error
-             (error "Failed to create png file from %s" texfile)
-           (message "Failed to create png file from %s" texfile)
-           nil)
-       ;; Use the requested file name and clean up
-       (copy-file pngfile tofile 'replace)
-       (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png" ".out") do
-             (if (file-exists-p (concat texfilebase e))
-                 (delete-file (concat texfilebase e))))
-       pngfile))))
-
-(declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
-(defun org-create-formula-image-with-imagemagick (string tofile options buffer)
-  "This calls convert, which is included into imagemagick."
-  (require 'ox-latex)
-  (let* ((tmpdir (if (featurep 'xemacs)
-                    (temp-directory)
-                  temporary-file-directory))
-        (texfilebase (make-temp-name
-                      (expand-file-name "orgtex" tmpdir)))
-        (texfile (concat texfilebase ".tex"))
-        (pdffile (concat texfilebase ".pdf"))
-        (pngfile (concat texfilebase ".png"))
-        (fnh (if (featurep 'xemacs)
-                  (font-height (face-font 'default))
-                (face-attribute 'default :height nil)))
-        (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
-        (dpi (number-to-string (* scale (floor (if buffer fnh 120.)))))
-        (fg (or (plist-get options (if buffer :foreground :html-foreground))
-                "black"))
-        (bg (or (plist-get options (if buffer :background :html-background))
-                "white")))
-    (if (eq fg 'default) (setq fg (org-latex-color :foreground))
-      (setq fg (org-latex-color-format fg)))
-    (if (eq bg 'default) (setq bg (org-latex-color :background))
-      (setq bg (org-latex-color-format
-               (if (string= bg "Transparent") "white" bg))))
-    (let ((latex-header (org-create-formula--latex-header)))
-      (with-temp-file texfile
-       (insert latex-header)
-       (insert "\n\\begin{document}\n"
-               "\\definecolor{fg}{rgb}{" fg "}\n"
-               "\\definecolor{bg}{rgb}{" bg "}\n"
-               "\n\\pagecolor{bg}\n"
-               "\n{\\color{fg}\n"
-               string
-               "\n}\n"
-               "\n\\end{document}\n")))
-    (org-latex-compile texfile t)
-    (if (not (file-exists-p pdffile))
-       (progn (message "Failed to create pdf file from %s" texfile) nil)
-      (condition-case nil
-         (if (featurep 'xemacs)
-             (call-process "convert" nil nil nil
-                           "-density" "96"
-                           "-trim"
-                           "-antialias"
-                           pdffile
-                           "-quality" "100"
-                           ;; "-sharpen" "0x1.0"
-                           pngfile)
-           (call-process "convert" nil nil nil
-                         "-density" dpi
-                         "-trim"
-                         "-antialias"
-                         pdffile
-                         "-quality" "100"
-                         ;; "-sharpen" "0x1.0"
-                         pngfile))
-       (error nil))
-      (if (not (file-exists-p pngfile))
-         (if org-format-latex-signal-error
-             (error "Failed to create png file from %s" texfile)
-           (message "Failed to create png file from %s" texfile)
-           nil)
-       ;; Use the requested file name and clean up
-       (copy-file pngfile tofile 'replace)
-       (loop for e in '(".pdf" ".tex" ".aux" ".log" ".png") do
-             (if (file-exists-p (concat texfilebase e))
-                 (delete-file (concat texfilebase e))))
-       pngfile))))
+
+    (let* ((err-msg (format "Please adjust '%s' part of \
+`org-preview-latex-process-alist'."
+                           processing-type))
+          (image-input-file
+           (org-compile-file
+            texfile latex-compiler image-input-type err-msg log-buf))
+          (image-output-file
+           (org-compile-file
+            image-input-file image-converter image-output-type err-msg log-buf
+            `((?F . ,(shell-quote-argument fg))
+              (?B . ,(shell-quote-argument bg))
+              (?D . ,(shell-quote-argument (format "%s" dpi)))
+              (?S . ,(shell-quote-argument (format "%s" (/ dpi 140.0))))))))
+      (copy-file image-output-file tofile 'replace)
+      (dolist (e post-clean)
+       (when (file-exists-p (concat texfilebase e))
+         (delete-file (concat texfilebase e))))
+      image-output-file)))
 
 (defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra)
   "Fill a LaTeX header template TPL.
@@ -18830,22 +19507,22 @@ SNIPPETS-P indicates if this is run to create snippet 
images for HTML."
        (setq rpl (if (or (match-end 1) (not def-pkg))
                      "" (org-latex-packages-to-string def-pkg snippets-p t))
              tpl (replace-match rpl t t tpl))
-      (if def-pkg (setq end (org-latex-packages-to-string def-pkg 
snippets-p))))
+      (when def-pkg (setq end (org-latex-packages-to-string def-pkg 
snippets-p))))
 
     (if (string-match "\\[\\(NO-\\)?PACKAGES\\][ \t]*\n?" tpl)
        (setq rpl (if (or (match-end 1) (not pkg))
                      "" (org-latex-packages-to-string pkg snippets-p t))
              tpl (replace-match rpl t t tpl))
-      (if pkg (setq end
-                   (concat end "\n"
-                           (org-latex-packages-to-string pkg snippets-p)))))
+      (when pkg (setq end
+                     (concat end "\n"
+                             (org-latex-packages-to-string pkg snippets-p)))))
 
     (if (string-match "\\[\\(NO-\\)?EXTRA\\][ \t]*\n?" tpl)
        (setq rpl (if (or (match-end 1) (not extra))
                      "" (concat extra "\n"))
              tpl (replace-match rpl t t tpl))
-      (if (and extra (string-match "\\S-" extra))
-         (setq end (concat end "\n" extra))))
+      (when (and extra (string-match "\\S-" extra))
+       (setq end (concat end "\n" extra))))
 
     (if (string-match "\\S-" end)
        (concat tpl "\n" end)
@@ -18869,35 +19546,21 @@ SNIPPETS-P indicates if this is run to create snippet 
images for HTML."
 
 (defun org-dvipng-color (attr)
   "Return a RGB color specification for dvipng."
-  (apply 'format "rgb %s %s %s"
-        (mapcar 'org-normalize-color
-                (if (featurep 'xemacs)
-                    (color-rgb-components
-                     (face-property 'default
-                                    (cond ((eq attr :foreground) 'foreground)
-                                          ((eq attr :background) 
'background))))
-                  (color-values (face-attribute 'default attr nil))))))
+  (org-dvipng-color-format (face-attribute 'default attr nil)))
 
 (defun org-dvipng-color-format (color-name)
   "Convert COLOR-NAME to a RGB color value for dvipng."
-  (apply 'format "rgb %s %s %s"
+  (apply #'format "rgb %s %s %s"
         (mapcar 'org-normalize-color
-                  (color-values color-name))))
+                (color-values color-name))))
 
 (defun org-latex-color (attr)
   "Return a RGB color for the LaTeX color package."
-  (apply 'format "%s,%s,%s"
-        (mapcar 'org-normalize-color
-                (if (featurep 'xemacs)
-                    (color-rgb-components
-                     (face-property 'default
-                                    (cond ((eq attr :foreground) 'foreground)
-                                          ((eq attr :background) 
'background))))
-                  (color-values (face-attribute 'default attr nil))))))
+  (org-latex-color-format (face-attribute 'default attr nil)))
 
 (defun org-latex-color-format (color-name)
   "Convert COLOR-NAME to a RGB color value."
-  (apply 'format "%s,%s,%s"
+  (apply #'format "%s,%s,%s"
         (mapcar 'org-normalize-color
                 (color-values color-name))))
 
@@ -18909,8 +19572,7 @@ SNIPPETS-P indicates if this is run to create snippet 
images for HTML."
 
 ;; Image display
 
-(defvar org-inline-image-overlays nil)
-(make-variable-buffer-local 'org-inline-image-overlays)
+(defvar-local org-inline-image-overlays nil)
 
 (defun org-toggle-inline-images (&optional include-linked)
   "Toggle the display of inline images.
@@ -18919,13 +19581,14 @@ INCLUDE-LINKED is passed to 
`org-display-inline-images'."
   (if org-inline-image-overlays
       (progn
        (org-remove-inline-images)
-       (message "Inline image display turned off"))
+       (when (called-interactively-p 'interactive)
+         (message "Inline image display turned off")))
     (org-display-inline-images include-linked)
-    (if (and (org-called-interactively-p)
-            org-inline-image-overlays)
-       (message "%d images displayed inline"
-                (length org-inline-image-overlays))
-      (message "No images to display inline"))))
+    (when (called-interactively-p 'interactive)
+      (message (if org-inline-image-overlays
+                  (format "%d images displayed inline"
+                          (length org-inline-image-overlays))
+                "No images to display inline")))))
 
 (defun org-redisplay-inline-images ()
   "Refresh the display of inline images."
@@ -18937,68 +19600,116 @@ INCLUDE-LINKED is passed to 
`org-display-inline-images'."
 
 (defun org-display-inline-images (&optional include-linked refresh beg end)
   "Display inline images.
-Normally only links without a description part are inlined, because this
-is how it will work for export.  When INCLUDE-LINKED is set, also links
-with a description part will be inlined.  This can be nice for a quick
-look at those images, but it does not reflect what exported files will look
-like.
-When REFRESH is set, refresh existing images between BEG and END.
-This will create new image displays only if necessary.
-BEG and END default to the buffer boundaries."
+
+An inline image is a link which follows either of these
+conventions:
+
+  1. Its path is a file with an extension matching return value
+     from `image-file-name-regexp' and it has no contents.
+
+  2. Its description consists in a single link of the previous
+     type.
+
+When optional argument INCLUDE-LINKED is non-nil, also links with
+a text description part will be inlined.  This can be nice for
+a quick look at those images, but it does not reflect what
+exported files will look like.
+
+When optional argument REFRESH is non-nil, refresh existing
+images between BEG and END.  This will create new image displays
+only if necessary.  BEG and END default to the buffer
+boundaries."
   (interactive "P")
   (when (display-graphic-p)
     (unless refresh
       (org-remove-inline-images)
-      (if (fboundp 'clear-image-cache) (clear-image-cache)))
-    (save-excursion
-      (save-restriction
-       (widen)
-       (setq beg (or beg (point-min)) end (or end (point-max)))
-       (goto-char beg)
-       (let ((re (concat "\\[\\[\\(\\(file:\\)\\|\\([./~]\\)\\)\\([^]\n]+?"
-                         (substring (org-image-file-name-regexp) 0 -2)
-                         "\\)\\]" (if include-linked "" "\\]")))
-             (case-fold-search t)
-             old file ov img type attrwidth width)
-         (while (re-search-forward re end t)
-           (setq old (get-char-property-and-overlay (match-beginning 1)
-                                                    'org-image-overlay)
-                 file (expand-file-name
-                       (concat (or (match-string 3) "") (match-string 4))))
-           (when (image-type-available-p 'imagemagick)
-             (setq attrwidth (if (or (listp org-image-actual-width)
-                                     (null org-image-actual-width))
-                                 (save-excursion
-                                   (save-match-data
-                                     (when (re-search-backward
-                                            "#\\+attr.*:width[ \t]+\\([^ ]+\\)"
-                                            (save-excursion
-                                              (re-search-backward "^[ 
\t]*$\\|\\`" nil t)) t)
-                                       (string-to-number (match-string 1))))))
-                   width (cond ((eq org-image-actual-width t) nil)
-                               ((null org-image-actual-width) attrwidth)
-                               ((numberp org-image-actual-width)
-                                org-image-actual-width)
-                               ((listp org-image-actual-width)
-                                (or attrwidth (car org-image-actual-width))))
-                   type (if width 'imagemagick)))
-           (when (file-exists-p file)
-             (if (and (car-safe old) refresh)
-                 (image-refresh (overlay-get (cdr old) 'display))
-               (setq img (save-match-data (create-image file type nil :width 
width)))
-               (when img
-                 (setq ov (make-overlay (match-beginning 0) (match-end 0)))
-                 (overlay-put ov 'display img)
-                 (overlay-put ov 'face 'default)
-                 (overlay-put ov 'org-image-overlay t)
-                 (overlay-put ov 'modification-hooks
-                              (list 'org-display-inline-remove-overlay))
-                 (push ov org-inline-image-overlays))))))))))
-
-(define-obsolete-function-alias
-  'org-display-inline-modification-hook 'org-display-inline-remove-overlay 
"24.3")
-
-(defun org-display-inline-remove-overlay (ov after beg end &optional len)
+      (when (fboundp 'clear-image-cache) (clear-image-cache)))
+    (org-with-wide-buffer
+     (goto-char (or beg (point-min)))
+     (let ((case-fold-search t)
+          (file-extension-re (image-file-name-regexp)))
+       (while (re-search-forward "[][]\\[\\(?:file\\|[./~]\\)" end t)
+        (let ((link (save-match-data (org-element-context))))
+          ;; Check if we're at an inline image.
+          (when (and (equal (org-element-property :type link) "file")
+                     (or include-linked
+                         (not (org-element-property :contents-begin link)))
+                     (let ((parent (org-element-property :parent link)))
+                       (or (not (eq (org-element-type parent) 'link))
+                           (not (cdr (org-element-contents parent)))))
+                     (string-match-p file-extension-re
+                                     (org-element-property :path link)))
+            (let ((file (expand-file-name
+                         (org-link-unescape
+                          (org-element-property :path link)))))
+              (when (file-exists-p file)
+                (let ((width
+                       ;; Apply `org-image-actual-width' specifications.
+                       (cond
+                        ((not (image-type-available-p 'imagemagick)) nil)
+                        ((eq org-image-actual-width t) nil)
+                        ((listp org-image-actual-width)
+                         (or
+                          ;; First try to find a width among
+                          ;; attributes associated to the paragraph
+                          ;; containing link.
+                          (let ((paragraph
+                                 (let ((e link))
+                                   (while (and (setq e (org-element-property
+                                                        :parent e))
+                                               (not (eq (org-element-type e)
+                                                        'paragraph))))
+                                   e)))
+                            (when paragraph
+                              (save-excursion
+                                (goto-char (org-element-property :begin 
paragraph))
+                                (when
+                                    (re-search-forward
+                                     "^[ \t]*#\\+attr_.*?: +.*?:width 
+\\(\\S-+\\)"
+                                     (org-element-property
+                                      :post-affiliated paragraph)
+                                     t)
+                                  (string-to-number (match-string 1))))))
+                          ;; Otherwise, fall-back to provided number.
+                          (car org-image-actual-width)))
+                        ((numberp org-image-actual-width)
+                         org-image-actual-width)))
+                      (old (get-char-property-and-overlay
+                            (org-element-property :begin link)
+                            'org-image-overlay)))
+                  (if (and (car-safe old) refresh)
+                      (image-refresh (overlay-get (cdr old) 'display))
+                    (let ((image (create-image file
+                                               (and width 'imagemagick)
+                                               nil
+                                               :width width)))
+                      (when image
+                        (let* ((link
+                                ;; If inline image is the description
+                                ;; of another link, be sure to
+                                ;; consider the latter as the one to
+                                ;; apply the overlay on.
+                                (let ((parent
+                                       (org-element-property :parent link)))
+                                  (if (eq (org-element-type parent) 'link)
+                                      parent
+                                    link)))
+                               (ov (make-overlay
+                                    (org-element-property :begin link)
+                                    (progn
+                                      (goto-char
+                                       (org-element-property :end link))
+                                      (skip-chars-backward " \t")
+                                      (point)))))
+                          (overlay-put ov 'display image)
+                          (overlay-put ov 'face 'default)
+                          (overlay-put ov 'org-image-overlay t)
+                          (overlay-put
+                           ov 'modification-hooks
+                           (list 'org-display-inline-remove-overlay))
+                          (push ov org-inline-image-overlays)))))))))))))))
+
+(defun org-display-inline-remove-overlay (ov after _beg _end &optional _len)
   "Remove inline-display overlay if a corresponding region is modified."
   (let ((inhibit-modification-hooks t))
     (when (and ov after)
@@ -19008,7 +19719,7 @@ BEG and END default to the buffer boundaries."
 (defun org-remove-inline-images ()
   "Remove inline display of images."
   (interactive)
-  (mapc 'delete-overlay org-inline-image-overlays)
+  (mapc #'delete-overlay org-inline-image-overlays)
   (setq org-inline-image-overlays nil))
 
 ;;;; Key bindings
@@ -19016,44 +19727,46 @@ BEG and END default to the buffer boundaries."
 ;; Outline functions from `outline-mode-prefix-map'
 ;; that can be remapped in Org:
 (define-key org-mode-map [remap outline-mark-subtree] 'org-mark-subtree)
-(define-key org-mode-map [remap show-subtree] 'org-show-subtree)
+(define-key org-mode-map [remap outline-show-subtree] 'org-show-subtree)
 (define-key org-mode-map [remap outline-forward-same-level]
   'org-forward-heading-same-level)
 (define-key org-mode-map [remap outline-backward-same-level]
   'org-backward-heading-same-level)
-(define-key org-mode-map [remap show-branches]
+(define-key org-mode-map [remap outline-show-branches]
   'org-kill-note-or-show-branches)
 (define-key org-mode-map [remap outline-promote] 'org-promote-subtree)
 (define-key org-mode-map [remap outline-demote] 'org-demote-subtree)
 (define-key org-mode-map [remap outline-insert-heading] 'org-ctrl-c-ret)
+(define-key org-mode-map [remap outline-next-visible-heading]
+  'org-next-visible-heading)
+(define-key org-mode-map [remap outline-previous-visible-heading]
+  'org-previous-visible-heading)
+(define-key org-mode-map [remap show-children] 'org-show-children)
 
 ;; Outline functions from `outline-mode-prefix-map' that can not
 ;; be remapped in Org:
-;;
+
 ;; - the column "key binding" shows whether the Outline function is still
 ;;   available in Org mode on the same key that it has been bound to in
 ;;   Outline mode:
 ;;   - "overridden": key used for a different functionality in Org mode
 ;;   - else: key still bound to the same Outline function in Org mode
-;;
-;; | Outline function                   | key binding | Org replacement       |
-;; |------------------------------------+-------------+-----------------------|
-;; | `outline-next-visible-heading'     | `C-c C-n'   | still same function   |
-;; | `outline-previous-visible-heading' | `C-c C-p'   | still same function   |
-;; | `outline-up-heading'               | `C-c C-u'   | still same function   |
-;; | `outline-move-subtree-up'          | overridden  | better: org-shiftup   |
-;; | `outline-move-subtree-down'        | overridden  | better: org-shiftdown |
-;; | `show-entry'                       | overridden  | no replacement        |
-;; | `show-children'                    | `C-c C-i'   | visibility cycling    |
-;; | `show-branches'                    | `C-c C-k'   | still same function   |
-;; | `show-subtree'                     | overridden  | visibility cycling    |
-;; | `show-all'                         | overridden  | no replacement        |
-;; | `hide-subtree'                     | overridden  | visibility cycling    |
-;; | `hide-body'                        | overridden  | no replacement        |
-;; | `hide-entry'                       | overridden  | visibility cycling    |
-;; | `hide-leaves'                      | overridden  | no replacement        |
-;; | `hide-sublevels'                   | overridden  | no replacement        |
-;; | `hide-other'                       | overridden  | no replacement        |
+
+;; | Outline function                   | key binding | Org replacement        
  |
+;; 
|------------------------------------+-------------+--------------------------|
+;; | `outline-up-heading'               | `C-c C-u'   | still same function    
  |
+;; | `outline-move-subtree-up'          | overridden  | better: org-shiftup    
  |
+;; | `outline-move-subtree-down'        | overridden  | better: org-shiftdown  
  |
+;; | `show-entry'                       | overridden  | no replacement         
  |
+;; | `show-branches'                    | `C-c C-k'   | still same function    
  |
+;; | `show-subtree'                     | overridden  | visibility cycling     
  |
+;; | `show-all'                         | overridden  | no replacement         
  |
+;; | `hide-subtree'                     | overridden  | visibility cycling     
  |
+;; | `hide-body'                        | overridden  | no replacement         
  |
+;; | `hide-entry'                       | overridden  | visibility cycling     
  |
+;; | `hide-leaves'                      | overridden  | no replacement         
  |
+;; | `hide-sublevels'                   | overridden  | no replacement         
  |
+;; | `hide-other'                       | overridden  | no replacement         
  |
 
 ;; Make `C-c C-x' a prefix key
 (org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap))
@@ -19064,8 +19777,7 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived)
 (org-defkey org-mode-map "\M-\t" #'pcomplete)
 ;; The following line is necessary under Suse GNU/Linux
-(unless (featurep 'xemacs)
-  (org-defkey org-mode-map [S-iso-lefttab]  'org-shifttab))
+(org-defkey org-mode-map [S-iso-lefttab]  'org-shifttab)
 (org-defkey org-mode-map [(shift tab)]    'org-shifttab)
 (define-key org-mode-map [backtab] 'org-shifttab)
 
@@ -19079,6 +19791,8 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map [(meta up)]    'org-metaup)
 (org-defkey org-mode-map [(meta down)]  'org-metadown)
 
+(org-defkey org-mode-map [(control meta shift right)] 
'org-increase-number-at-point)
+(org-defkey org-mode-map [(control meta shift left)] 
'org-decrease-number-at-point)
 (org-defkey org-mode-map [(meta shift left)]   'org-shiftmetaleft)
 (org-defkey org-mode-map [(meta shift right)]  'org-shiftmetaright)
 (org-defkey org-mode-map [(meta shift up)]     'org-shiftmetaup)
@@ -19096,17 +19810,14 @@ BEG and END default to the buffer boundaries."
 
 ;; Babel keys
 (define-key org-mode-map org-babel-key-prefix org-babel-map)
-(mapc (lambda (pair)
-        (define-key org-babel-map (car pair) (cdr pair)))
-      org-babel-key-bindings)
+(dolist (pair org-babel-key-bindings)
+  (define-key org-babel-map (car pair) (cdr pair)))
 
 ;;; Extra keys for tty access.
 ;;  We only set them when really needed because otherwise the
 ;;  menus don't show the simple keys
 
-(when (or org-use-extra-keys
-         (featurep 'xemacs)   ;; because XEmacs supports multi-device stuff
-         (not window-system))
+(when (or org-use-extra-keys (not window-system))
   (org-defkey org-mode-map "\C-c\C-xc"    'org-table-copy-down)
   (org-defkey org-mode-map "\C-c\C-xM"    'org-insert-todo-heading)
   (org-defkey org-mode-map "\C-c\C-xm"    'org-meta-return)
@@ -19138,7 +19849,7 @@ BEG and END default to the buffer boundaries."
 
 ;; All the other keys
 
-(org-defkey org-mode-map "\C-c\C-a" 'show-all)  ; in case allout messed up.
+(org-defkey org-mode-map "\C-c\C-a" 'outline-show-all)  ; in case allout 
messed up.
 (org-defkey org-mode-map "\C-c\C-r" 'org-reveal)
 (if (boundp 'narrow-map)
     (org-defkey narrow-map "s" 'org-narrow-to-subtree)
@@ -19185,6 +19896,7 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
 (org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link)
 (org-defkey org-mode-map "\C-c\C-l" 'org-insert-link)
+(org-defkey org-mode-map "\C-c\M-l" 'org-insert-last-stored-link)
 (org-defkey org-mode-map "\C-c\C-\M-l" 'org-insert-all-links)
 (org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point)
 (org-defkey org-mode-map "\C-c%"    'org-mark-ring-push)
@@ -19209,8 +19921,10 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c\C-k" 'org-kill-note-or-show-branches)
 (org-defkey org-mode-map "\C-c#"    'org-update-statistics-cookies)
 (org-defkey org-mode-map [remap open-line] 'org-open-line)
+(org-defkey org-mode-map [remap comment-dwim] 'org-comment-dwim)
 (org-defkey org-mode-map [remap forward-paragraph] 'org-forward-paragraph)
 (org-defkey org-mode-map [remap backward-paragraph] 'org-backward-paragraph)
+(org-defkey org-mode-map "\M-^"     'org-delete-indentation)
 (org-defkey org-mode-map "\C-m"     'org-return)
 (org-defkey org-mode-map "\C-j"     'org-return-indent)
 (org-defkey org-mode-map "\C-c?"    'org-table-field-info)
@@ -19219,6 +19933,8 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c="    'org-table-eval-formula)
 (org-defkey org-mode-map "\C-c'"    'org-edit-special)
 (org-defkey org-mode-map "\C-c`"    'org-table-edit-field)
+(org-defkey org-mode-map "\C-c\"a"  'orgtbl-ascii-plot)
+(org-defkey org-mode-map "\C-c\"g"  'org-plot/gnuplot)
 (org-defkey org-mode-map "\C-c|"    'org-table-create-or-convert-from-region)
 (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
 (org-defkey org-mode-map "\C-c~"    'org-table-create-with-table.el)
@@ -19226,7 +19942,7 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c}"    'org-table-toggle-coordinate-overlays)
 (org-defkey org-mode-map "\C-c{"    'org-table-toggle-formula-debugger)
 (org-defkey org-mode-map "\C-c\C-e" 'org-export-dispatch)
-(org-defkey org-mode-map "\C-c:"    'org-toggle-fixed-width-section)
+(org-defkey org-mode-map "\C-c:"    'org-toggle-fixed-width)
 (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize)
 (org-defkey org-mode-map "\C-c\C-xf"    'org-footnote-action)
 (org-defkey org-mode-map "\C-c\C-x\C-mg"    'org-mobile-pull)
@@ -19250,7 +19966,7 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
 (org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
 (org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
-(org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
+(org-defkey org-mode-map "\C-c\C-x\C-l" 'org-toggle-latex-fragment)
 (org-defkey org-mode-map "\C-c\C-x\C-v" 'org-toggle-inline-images)
 (org-defkey org-mode-map "\C-c\C-x\C-\M-v" 'org-redisplay-inline-images)
 (org-defkey org-mode-map "\C-c\C-x\\"   'org-toggle-pretty-entities)
@@ -19260,9 +19976,8 @@ BEG and END default to the buffer boundaries."
 (org-defkey org-mode-map "\C-c\C-xe"    'org-set-effort)
 (org-defkey org-mode-map "\C-c\C-xE"    'org-inc-effort)
 (org-defkey org-mode-map "\C-c\C-xo"    'org-toggle-ordered-property)
-(org-defkey org-mode-map "\C-c\C-xi"    'org-insert-columns-dblock)
+(org-defkey org-mode-map "\C-c\C-xi"    'org-columns-insert-dblock)
 (org-defkey org-mode-map [(control ?c) (control ?x) ?\;] 'org-timer-set-timer)
-(org-defkey org-mode-map [(control ?c) (control ?x) ?\:] 
'org-timer-cancel-timer)
 
 (org-defkey org-mode-map "\C-c\C-x."    'org-timer)
 (org-defkey org-mode-map "\C-c\C-x-"    'org-timer-item)
@@ -19280,15 +19995,11 @@ BEG and END default to the buffer boundaries."
 (define-key org-mode-map "\C-c\C-x[" 'org-reftex-citation)
 
 
-(when (featurep 'xemacs)
-  (org-defkey org-mode-map 'button3   'popup-mode-menu))
-
-
 (defconst org-speed-commands-default
   '(
     ("Outline Navigation")
-    ("n" . (org-speed-move-safe 'outline-next-visible-heading))
-    ("p" . (org-speed-move-safe 'outline-previous-visible-heading))
+    ("n" . (org-speed-move-safe 'org-next-visible-heading))
+    ("p" . (org-speed-move-safe 'org-previous-visible-heading))
     ("f" . (org-speed-move-safe 'org-forward-heading-same-level))
     ("b" . (org-speed-move-safe 'org-backward-heading-same-level))
     ("F" . org-next-block)
@@ -19303,8 +20014,8 @@ BEG and END default to the buffer boundaries."
     ("s" . org-narrow-to-subtree)
     ("=" . org-columns)
     ("Outline Structure Editing")
-    ("U" . org-shiftmetaup)
-    ("D" . org-shiftmetadown)
+    ("U" . org-metaup)
+    ("D" . org-metadown)
     ("r" . org-metaright)
     ("l" . org-metaleft)
     ("R" . org-shiftmetaright)
@@ -19364,10 +20075,10 @@ BEG and END default to the buffer boundaries."
       (user-error "Speed commands are not activated, customize 
`org-use-speed-commands'")
     (with-output-to-temp-buffer "*Help*"
       (princ "User-defined Speed commands\n===========================\n")
-      (mapc 'org-print-speed-command org-speed-commands-user)
+      (mapc #'org-print-speed-command org-speed-commands-user)
       (princ "\n")
       (princ "Built-in Speed commands\n=======================\n")
-      (mapc 'org-print-speed-command org-speed-commands-default))
+      (mapc #'org-print-speed-command org-speed-commands-default))
     (with-current-buffer "*Help*"
       (setq truncate-lines t))))
 
@@ -19386,9 +20097,6 @@ If not, return to the original position and throw an 
error."
 (defvar org-table-auto-blank-field) ; defined in org-table.el
 (defvar org-speed-command nil)
 
-(define-obsolete-function-alias
-  'org-speed-command-default-hook 'org-speed-command-activate "24.3")
-
 (defun org-speed-command-activate (keys)
   "Hook for activating single-letter speed commands.
 `org-speed-commands-default' specifies a minimal command set.
@@ -19399,9 +20107,6 @@ Use `org-speed-commands-user' for further 
customization."
     (cdr (assoc keys (append org-speed-commands-user
                             org-speed-commands-default)))))
 
-(define-obsolete-function-alias
-  'org-babel-speed-command-hook 'org-babel-speed-command-activate "24.3")
-
 (defun org-babel-speed-command-activate (keys)
   "Hook for activating single-letter code block commands."
   (when (and (bolp) (looking-at org-babel-src-block-regexp))
@@ -19434,9 +20139,11 @@ overwritten, and the table is not marked as requiring 
realignment."
   (org-check-before-invisible-edit 'insert)
   (cond
    ((and org-use-speed-commands
-        (setq org-speed-command
-              (run-hook-with-args-until-success
-               'org-speed-command-hook (this-command-keys))))
+        (let ((kv (this-command-keys-vector)))
+          (setq org-speed-command
+                (run-hook-with-args-until-success
+                 'org-speed-command-hook
+                 (make-string 1 (aref kv (1- (length kv))))))))
     (cond
      ((commandp org-speed-command)
       (setq this-command org-speed-command)
@@ -19448,94 +20155,98 @@ overwritten, and the table is not marked as requiring 
realignment."
      (t (let (org-use-speed-commands)
          (call-interactively 'org-self-insert-command)))))
    ((and
-     (org-table-p)
+     (org-at-table-p)
      (progn
-       ;; check if we blank the field, and if that triggers align
+       ;; Check if we blank the field, and if that triggers align.
        (and (featurep 'org-table) org-table-auto-blank-field
-           (member last-command
-                   '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c 
yas/expand))
-           (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]*  |"))
-               ;; got extra space, this field does not determine column width
+           (memq last-command
+                 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
+           (if (or (eq (char-after) ?\s) (looking-at "[^|\n]*  |"))
+               ;; Got extra space, this field does not determine
+               ;; column width.
                (let (org-table-may-need-update) (org-table-blank-field))
-             ;; no extra space, this field may determine column width
+             ;; No extra space, this field may determine column
+             ;; width.
              (org-table-blank-field)))
        t)
      (eq N 1)
-     (looking-at "[^|\n]*  |"))
-    (let (org-table-may-need-update)
-      (goto-char (1- (match-end 0)))
-      (backward-delete-char 1)
-      (goto-char (match-beginning 0))
-      (self-insert-command N)))
+     (looking-at "[^|\n]* \\( \\)|"))
+    ;; There is room for insertion without re-aligning the table.
+    (delete-region (match-beginning 1) (match-end 1))
+    (self-insert-command N))
    (t
     (setq org-table-may-need-update t)
     (self-insert-command N)
     (org-fix-tags-on-the-fly)
-    (if org-self-insert-cluster-for-undo
-       (if (not (eq last-command 'org-self-insert-command))
+    (when org-self-insert-cluster-for-undo
+      (if (not (eq last-command 'org-self-insert-command))
+         (setq org-self-insert-command-undo-counter 1)
+       (if (>= org-self-insert-command-undo-counter 20)
            (setq org-self-insert-command-undo-counter 1)
-         (if (>= org-self-insert-command-undo-counter 20)
-             (setq org-self-insert-command-undo-counter 1)
-           (and (> org-self-insert-command-undo-counter 0)
-                buffer-undo-list (listp buffer-undo-list)
-                (not (cadr buffer-undo-list)) ; remove nil entry
-                (setcdr buffer-undo-list (cddr buffer-undo-list)))
-           (setq org-self-insert-command-undo-counter
-                 (1+ org-self-insert-command-undo-counter))))))))
+         (and (> org-self-insert-command-undo-counter 0)
+              buffer-undo-list (listp buffer-undo-list)
+              (not (cadr buffer-undo-list)) ; remove nil entry
+              (setcdr buffer-undo-list (cddr buffer-undo-list)))
+         (setq org-self-insert-command-undo-counter
+               (1+ org-self-insert-command-undo-counter))))))))
 
 (defun org-check-before-invisible-edit (kind)
   "Check is editing if kind KIND would be dangerous with invisible text around.
 The detailed reaction depends on the user option `org-catch-invisible-edits'."
   ;; First, try to get out of here as quickly as possible, to reduce overhead
-  (if (and org-catch-invisible-edits
-          (or (not (boundp 'visible-mode)) (not visible-mode))
-          (or (get-char-property (point) 'invisible)
-              (get-char-property (max (point-min) (1- (point))) 'invisible)))
-      ;; OK, we need to take a closer look
-      (let* ((invisible-at-point (get-char-property (point) 'invisible))
-            (invisible-before-point (if (bobp) nil  (get-char-property
-                                                     (1- (point)) 'invisible)))
-            (border-and-ok-direction
-             (or
-              ;; Check if we are acting predictably before invisible text
-              (and invisible-at-point (not invisible-before-point)
-                   (memq kind '(insert delete-backward)))
-              ;; Check if we are acting predictably after invisible text
-              ;; This works not well, and I have turned it off.  It seems
-              ;; better to always show and stop after invisible text.
-              ;; (and (not invisible-at-point) invisible-before-point
-              ;;  (memq kind '(insert delete)))
-              )))
-       (when (or (memq invisible-at-point '(outline org-hide-block t))
-                 (memq invisible-before-point '(outline org-hide-block t)))
-         (if (eq org-catch-invisible-edits 'error)
-             (user-error "Editing in invisible areas is prohibited, make them 
visible first"))
-         (if (and org-custom-properties-overlays
-                  (y-or-n-p "Display invisible properties in this buffer? "))
-             (org-toggle-custom-properties-visibility)
-           ;; Make the area visible
-           (save-excursion
-             (if invisible-before-point
-                 (goto-char (previous-single-char-property-change
-                             (point) 'invisible)))
-             (show-subtree))
-           (cond
-            ((eq org-catch-invisible-edits 'show)
-             ;; That's it, we do the edit after showing
-             (message
-              "Unfolding invisible region around point before editing")
-             (sit-for 1))
-            ((and (eq org-catch-invisible-edits 'smart)
-                  border-and-ok-direction)
-             (message "Unfolding invisible region around point before 
editing"))
-            (t
-             ;; Don't do the edit, make the user repeat it in full visibility
-             (user-error "Edit in invisible region aborted, repeat to confirm 
with text visible"))))))))
+  (when (and org-catch-invisible-edits
+            (or (not (boundp 'visible-mode)) (not visible-mode))
+            (or (get-char-property (point) 'invisible)
+                (get-char-property (max (point-min) (1- (point))) 'invisible)))
+    ;; OK, we need to take a closer look
+    (let* ((invisible-at-point (get-char-property (point) 'invisible))
+          (invisible-before-point (unless (bobp) (get-char-property
+                                                  (1- (point)) 'invisible)))
+          (border-and-ok-direction
+           (or
+            ;; Check if we are acting predictably before invisible text
+            (and invisible-at-point (not invisible-before-point)
+                 (memq kind '(insert delete-backward)))
+            ;; Check if we are acting predictably after invisible text
+            ;; This works not well, and I have turned it off.  It seems
+            ;; better to always show and stop after invisible text.
+            ;; (and (not invisible-at-point) invisible-before-point
+            ;;  (memq kind '(insert delete)))
+            )))
+      (when (or (memq invisible-at-point '(outline org-hide-block t))
+               (memq invisible-before-point '(outline org-hide-block t)))
+       (when (eq org-catch-invisible-edits 'error)
+         (user-error "Editing in invisible areas is prohibited, make them 
visible first"))
+       (if (and org-custom-properties-overlays
+                (y-or-n-p "Display invisible properties in this buffer? "))
+           (org-toggle-custom-properties-visibility)
+         ;; Make the area visible
+         (save-excursion
+           (when invisible-before-point
+             (goto-char (previous-single-char-property-change
+                         (point) 'invisible)))
+           (outline-show-subtree))
+         (cond
+          ((eq org-catch-invisible-edits 'show)
+           ;; That's it, we do the edit after showing
+           (message
+            "Unfolding invisible region around point before editing")
+           (sit-for 1))
+          ((and (eq org-catch-invisible-edits 'smart)
+                border-and-ok-direction)
+           (message "Unfolding invisible region around point before editing"))
+          (t
+           ;; Don't do the edit, make the user repeat it in full visibility
+           (user-error "Edit in invisible region aborted, repeat to confirm 
with text visible"))))))))
 
 (defun org-fix-tags-on-the-fly ()
-  (when (and (equal (char-after (point-at-bol)) ?*)
+  "Align tags in headline at point.
+Unlike to `org-set-tags', it ignores region and sorting."
+  (when (and (eq (char-after (line-beginning-position)) ?*) ;short-circuit
             (org-at-heading-p))
-    (org-align-tags-here org-tags-column)))
+    (let ((org-ignore-region t)
+         (org-tags-sort-function nil))
+      (org-set-tags nil t))))
 
 (defun org-delete-backward-char (N)
   "Like `delete-backward-char', insert whitespace at field end in tables.
@@ -19546,7 +20257,7 @@ because, in this case the deletion might narrow the 
column."
   (interactive "p")
   (save-match-data
     (org-check-before-invisible-edit 'delete-backward)
-    (if (and (org-table-p)
+    (if (and (org-at-table-p)
             (eq N 1)
             (string-match "|" (buffer-substring (point-at-bol) (point)))
             (looking-at ".*?|"))
@@ -19554,14 +20265,13 @@ because, in this case the deletion might narrow the 
column."
              (noalign (looking-at "[^|\n\r]*  |"))
              (c org-table-may-need-update))
          (backward-delete-char N)
-         (if (not overwrite-mode)
-             (progn
-               (skip-chars-forward "^|")
-               (insert " ")
-               (goto-char (1- pos))))
+         (unless overwrite-mode
+           (skip-chars-forward "^|")
+           (insert " ")
+           (goto-char (1- pos)))
          ;; noalign: if there were two spaces at the end, this field
          ;; does not determine the width of the column.
-         (if noalign (setq org-table-may-need-update c)))
+         (when noalign (setq org-table-may-need-update c)))
       (backward-delete-char N)
       (org-fix-tags-on-the-fly))))
 
@@ -19574,7 +20284,7 @@ because, in this case the deletion might narrow the 
column."
   (interactive "p")
   (save-match-data
     (org-check-before-invisible-edit 'delete)
-    (if (and (org-table-p)
+    (if (and (org-at-table-p)
             (not (bolp))
             (not (= (char-after) ?|))
             (eq N 1))
@@ -19587,12 +20297,12 @@ because, in this case the deletion might narrow the 
column."
              (goto-char pos)
              ;; noalign: if there were two spaces at the end, this field
              ;; does not determine the width of the column.
-             (if noalign (setq org-table-may-need-update c)))
+             (when noalign (setq org-table-may-need-update c)))
          (delete-char N))
       (delete-char N)
       (org-fix-tags-on-the-fly))))
 
-;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
+;; Make `delete-selection-mode' work with Org mode and Orgtbl mode
 (put 'org-self-insert-command 'delete-selection
      (lambda ()
        (not (run-hook-with-args-until-success
@@ -19611,7 +20321,7 @@ because, in this case the deletion might narrow the 
column."
 (put 'org-delete-char 'flyspell-delayed t)
 (put 'org-delete-backward-char 'flyspell-delayed t)
 
-;; Make pabbrev-mode expand after org-mode commands
+;; Make pabbrev-mode expand after Org mode commands
 (put 'org-self-insert-command 'pabbrev-expand-after-command t)
 (put 'orgtbl-self-insert-command 'pabbrev-expand-after-command t)
 
@@ -19621,9 +20331,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command 
names."
   (let (new old)
     (while commands
       (setq old (pop commands) new (pop commands))
-      (if (fboundp 'command-remapping)
-         (org-defkey map (vector 'remap old) new)
-       (substitute-key-definition old new map global-map)))))
+      (org-defkey map (vector 'remap old) new))))
 
 (defun org-transpose-words ()
   "Transpose words for Org.
@@ -19765,7 +20473,7 @@ See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defun org-shiftselect-error ()
   "Throw an error because Shift-Cursor command was applied in wrong context."
   (if (and (boundp 'shift-select-mode) shift-select-mode)
-      (user-error "To use shift-selection with Org-mode, customize 
`org-support-shift-select'")
+      (user-error "To use shift-selection with Org mode, customize 
`org-support-shift-select'")
     (user-error "This command works only in special context like headlines or 
timestamps")))
 
 (defun org-call-for-shift-select (cmd)
@@ -19820,32 +20528,30 @@ individual commands for more information."
     (call-interactively 'org-indent-item-tree))
    (t (org-modifier-cursor-error))))
 
-(defun org-shiftmetaup (&optional arg)
-  "Move subtree up or kill table row.
-Calls `org-move-subtree-up' or `org-table-kill-row' or
-`org-move-item-up' or `org-timestamp-up', depending on context.
-See the individual commands for more information."
+(defun org-shiftmetaup (&optional _arg)
+  "Drag the line at point up.
+In a table, kill the current row.
+On a clock timestamp, update the value of the timestamp like `S-<up>'
+but also adjust the previous clocked item in the clock history.
+Everywhere else, drag the line at point up."
   (interactive "P")
   (cond
    ((run-hook-with-args-until-success 'org-shiftmetaup-hook))
    ((org-at-table-p) (call-interactively 'org-table-kill-row))
-   ((org-at-heading-p) (call-interactively 'org-move-subtree-up))
-   ((org-at-item-p) (call-interactively 'org-move-item-up))
    ((org-at-clock-log-p) (let ((org-clock-adjust-closest t))
                           (call-interactively 'org-timestamp-up)))
    (t (call-interactively 'org-drag-line-backward))))
 
-(defun org-shiftmetadown (&optional arg)
-  "Move subtree down or insert table row.
-Calls `org-move-subtree-down' or `org-table-insert-row' or
-`org-move-item-down' or `org-timestamp-up', depending on context.
-See the individual commands for more information."
+(defun org-shiftmetadown (&optional _arg)
+  "Drag the line at point down.
+In a table, insert an empty row at the current line.
+On a clock timestamp, update the value of the timestamp like `S-<down>'
+but also adjust the previous clocked item in the clock history.
+Everywhere else, drag the line at point down."
   (interactive "P")
   (cond
    ((run-hook-with-args-until-success 'org-shiftmetadown-hook))
    ((org-at-table-p) (call-interactively 'org-table-insert-row))
-   ((org-at-heading-p) (call-interactively 'org-move-subtree-down))
-   ((org-at-item-p) (call-interactively 'org-move-item-down))
    ((org-at-clock-log-p) (let ((org-clock-adjust-closest t))
                           (call-interactively 'org-timestamp-down)))
    (t (call-interactively 'org-drag-line-forward))))
@@ -19854,11 +20560,16 @@ See the individual commands for more information."
   (user-error
    "Hidden subtree, open with TAB or use subtree command M-S-<left>/<right>"))
 
-(defun org-metaleft (&optional arg)
-  "Promote heading or move table column to left.
-Calls `org-do-promote' or `org-table-move-column', depending on context.
-With no specific context, calls the Emacs default `backward-word'.
-See the individual commands for more information."
+(defun org-metaleft (&optional _arg)
+  "Promote heading, list item at point or move table column left.
+
+Calls `org-do-promote', `org-outdent-item' or `org-table-move-column',
+depending on context.  With no specific context, calls the Emacs
+default `backward-word'.  See the individual commands for more
+information.
+
+This function runs the hook `org-metaleft-hook' as a first step,
+and returns at first non-nil value."
   (interactive "P")
   (cond
    ((run-hook-with-args-until-success 'org-metaleft-hook))
@@ -19883,11 +20594,18 @@ See the individual commands for more information."
     (call-interactively 'org-outdent-item))
    (t (call-interactively 'backward-word))))
 
-(defun org-metaright (&optional arg)
-  "Demote a subtree, a list item or move table column to right.
+(defun org-metaright (&optional _arg)
+  "Demote heading, list item at point or move table column right.
+
 In front of a drawer or a block keyword, indent it correctly.
+
+Calls `org-do-demote', `org-indent-item', `org-table-move-column',
+`org-indent-drawer' or `org-indent-block' depending on context.
 With no specific context, calls the Emacs default `forward-word'.
-See the individual commands for more information."
+See the individual commands for more information.
+
+This function runs the hook `org-metaright-hook' as a first step,
+and returns at first non-nil value."
   (interactive "P")
   (cond
    ((run-hook-with-args-until-success 'org-metaright-hook))
@@ -19937,11 +20655,11 @@ this function returns t, nil otherwise."
          (goto-char (point-at-eol))
          (setq end (max end (point)))
          (while (re-search-forward re end t)
-           (if (get-char-property (match-beginning 0) 'invisible)
-               (throw 'exit t))))
+           (when (get-char-property (match-beginning 0) 'invisible)
+             (throw 'exit t))))
        nil))))
 
-(defun org-metaup (&optional arg)
+(defun org-metaup (&optional _arg)
   "Move subtree up or move table row up.
 Calls `org-move-subtree-up' or `org-table-move-row' or
 `org-move-item-up', depending on context.  See the individual commands
@@ -19963,7 +20681,7 @@ for more information."
    ((org-at-item-p) (call-interactively 'org-move-item-up))
    (t (org-drag-element-backward))))
 
-(defun org-metadown (&optional arg)
+(defun org-metadown (&optional _arg)
   "Move subtree down or move table row down.
 Calls `org-move-subtree-down' or `org-table-move-row' or
 `org-move-item-down', depending on context.  See the individual
@@ -20149,6 +20867,32 @@ Optional argument N tells to change by that many 
units."
        (org-clock-timestamps-down n))
     (user-error "Not at a clock log")))
 
+(defun org-increase-number-at-point (&optional inc)
+  "Increment the number at point.
+With an optional prefix numeric argument INC, increment using
+this numeric value."
+  (interactive "p")
+  (if (not (number-at-point))
+      (user-error "Not on a number")
+    (unless inc (setq inc 1))
+    (let ((pos (point))
+         (beg (skip-chars-backward "-+^/*0-9eE."))
+         (end (skip-chars-forward "-+^/*0-9eE^.")) nap)
+      (setq nap (buffer-substring-no-properties
+                (+ pos beg) (+ pos beg end)))
+      (delete-region (+ pos beg) (+ pos beg end))
+      (insert (calc-eval (concat (number-to-string inc) "+" nap))))
+    (when (org-at-table-p)
+      (org-table-align)
+      (org-table-end-of-field 1))))
+
+(defun org-decrease-number-at-point (&optional inc)
+  "Decrement the number at point.
+With an optional prefix numeric argument INC, decrement using
+this numeric value."
+  (interactive "p")
+  (org-increase-number-at-point (- (or inc 1))))
+
 (defun org-ctrl-c-ret ()
   "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context."
   (interactive)
@@ -20183,19 +20927,19 @@ Optional argument N tells to change by that many 
units."
 
 (defun org-copy-special ()
   "Copy region in table or copy current subtree.
-Calls `org-table-copy' or `org-copy-subtree', depending on context.
-See the individual commands for more information."
+Calls `org-table-copy-region' or `org-copy-subtree', depending on
+context.  See the individual commands for more information."
   (interactive)
   (call-interactively
-   (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
+   (if (org-at-table-p) #'org-table-copy-region #'org-copy-subtree)))
 
 (defun org-cut-special ()
   "Cut region in table or cut current subtree.
-Calls `org-table-copy' or `org-cut-subtree', depending on context.
-See the individual commands for more information."
+Calls `org-table-cut-region' or `org-cut-subtree', depending on
+context.  See the individual commands for more information."
   (interactive)
   (call-interactively
-   (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
+   (if (org-at-table-p) #'org-table-cut-region #'org-cut-subtree)))
 
 (defun org-paste-special (arg)
   "Paste rectangular region into table, or past subtree relative to level.
@@ -20206,57 +20950,65 @@ See the individual commands for more information."
       (org-table-paste-rectangle)
     (org-paste-subtree arg)))
 
-(defsubst org-in-fixed-width-region-p ()
-  "Is point in a fixed-width region?"
-  (save-match-data
-    (eq 'fixed-width (org-element-type (org-element-at-point)))))
-
 (defun org-edit-special (&optional arg)
   "Call a special editor for the element at point.
 When at a table, call the formula editor with `org-table-edit-formulas'.
 When in a source code block, call `org-edit-src-code'.
 When in a fixed-width region, call `org-edit-fixed-width-region'.
+When in an export block, call `org-edit-export-block'.
 When at an #+INCLUDE keyword, visit the included file.
+When at a footnote reference, call `org-edit-footnote-reference'
 On a link, call `ffap' to visit the link at point.
 Otherwise, return a user error."
   (interactive "P")
   (let ((element (org-element-at-point)))
-    (assert (not buffer-read-only) nil
-           "Buffer is read-only: %s" (buffer-name))
-    (case (org-element-type element)
-      (src-block
+    (barf-if-buffer-read-only)
+    (pcase (org-element-type element)
+      (`src-block
        (if (not arg) (org-edit-src-code)
-         (let* ((info (org-babel-get-src-block-info))
-                (lang (nth 0 info))
-                (params (nth 2 info))
-                (session (cdr (assq :session params))))
-           (if (not session) (org-edit-src-code)
-             ;; At a src-block with a session and function called with
-             ;; an ARG: switch to the buffer related to the inferior
-             ;; process.
-             (switch-to-buffer
+        (let* ((info (org-babel-get-src-block-info))
+               (lang (nth 0 info))
+               (params (nth 2 info))
+               (session (cdr (assq :session params))))
+          (if (not session) (org-edit-src-code)
+            ;; At a src-block with a session and function called with
+            ;; an ARG: switch to the buffer related to the inferior
+            ;; process.
+            (switch-to-buffer
              (funcall (intern (concat "org-babel-prep-session:" lang))
                       session params))))))
-      (keyword
+      (`keyword
        (if (member (org-element-property :key element) '("INCLUDE" 
"SETUPFILE"))
-           (find-file
-            (org-remove-double-quotes
-             (car (org-split-string (org-element-property :value element)))))
+           (org-open-link-from-string
+           (format "[[%s]]"
+                   (expand-file-name
+                    (let ((value (org-element-property :value element)))
+                      (cond ((not (org-string-nw-p value))
+                             (user-error "No file to edit"))
+                            ((string-match "\\`\"\\(.*?\\)\"" value)
+                             (match-string 1 value))
+                            ((string-match "\\`[^ \t\"]\\S-*" value)
+                             (match-string 0 value))
+                            (t (user-error "No valid file specified")))))))
          (user-error "No special environment to edit here")))
-      (table
+      (`table
        (if (eq (org-element-property :type element) 'table.el)
-           (org-edit-src-code)
+           (org-edit-table.el)
          (call-interactively 'org-table-edit-formulas)))
       ;; Only Org tables contain `table-row' type elements.
-      (table-row (call-interactively 'org-table-edit-formulas))
-      ((example-block export-block) (org-edit-src-code))
-      (fixed-width (org-edit-fixed-width-region))
-      (otherwise
-       ;; No notable element at point.  Though, we may be at a link,
-       ;; which is an object.  Thus, scan deeper.
-       (if (eq (org-element-type (org-element-context element)) 'link)
-          (call-interactively 'ffap)
-        (user-error "No special environment to edit here"))))))
+      (`table-row (call-interactively 'org-table-edit-formulas))
+      (`example-block (org-edit-src-code))
+      (`export-block (org-edit-export-block))
+      (`fixed-width (org-edit-fixed-width-region))
+      (_
+       ;; No notable element at point.  Though, we may be at a link or
+       ;; a footnote reference, which are objects.  Thus, scan deeper.
+       (let ((context (org-element-context element)))
+        (pcase (org-element-type context)
+          (`footnote-reference (org-edit-footnote-reference))
+          (`inline-src-block (org-edit-inline-src-code))
+          (`link (call-interactively #'ffap))
+          (_ (user-error "No special environment to edit here"))))))))
 
 (defvar org-table-coordinate-overlays) ; defined in org-table.el
 (defun org-ctrl-c-ctrl-c (&optional arg)
@@ -20305,240 +21057,314 @@ This command does many different things, depending 
on context:
   inhibited by setting `org-babel-no-eval-on-ctrl-c-ctrl-c'."
   (interactive "P")
   (cond
-   ((or (and (boundp 'org-clock-overlays) org-clock-overlays)
-       org-occur-highlights
-       org-latex-fragment-image-overlays)
-    (and (boundp 'org-clock-overlays) (org-clock-remove-overlays))
+   ((or (bound-and-true-p org-clock-overlays) org-occur-highlights)
+    (when (boundp 'org-clock-overlays) (org-clock-remove-overlays))
     (org-remove-occur-highlights)
-    (org-remove-latex-fragment-image-overlays)
     (message "Temporary highlights/overlays removed from current buffer"))
-   ((and (local-variable-p 'org-finish-function (current-buffer))
+   ((and (local-variable-p 'org-finish-function)
         (fboundp org-finish-function))
     (funcall org-finish-function))
+   ((org-babel-hash-at-point))
    ((run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-hook))
    (t
-    (let* ((context (org-element-context)) (type (org-element-type context)))
-      ;; Test if point is within a blank line.
-      (if (save-excursion (beginning-of-line) (looking-at "[ \t]*$"))
-         (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook)
-             (user-error "C-c C-c can do nothing useful at this location"))
-       (case type
-         ;; When at a link, act according to the parent instead.
-         (link (setq context (org-element-property :parent context))
-               (setq type (org-element-type context)))
-         ;; Unsupported object types: refer to the first supported
-         ;; element or object containing it.
-         ((bold code entity export-snippet inline-babel-call inline-src-block
-                italic latex-fragment line-break macro strike-through subscript
-                superscript underline verbatim)
-          (while (and (setq context (org-element-property :parent context))
-                      (not (memq (setq type (org-element-type context))
-                                 '(radio-target paragraph verse-block
-                                                table-cell)))))))
-       ;; For convenience: at the first line of a paragraph on the
-       ;; same line as an item, apply function on that item instead.
-       (when (eq type 'paragraph)
-         (let ((parent (org-element-property :parent context)))
-           (when (and (eq (org-element-type parent) 'item)
-                      (= (point-at-bol) (org-element-property :begin parent)))
-             (setq context parent type 'item))))
-       ;; Act according to type of element or object at point.
-       (case type
-         (clock (org-clock-update-time-maybe))
-         (dynamic-block
-          (save-excursion
-            (goto-char (org-element-property :post-affiliated context))
-            (org-update-dblock)))
-         (footnote-definition
+    (let* ((context
+           (org-element-lineage
+            (org-element-context)
+            ;; Limit to supported contexts.
+            '(babel-call clock dynamic-block footnote-definition
+                         footnote-reference inline-babel-call inline-src-block
+                         inlinetask item keyword node-property paragraph
+                         plain-list property-drawer radio-target src-block
+                         statistics-cookie table table-cell table-row
+                         timestamp)
+            t))
+          (type (org-element-type context)))
+      ;; For convenience: at the first line of a paragraph on the same
+      ;; line as an item, apply function on that item instead.
+      (when (eq type 'paragraph)
+       (let ((parent (org-element-property :parent context)))
+         (when (and (eq (org-element-type parent) 'item)
+                    (= (line-beginning-position)
+                       (org-element-property :begin parent)))
+           (setq context parent)
+           (setq type 'item))))
+      ;; Act according to type of element or object at point.
+      ;;
+      ;; Do nothing on a blank line, except if it is contained in
+      ;; a src block.  Hence, we first check if point is in such
+      ;; a block and then if it is at a blank line.
+      (pcase type
+       ((or `inline-src-block `src-block)
+        (unless org-babel-no-eval-on-ctrl-c-ctrl-c
+          (org-babel-eval-wipe-error-buffer)
+          (org-babel-execute-src-block
+           current-prefix-arg (org-babel-get-src-block-info nil context))))
+       ((guard (org-match-line "[ \t]*$"))
+        (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook)
+            (user-error
+             (substitute-command-keys
+              "`\\[org-ctrl-c-ctrl-c]' can do nothing useful here"))))
+       ((or `babel-call `inline-babel-call)
+        (let ((info (org-babel-lob-get-info context)))
+          (when info (org-babel-execute-src-block nil info))))
+       (`clock (org-clock-update-time-maybe))
+       (`dynamic-block
+        (save-excursion
           (goto-char (org-element-property :post-affiliated context))
-          (call-interactively 'org-footnote-action))
-         (footnote-reference (call-interactively 'org-footnote-action))
-         ((headline inlinetask)
-          (save-excursion (goto-char (org-element-property :begin context))
-                          (call-interactively 'org-set-tags)))
-         (item
-          ;; At an item: a double C-u set checkbox to "[-]"
-          ;; unconditionally, whereas a single one will toggle its
-          ;; presence.  Without a universal argument, if the item
-          ;; has a checkbox, toggle it.  Otherwise repair the list.
-          (let* ((box (org-element-property :checkbox context))
-                 (struct (org-element-property :structure context))
-                 (old-struct (copy-tree struct))
-                 (parents (org-list-parents-alist struct))
-                 (prevs (org-list-prevs-alist struct))
-                 (orderedp (org-not-nil (org-entry-get nil "ORDERED"))))
-            (org-list-set-checkbox
-             (org-element-property :begin context) struct
-             (cond ((equal arg '(16)) "[-]")
-                   ((and (not box) (equal arg '(4))) "[ ]")
-                   ((or (not box) (equal arg '(4))) nil)
-                   ((eq box 'on) "[ ]")
-                   (t "[X]")))
-            ;; Mimic `org-list-write-struct' but with grabbing
-            ;; a return value from `org-list-struct-fix-box'.
-            (org-list-struct-fix-ind struct parents 2)
-            (org-list-struct-fix-item-end struct)
-            (org-list-struct-fix-bul struct prevs)
-            (org-list-struct-fix-ind struct parents)
-            (let ((block-item
-                   (org-list-struct-fix-box struct parents prevs orderedp)))
-              (if (and box (equal struct old-struct))
-                  (if (equal arg '(16))
-                      (message "Checkboxes already reset")
-                    (user-error "Cannot toggle this checkbox: %s"
-                                (if (eq box 'on)
-                                    "all subitems checked"
-                                  "unchecked subitems")))
-                (org-list-struct-apply-struct struct old-struct)
-                (org-update-checkbox-count-maybe))
-              (when block-item
-                (message "Checkboxes were removed due to empty box at line %d"
-                         (org-current-line block-item))))))
-         (keyword
-          (let ((org-inhibit-startup-visibility-stuff t)
-                (org-startup-align-all-tables nil))
-            (when (boundp 'org-table-coordinate-overlays)
-              (mapc 'delete-overlay org-table-coordinate-overlays)
-              (setq org-table-coordinate-overlays nil))
-            (org-save-outline-visibility 'use-markers (org-mode-restart)))
-          (message "Local setup has been refreshed"))
-         (plain-list
-          ;; At a plain list, with a double C-u argument, set
-          ;; checkboxes of each item to "[-]", whereas a single one
-          ;; will toggle their presence according to the state of the
-          ;; first item in the list.  Without an argument, repair the
-          ;; list.
-          (let* ((begin (org-element-property :contents-begin context))
-                 (beginm (move-marker (make-marker) begin))
-                 (struct (org-element-property :structure context))
-                 (old-struct (copy-tree struct))
-                 (first-box (save-excursion
-                              (goto-char begin)
-                              (looking-at org-list-full-item-re)
-                              (match-string-no-properties 3)))
-                 (new-box (cond ((equal arg '(16)) "[-]")
-                                ((equal arg '(4)) (unless first-box "[ ]"))
-                                ((equal first-box "[X]") "[ ]")
-                                (t "[X]"))))
-            (cond
-             (arg
-              (mapc (lambda (pos) (org-list-set-checkbox pos struct new-box))
-                    (org-list-get-all-items
-                     begin struct (org-list-prevs-alist struct))))
-             ((and first-box (eq (point) begin))
-              ;; For convenience, when point is at bol on the first
-              ;; item of the list and no argument is provided, simply
-              ;; toggle checkbox of that item, if any.
-              (org-list-set-checkbox begin struct new-box)))
-            (org-list-write-struct
-             struct (org-list-parents-alist struct) old-struct)
-            (org-update-checkbox-count-maybe)
-            (save-excursion (goto-char beginm) (org-list-send-list 'maybe))))
-         ((property-drawer node-property)
-          (call-interactively 'org-property-action))
-         ((radio-target target)
-          (call-interactively 'org-update-radio-target-regexp))
-         (statistics-cookie
-          (call-interactively 'org-update-statistics-cookies))
-         ((table table-cell table-row)
-          ;; At a table, recalculate every field and align it.  Also
-          ;; send the table if necessary.  If the table has
-          ;; a `table.el' type, just give up.  At a table row or
-          ;; cell, maybe recalculate line but always align table.
-          (if (eq (org-element-property :type context) 'table.el)
-              (message "%s" "Use C-c ' to edit table.el tables")
-            (let ((org-enable-table-editor t))
-              (if (or (eq type 'table)
-                      ;; Check if point is at a TBLFM line.
-                      (and (eq type 'table-row)
-                           (= (point) (org-element-property :end context))))
-                  (save-excursion
-                    (if (org-at-TBLFM-p)
-                        (progn (require 'org-table)
-                               (org-table-calc-current-TBLFM))
-                      (goto-char (org-element-property :contents-begin 
context))
-                      (org-call-with-arg 'org-table-recalculate (or arg t))
-                      (orgtbl-send-table 'maybe)))
-                (org-table-maybe-eval-formula)
-                (cond (arg (call-interactively 'org-table-recalculate))
-                      ((org-table-maybe-recalculate-line))
-                      (t (org-table-align)))))))
-         (timestamp (org-timestamp-change 0 'day))
-         (otherwise
-          (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook)
-              (user-error
-               "C-c C-c can do nothing useful at this location")))))))))
+          (org-update-dblock)))
+       (`footnote-definition
+        (goto-char (org-element-property :post-affiliated context))
+        (call-interactively 'org-footnote-action))
+       (`footnote-reference (call-interactively #'org-footnote-action))
+       ((or `headline `inlinetask)
+        (save-excursion (goto-char (org-element-property :begin context))
+                        (call-interactively #'org-set-tags)))
+       (`item
+        ;; At an item: `C-u C-u' sets checkbox to "[-]"
+        ;; unconditionally, whereas `C-u' will toggle its presence.
+        ;; Without a universal argument, if the item has a checkbox,
+        ;; toggle it.  Otherwise repair the list.
+        (let* ((box (org-element-property :checkbox context))
+               (struct (org-element-property :structure context))
+               (old-struct (copy-tree struct))
+               (parents (org-list-parents-alist struct))
+               (prevs (org-list-prevs-alist struct))
+               (orderedp (org-not-nil (org-entry-get nil "ORDERED"))))
+          (org-list-set-checkbox
+           (org-element-property :begin context) struct
+           (cond ((equal arg '(16)) "[-]")
+                 ((and (not box) (equal arg '(4))) "[ ]")
+                 ((or (not box) (equal arg '(4))) nil)
+                 ((eq box 'on) "[ ]")
+                 (t "[X]")))
+          ;; Mimic `org-list-write-struct' but with grabbing a return
+          ;; value from `org-list-struct-fix-box'.
+          (org-list-struct-fix-ind struct parents 2)
+          (org-list-struct-fix-item-end struct)
+          (org-list-struct-fix-bul struct prevs)
+          (org-list-struct-fix-ind struct parents)
+          (let ((block-item
+                 (org-list-struct-fix-box struct parents prevs orderedp)))
+            (if (and box (equal struct old-struct))
+                (if (equal arg '(16))
+                    (message "Checkboxes already reset")
+                  (user-error "Cannot toggle this checkbox: %s"
+                              (if (eq box 'on)
+                                  "all subitems checked"
+                                "unchecked subitems")))
+              (org-list-struct-apply-struct struct old-struct)
+              (org-update-checkbox-count-maybe))
+            (when block-item
+              (message "Checkboxes were removed due to empty box at line %d"
+                       (org-current-line block-item))))))
+       (`keyword
+        (let ((org-inhibit-startup-visibility-stuff t)
+              (org-startup-align-all-tables nil))
+          (when (boundp 'org-table-coordinate-overlays)
+            (mapc #'delete-overlay org-table-coordinate-overlays)
+            (setq org-table-coordinate-overlays nil))
+          (org-save-outline-visibility 'use-markers (org-mode-restart)))
+        (message "Local setup has been refreshed"))
+       (`plain-list
+        ;; At a plain list, with a double C-u argument, set
+        ;; checkboxes of each item to "[-]", whereas a single one
+        ;; will toggle their presence according to the state of the
+        ;; first item in the list.  Without an argument, repair the
+        ;; list.
+        (let* ((begin (org-element-property :contents-begin context))
+               (beginm (move-marker (make-marker) begin))
+               (struct (org-element-property :structure context))
+               (old-struct (copy-tree struct))
+               (first-box (save-excursion
+                            (goto-char begin)
+                            (looking-at org-list-full-item-re)
+                            (match-string-no-properties 3)))
+               (new-box (cond ((equal arg '(16)) "[-]")
+                              ((equal arg '(4)) (unless first-box "[ ]"))
+                              ((equal first-box "[X]") "[ ]")
+                              (t "[X]"))))
+          (cond
+           (arg
+            (dolist (pos
+                     (org-list-get-all-items
+                      begin struct (org-list-prevs-alist struct)))
+              (org-list-set-checkbox pos struct new-box)))
+           ((and first-box (eq (point) begin))
+            ;; For convenience, when point is at bol on the first
+            ;; item of the list and no argument is provided, simply
+            ;; toggle checkbox of that item, if any.
+            (org-list-set-checkbox begin struct new-box)))
+          (org-list-write-struct
+           struct (org-list-parents-alist struct) old-struct)
+          (org-update-checkbox-count-maybe)
+          (save-excursion (goto-char beginm) (org-list-send-list 'maybe))))
+       ((or `property-drawer `node-property)
+        (call-interactively #'org-property-action))
+       (`radio-target
+        (call-interactively #'org-update-radio-target-regexp))
+       (`statistics-cookie
+        (call-interactively #'org-update-statistics-cookies))
+       ((or `table `table-cell `table-row)
+        ;; At a table, recalculate every field and align it.  Also
+        ;; send the table if necessary.  If the table has
+        ;; a `table.el' type, just give up.  At a table row or cell,
+        ;; maybe recalculate line but always align table.
+        (if (eq (org-element-property :type context) 'table.el)
+            (message "%s" (substitute-command-keys "\\<org-mode-map>\
+Use `\\[org-edit-special]' to edit table.el tables"))
+          (let ((org-enable-table-editor t))
+            (if (or (eq type 'table)
+                    ;; Check if point is at a TBLFM line.
+                    (and (eq type 'table-row)
+                         (= (point) (org-element-property :end context))))
+                (save-excursion
+                  (if (org-at-TBLFM-p)
+                      (progn (require 'org-table)
+                             (org-table-calc-current-TBLFM))
+                    (goto-char (org-element-property :contents-begin context))
+                    (org-call-with-arg 'org-table-recalculate (or arg t))
+                    (orgtbl-send-table 'maybe)))
+              (org-table-maybe-eval-formula)
+              (cond (arg (call-interactively #'org-table-recalculate))
+                    ((org-table-maybe-recalculate-line))
+                    (t (org-table-align)))))))
+       (`timestamp (org-timestamp-change 0 'day))
+       ((and `nil (guard (org-at-heading-p)))
+        ;; When point is on an unsupported object type, we can miss
+        ;; the fact that it also is at a heading.  Handle it here.
+        (call-interactively #'org-set-tags))
+       ((guard
+         (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook)))
+       (_
+        (user-error
+         (substitute-command-keys
+          "`\\[org-ctrl-c-ctrl-c]' can do nothing useful here"))))))))
 
 (defun org-mode-restart ()
   (interactive)
-  (let ((indent-status (org-bound-and-true-p org-indent-mode)))
+  (let ((indent-status (bound-and-true-p org-indent-mode)))
     (funcall major-mode)
     (hack-local-variables)
-    (when (and indent-status (not (org-bound-and-true-p org-indent-mode)))
+    (when (and indent-status (not (bound-and-true-p org-indent-mode)))
       (org-indent-mode -1)))
   (message "%s restarted" major-mode))
 
 (defun org-kill-note-or-show-branches ()
-  "If this is a Note buffer, abort storing the note.  Else call 
`show-branches'."
+  "Abort storing current note, or call `outline-show-branches'."
   (interactive)
   (if (not org-finish-function)
       (progn
-       (hide-subtree)
-       (call-interactively 'show-branches))
+       (outline-hide-subtree)
+       (call-interactively 'outline-show-branches))
     (let ((org-note-abort t))
       (funcall org-finish-function))))
 
+(defun org-delete-indentation (&optional arg)
+  "Join current line to previous and fix whitespace at join.
+
+If previous line is a headline add to headline title.  Otherwise
+the function calls `delete-indentation'.
+
+With a non-nil optional argument, join it to the following one."
+  (interactive "*P")
+  (if (save-excursion
+       (beginning-of-line (if arg 1 0))
+       (let ((case-fold-search nil))
+         (looking-at org-complex-heading-regexp)))
+      ;; At headline.
+      (let ((tags-column (when (match-beginning 5)
+                          (save-excursion (goto-char (match-beginning 5))
+                                          (current-column))))
+           (string (concat " " (progn (when arg (forward-line 1))
+                                      (org-trim (delete-and-extract-region
+                                                 (line-beginning-position)
+                                                 (line-end-position)))))))
+       (unless (bobp) (delete-region (point) (1- (point))))
+       (goto-char (or (match-end 4)
+                      (match-beginning 5)
+                      (match-end 0)))
+       (skip-chars-backward " \t")
+       (save-excursion (insert string))
+       ;; Adjust alignment of tags.
+       (cond
+        ((not tags-column))            ;no tags
+        (org-auto-align-tags (org-set-tags nil t))
+        (t (org--align-tags-here tags-column)))) ;preserve tags column
+    (delete-indentation arg)))
+
 (defun org-open-line (n)
   "Insert a new row in tables, call `open-line' elsewhere.
-If `org-special-ctrl-o' is nil, just call `open-line' everywhere."
+If `org-special-ctrl-o' is nil, just call `open-line' everywhere.
+As a special case, when a document starts with a table, allow to
+call `open-line' on the very first character."
   (interactive "*p")
-  (cond
-   ((not org-special-ctrl-o)
-    (open-line n))
-   ((org-at-table-p)
-    (org-table-insert-row))
-   (t
-    (open-line n))))
+  (if (and org-special-ctrl-o (/= (point) 1) (org-at-table-p))
+      (org-table-insert-row)
+    (open-line n)))
 
 (defun org-return (&optional indent)
   "Goto next table row or insert a newline.
+
 Calls `org-table-next-row' or `newline', depending on context.
-See the individual commands for more information."
+
+When optional INDENT argument is non-nil, call
+`newline-and-indent' instead of `newline'.
+
+When `org-return-follows-link' is non-nil and point is on
+a timestamp or a link, call `org-open-at-point'.  However, it
+will not happen if point is in a table or on a \"dead\"
+object (e.g., within a comment).  In these case, you need to use
+`org-open-at-point' directly."
   (interactive)
-  (let (org-ts-what)
+  (let ((context (if org-return-follows-link (org-element-context)
+                  (org-element-at-point))))
     (cond
-     ((or (bobp) (org-in-src-block-p))
-      (if indent (newline-and-indent) (newline)))
-     ((org-at-table-p)
+     ;; In a table, call `org-table-next-row'.
+     ((or (and (eq (org-element-type context) 'table)
+              (>= (point) (org-element-property :contents-begin context))
+              (< (point) (org-element-property :contents-end context)))
+         (org-element-lineage context '(table-row table-cell) t))
       (org-table-justify-field-maybe)
-      (call-interactively 'org-table-next-row))
-     ;; when `newline-and-indent' is called within a list, make sure
-     ;; text moved stays inside the item.
-     ((and (org-in-item-p) indent)
-      (if (and (org-at-item-p) (>= (point) (match-end 0)))
-         (progn
-           (save-match-data (newline))
-           (org-indent-line-to (length (match-string 0))))
-       (let ((ind (org-get-indentation)))
-         (newline)
-         (if (org-looking-back org-list-end-re)
-             (org-indent-line)
-           (org-indent-line-to ind)))))
-     ((and org-return-follows-link
-          (org-at-timestamp-p t)
-          (not (eq org-ts-what 'after)))
-      (org-follow-timestamp-link))
+      (call-interactively #'org-table-next-row))
+     ;; On a link or a timestamp, call `org-open-at-point' if
+     ;; `org-return-follows-link' allows it.  Tolerate fuzzy
+     ;; locations, e.g., in a comment, as `org-open-at-point'.
      ((and org-return-follows-link
-          (let ((tprop (get-text-property (point) 'face)))
-            (or (eq tprop 'org-link)
-                (and (listp tprop) (memq 'org-link tprop)))))
-      (call-interactively 'org-open-at-point))
-     ((and (org-at-heading-p)
-          (looking-at
-           (org-re "\\([ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)[ \t]*$")))
-      (org-show-entry)
-      (end-of-line 1)
-      (newline))
+          (or (org-in-regexp org-ts-regexp-both nil t)
+              (org-in-regexp org-tsr-regexp-both nil  t)
+              (org-in-regexp org-any-link-re nil t)))
+      (call-interactively #'org-open-at-point))
+     ;; Insert newline in heading, but preserve tags.
+     ((and (not (bolp))
+          (save-excursion (beginning-of-line)
+                          (let ((case-fold-search nil))
+                            (looking-at org-complex-heading-regexp))))
+      ;; At headline.  Split line.  However, if point is on keyword,
+      ;; priority cookie or tags, do not break any of them: add
+      ;; a newline after the headline instead.
+      (let ((tags-column (and (match-beginning 5)
+                             (save-excursion (goto-char (match-beginning 5))
+                                             (current-column))))
+           (string
+            (when (and (match-end 4) (org-point-in-group (point) 4))
+              (delete-and-extract-region (point) (match-end 4)))))
+       ;; Adjust tag alignment.
+       (cond
+        ((not (and tags-column string)))
+        (org-auto-align-tags (org-set-tags nil t))
+        (t (org--align-tags-here tags-column))) ;preserve tags column
+       (end-of-line)
+       (org-show-entry)
+       (if indent (newline-and-indent) (newline))
+       (when string (save-excursion (insert (org-trim string))))))
+     ;; In a list, make sure indenting keeps trailing text within.
+     ((and indent
+          (not (eolp))
+          (org-element-lineage context '(item)))
+      (let ((trailing-data
+            (delete-and-extract-region (point) (line-end-position))))
+       (newline-and-indent)
+       (save-excursion (insert trailing-data))))
      (t (if indent (newline-and-indent) (newline))))))
 
 (defun org-return-indent ()
@@ -20571,146 +21397,16 @@ Calls `org-table-insert-hline', `org-toggle-item', or
     (call-interactively 'org-table-insert-hline))
    ((org-region-active-p)
     (call-interactively 'org-toggle-item))
-   ((org-in-item-p)
-    (call-interactively 'org-cycle-list-bullet))
-   (t
-    (call-interactively 'org-toggle-item))))
-
-(defun org-toggle-item (arg)
-  "Convert headings or normal lines to items, items to normal lines.
-If there is no active region, only the current line is considered.
-
-If the first non blank line in the region is a headline, convert
-all headlines to items, shifting text accordingly.
-
-If it is an item, convert all items to normal lines.
-
-If it is normal text, change region into a list of items.
-With a prefix argument ARG, change the region in a single item."
-  (interactive "P")
-  (let ((shift-text
-        (function
-         ;; Shift text in current section to IND, from point to END.
-         ;; The function leaves point to END line.
-         (lambda (ind end)
-           (let ((min-i 1000) (end (copy-marker end)))
-             ;; First determine the minimum indentation (MIN-I) of
-             ;; the text.
-             (save-excursion
-               (catch 'exit
-                 (while (< (point) end)
-                   (let ((i (org-get-indentation)))
-                     (cond
-                      ;; Skip blank lines and inline tasks.
-                      ((looking-at "^[ \t]*$"))
-                      ((looking-at org-outline-regexp-bol))
-                      ;; We can't find less than 0 indentation.
-                      ((zerop i) (throw 'exit (setq min-i 0)))
-                      ((< i min-i) (setq min-i i))))
-                   (forward-line))))
-             ;; Then indent each line so that a line indented to
-             ;; MIN-I becomes indented to IND.  Ignore blank lines
-             ;; and inline tasks in the process.
-             (let ((delta (- ind min-i)))
-               (while (< (point) end)
-                 (unless (or (looking-at "^[ \t]*$")
-                             (looking-at org-outline-regexp-bol))
-                   (org-indent-line-to (+ (org-get-indentation) delta)))
-                 (forward-line)))))))
-       (skip-blanks
-        (function
-         ;; Return beginning of first non-blank line, starting from
-         ;; line at POS.
-         (lambda (pos)
-           (save-excursion
-             (goto-char pos)
-             (skip-chars-forward " \r\t\n")
-             (point-at-bol)))))
-       beg end)
-    ;; Determine boundaries of changes.
-    (if (org-region-active-p)
-       (setq beg (funcall skip-blanks (region-beginning))
-             end (copy-marker (region-end)))
-      (setq beg (funcall skip-blanks (point-at-bol))
-           end (copy-marker (point-at-eol))))
-    ;; Depending on the starting line, choose an action on the text
-    ;; between BEG and END.
-    (org-with-limited-levels
-     (save-excursion
-       (goto-char beg)
-       (cond
-       ;; Case 1. Start at an item: de-itemize.  Note that it only
-       ;;         happens when a region is active: `org-ctrl-c-minus'
-       ;;         would call `org-cycle-list-bullet' otherwise.
-       ((org-at-item-p)
-        (while (< (point) end)
-          (when (org-at-item-p)
-            (skip-chars-forward " \t")
-            (delete-region (point) (match-end 0)))
-          (forward-line)))
-       ;; Case 2. Start at an heading: convert to items.
-       ((org-at-heading-p)
-        (let* ((bul (org-list-bullet-string "-"))
-               (bul-len (length bul))
-               ;; Indentation of the first heading.  It should be
-               ;; relative to the indentation of its parent, if any.
-               (start-ind (save-excursion
-                            (cond
-                             ((not org-adapt-indentation) 0)
-                             ((not (outline-previous-heading)) 0)
-                             (t (length (match-string 0))))))
-               ;; Level of first heading.  Further headings will be
-               ;; compared to it to determine hierarchy in the list.
-               (ref-level (org-reduced-level (org-outline-level))))
-          (while (< (point) end)
-            (let* ((level (org-reduced-level (org-outline-level)))
-                   (delta (max 0 (- level ref-level))))
-              ;; If current headline is less indented than the first
-              ;; one, set it as reference, in order to preserve
-              ;; subtrees.
-              (when (< level ref-level) (setq ref-level level))
-              (replace-match bul t t)
-              (org-indent-line-to (+ start-ind (* delta bul-len)))
-              ;; Ensure all text down to END (or SECTION-END) belongs
-              ;; to the newly created item.
-              (let ((section-end (save-excursion
-                                   (or (outline-next-heading) (point)))))
-                (forward-line)
-                (funcall shift-text
-                         (+ start-ind (* (1+ delta) bul-len))
-                         (min end section-end)))))))
-       ;; Case 3. Normal line with ARG: make the first line of region
-       ;;         an item, and shift indentation of others lines to
-       ;;         set them as item's body.
-       (arg (let* ((bul (org-list-bullet-string "-"))
-                 (bul-len (length bul))
-                 (ref-ind (org-get-indentation)))
-            (skip-chars-forward " \t")
-            (insert bul)
-            (forward-line)
-            (while (< (point) end)
-              ;; Ensure that lines less indented than first one
-              ;; still get included in item body.
-              (funcall shift-text
-                       (+ ref-ind bul-len)
-                       (min end (save-excursion (or (outline-next-heading)
-                                                    (point)))))
-              (forward-line))))
-       ;; Case 4. Normal line without ARG: turn each non-item line
-       ;;         into an item.
-       (t
-        (while (< (point) end)
-          (unless (or (org-at-heading-p) (org-at-item-p))
-            (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
-                (replace-match
-                 (concat "\\1" (org-list-bullet-string "-") "\\2"))))
-          (forward-line))))))))
+   ((org-in-item-p)
+    (call-interactively 'org-cycle-list-bullet))
+   (t
+    (call-interactively 'org-toggle-item))))
 
 (defun org-toggle-heading (&optional nstars)
   "Convert headings to normal text, or items or text to headings.
 If there is no active region, only convert the current line.
 
-With a \\[universal-argument] prefix, convert the whole list at
+With a `\\[universal-argument]' prefix, convert the whole list at
 point into heading.
 
 In a region:
@@ -20746,7 +21442,7 @@ number of stars to add."
     ;; do not consider the last line to be in the region.
 
     (when (and current-prefix-arg (org-at-item-p))
-      (if (listp current-prefix-arg) (setq current-prefix-arg 1))
+      (when (listp current-prefix-arg) (setq current-prefix-arg 1))
       (org-mark-element))
 
     (if (org-region-active-p)
@@ -20771,31 +21467,17 @@ number of stars to add."
        ;; Case 2. Started at an item: change items into headlines.
        ;;         One star will be added by `org-list-to-subtree'.
        ((org-at-item-p)
-        (let* ((stars (make-string
-                       ;; subtract the star that will be added again by
-                       ;; `org-list-to-subtree'
-                       (if (numberp nstars) (1- nstars)
-                         (or (org-current-level) 0))
-                       ?*))
-               (add-stars
-                (cond (nstars "")               ; stars from prefix only
-                      ((equal stars "") "")     ; before first heading
-                      (org-odd-levels-only "*") ; inside heading, odd
-                      (t ""))))                 ; inside heading, oddeven
-          (while (< (point) end)
-            (when (org-at-item-p)
-              ;; Pay attention to cases when region ends before list.
-              (let* ((struct (org-list-struct))
-                     (list-end (min (org-list-get-bottom-point struct) (1+ 
end))))
-                (save-restriction
-                  (narrow-to-region (point) list-end)
-                  (insert
-                   (org-list-to-subtree
-                    (org-list-parse-list t)
-                    `(:istart (concat ',stars ',add-stars (funcall get-stars 
depth))
-                       :icount (concat ',stars ',add-stars (funcall get-stars 
depth)))))))
-              (setq toggled t))
-            (forward-line))))
+        (while (< (point) end)
+          (when (org-at-item-p)
+            ;; Pay attention to cases when region ends before list.
+            (let* ((struct (org-list-struct))
+                   (list-end
+                    (min (org-list-get-bottom-point struct) (1+ end))))
+              (save-restriction
+                (narrow-to-region (point) list-end)
+                (insert (org-list-to-subtree (org-list-to-lisp t)) "\n")))
+            (setq toggled t))
+          (forward-line)))
        ;; Case 3. Started at normal text: make every line an heading,
        ;;         skipping headlines and items.
        (t (let* ((stars
@@ -20807,7 +21489,7 @@ number of stars to add."
                         (org-odd-levels-only "**") ; inside heading, odd
                         (t "*")))                  ; inside heading, oddeven
                  (rpl (concat stars add-stars " "))
-                 (lend (if (listp nstars) (save-excursion (end-of-line) 
(point)))))
+                 (lend (when (listp nstars) (save-excursion (end-of-line) 
(point)))))
             (while (< (point) (if (equal nstars '(4)) lend end))
               (when (and (not (or (org-at-heading-p) (org-at-item-p) 
(org-at-comment-p)))
                          (looking-at "\\([ \t]*\\)\\(\\S-\\)"))
@@ -20822,17 +21504,8 @@ on context.  See the individual commands for more 
information."
   (interactive)
   (org-check-before-invisible-edit 'insert)
   (or (run-hook-with-args-until-success 'org-metareturn-hook)
-      (let* ((element (org-element-at-point))
-             (type (org-element-type element)))
-        (when (eq type 'table-row)
-          (setq element (org-element-property :parent element))
-          (setq type 'table))
-        (if (and (eq type 'table)
-                 (eq (org-element-property :type element) 'org)
-                 (>= (point) (org-element-property :contents-begin element))
-                 (< (point) (org-element-property :contents-end element)))
-            (call-interactively 'org-table-wrap-region)
-          (call-interactively 'org-insert-heading)))))
+      (call-interactively (if (org-at-table-p) #'org-table-wrap-region
+                           #'org-insert-heading))))
 
 ;;; Menu entries
 
@@ -20841,7 +21514,7 @@ on context.  See the individual commands for more 
information."
   (and (not (org-before-first-heading-p))
        (not (org-at-table-p))))
 
-;; Define the Org-mode menus
+;; Define the Org mode menus
 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
   '("Tbl"
     ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p)]
@@ -20888,11 +21561,11 @@ on context.  See the individual commands for more 
information."
      ["Which Column?" org-table-current-column (org-at-table-p)])
     ["Debug Formulas"
      org-table-toggle-formula-debugger
-     :style toggle :selected (org-bound-and-true-p org-table-formula-debug)]
+     :style toggle :selected (bound-and-true-p org-table-formula-debug)]
     ["Show Col/Row Numbers"
      org-table-toggle-coordinate-overlays
      :style toggle
-     :selected (org-bound-and-true-p org-table-overlay-coordinates)]
+     :selected (bound-and-true-p org-table-overlay-coordinates)]
     "--"
     ["Create" org-table-create (and (not (org-at-table-p))
                                    org-enable-table-editor)]
@@ -20900,7 +21573,11 @@ on context.  See the individual commands for more 
information."
     ["Import from File" org-table-import (not (org-at-table-p))]
     ["Export to File" org-table-export (org-at-table-p)]
     "--"
-    ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
+    ["Create/Convert from/to table.el" org-table-create-with-table.el t]
+    "--"
+    ("Plot"
+     ["Ascii plot" orgtbl-ascii-plot :active (org-at-table-p) :keys "C-c \" a"]
+     ["Gnuplot" org-plot/gnuplot :active (org-at-table-p) :keys "C-c \" g"])))
 
 (easy-menu-define org-org-menu org-mode-map "Org menu"
   '("Org"
@@ -20909,7 +21586,7 @@ on context.  See the individual commands for more 
information."
      ["Cycle Global Visibility" org-shifttab :active (not (org-at-table-p))]
      ["Sparse Tree..." org-sparse-tree t]
      ["Reveal Context" org-reveal t]
-     ["Show All" show-all t]
+     ["Show All" outline-show-all t]
      "--"
      ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
     "--"
@@ -20925,8 +21602,8 @@ on context.  See the individual commands for more 
information."
     ("Edit Structure"
      ["Refile Subtree" org-refile (org-in-subtree-not-table-p)]
      "--"
-     ["Move Subtree Up" org-shiftmetaup (org-in-subtree-not-table-p)]
-     ["Move Subtree Down" org-shiftmetadown (org-in-subtree-not-table-p)]
+     ["Move Subtree Up" org-metaup (org-at-heading-p)]
+     ["Move Subtree Down" org-metadown (org-at-heading-p)]
      "--"
      ["Copy Subtree"  org-copy-special (org-in-subtree-not-table-p)]
      ["Cut Subtree"  org-cut-special (org-in-subtree-not-table-p)]
@@ -21012,7 +21689,7 @@ on context.  See the individual commands for more 
information."
      "--"
      ["Set property" org-set-property (not (org-before-first-heading-p))]
      ["Column view of properties" org-columns t]
-     ["Insert Column View DBlock" org-insert-columns-dblock t])
+     ["Insert Column View DBlock" org-columns-insert-dblock t])
     ("Dates and Scheduling"
      ["Timestamp" org-time-stamp (not (org-before-first-heading-p))]
      ["Timestamp (inactive)" org-time-stamp-inactive (not 
(org-before-first-heading-p))]
@@ -21073,9 +21750,7 @@ on context.  See the individual commands for more 
information."
      ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
      ["Modify math symbol" org-cdlatex-math-modify
       (org-inside-LaTeX-fragment-p)]
-     ["Insert citation" org-reftex-citation t]
-     "--"
-     ["Template for BEAMER" (org-beamer-insert-options-template) t])
+     ["Insert citation" org-reftex-citation t])
     "--"
     ("MobileOrg"
      ["Push Files and Views" org-mobile-push t]
@@ -21101,20 +21776,20 @@ on context.  See the individual commands for more 
information."
     ))
 
 (defun org-info (&optional node)
-  "Read documentation for Org-mode in the info system.
+  "Read documentation for Org in the info system.
 With optional NODE, go directly to that node."
   (interactive)
   (info (format "(org)%s" (or node ""))))
 
 ;;;###autoload
 (defun org-submit-bug-report ()
-  "Submit a bug report on Org-mode via mail.
+  "Submit a bug report on Org via mail.
 
 Don't hesitate to report any problems or inaccurate documentation.
 
 If you don't have setup sending mail from (X)Emacs, please copy the
 output buffer into your mail program, as it gives us important
-information about your Org-mode version and configuration."
+information about your Org version and configuration."
   (interactive)
   (require 'reporter)
   (defvar reporter-prompt-for-summary-p)
@@ -21126,12 +21801,12 @@ information about your Org-mode version and 
configuration."
      (org-version nil 'full)
      (let (list)
        (save-window-excursion
-        (org-pop-to-buffer-same-window (get-buffer-create "*Warn about 
privacy*"))
+        (pop-to-buffer-same-window (get-buffer-create "*Warn about privacy*"))
         (delete-other-windows)
         (erase-buffer)
-        (insert "You are about to submit a bug report to the Org-mode mailing 
list.
+        (insert "You are about to submit a bug report to the Org mailing list.
 
-We would like to add your full Org-mode and Outline configuration to the
+We would like to add your full Org and Outline configuration to the
 bug report.  This greatly simplifies the work of the maintainer and
 other experts on the mailing list.
 
@@ -21141,7 +21816,7 @@ appear in the form of file names, tags, todo states, or 
search strings.
 If you answer yes to the prompt, you might want to check and remove
 such private information before sending the email.")
         (add-text-properties (point-min) (point-max) '(face org-warning))
-        (when (yes-or-no-p "Include your Org-mode configuration ")
+        (when (yes-or-no-p "Include your Org configuration ")
           (mapatoms
            (lambda (v)
              (and (boundp v)
@@ -21160,11 +21835,11 @@ what in fact did happen.  You don't know how to make 
a good report?  See
 
      http://orgmode.org/manual/Feedback.html#Feedback
 
-Your bug report will be posted to the Org-mode mailing list.
+Your bug report will be posted to the Org mailing list.
 ------------------------------------------------------------------------")
     (save-excursion
-      (if (re-search-backward "^\\(Subject: \\)Org-mode version \\(.*?\\);[ 
\t]*\\(.*\\)" nil t)
-         (replace-match "\\1Bug: \\3 [\\2]")))))
+      (when (re-search-backward "^\\(Subject: \\)Org mode version \\(.*?\\);[ 
\t]*\\(.*\\)" nil t)
+       (replace-match "\\1Bug: \\3 [\\2]")))))
 
 
 (defun org-install-agenda-files-menu ()
@@ -21172,7 +21847,7 @@ Your bug report will be posted to the Org-mode mailing 
list.
     (save-excursion
       (while bl
        (set-buffer (pop bl))
-       (if (derived-mode-p 'org-mode) (setq bl nil)))
+       (when (derived-mode-p 'org-mode) (setq bl nil)))
       (when (derived-mode-p 'org-mode)
        (easy-menu-change
         '("Org") "File List for Agenda"
@@ -21190,7 +21865,7 @@ Your bug report will be posted to the Org-mode mailing 
list.
 
 (defun org-require-autoloaded-modules ()
   (interactive)
-  (mapc 'require
+  (mapc #'require
        '(org-agenda org-archive org-attach org-clock org-colview org-id
                     org-table org-timer)))
 
@@ -21203,13 +21878,8 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
   (let* ((org-dir     (org-find-library-dir "org"))
         (contrib-dir (or (org-find-library-dir "org-contribdir") org-dir))
         (feature-re "^\\(org\\|ob\\|ox\\)\\(-.*\\)?")
-        (remove-re (mapconcat 'identity
-                              (mapcar (lambda (f) (concat "^" f "$"))
-                                      (list (if (featurep 'xemacs)
-                                                "org-colview"
-                                              "org-colview-xemacs")
-                                            "org" "org-loaddefs" 
"org-version"))
-                              "\\|"))
+        (remove-re (format "\\`%s\\'"
+                           (regexp-opt '("org" "org-loaddefs" "org-version"))))
         (feats (delete-dups
                 (mapcar 'file-name-sans-extension
                         (mapcar 'file-name-nondirectory
@@ -21241,9 +21911,9 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
                                   't)
                              f))
                        lfeat)))
-    (if load-uncore
-       (message "The following feature%s found in load-path, please check if 
that's correct:\n%s"
-                (if (> (length load-uncore) 1) "s were" " was") load-uncore))
+    (when load-uncore
+      (message "The following feature%s found in load-path, please check if 
that's correct:\n%s"
+              (if (> (length load-uncore) 1) "s were" " was") load-uncore))
     (if load-misses
        (message "Some error occurred while reloading Org feature%s\n%s\nPlease 
check *Messages*!\n%s"
                 (if (> (length load-misses) 1) "s" "") load-misses 
(org-version nil 'full))
@@ -21258,7 +21928,7 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
   (customize-browse 'org))
 
 (defun org-create-customize-menu ()
-  "Create a full customization menu for Org-mode, insert it into the menu."
+  "Create a full customization menu for Org mode, insert it into the menu."
   (interactive)
   (org-load-modules-maybe)
   (org-require-autoloaded-modules)
@@ -21281,9 +21951,9 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
 
 ;;; Generally useful functions
 
-(defun org-get-at-bol (property)
-  "Get text property PROPERTY at beginning of line."
-  (get-text-property (point-at-bol) property))
+(defun org-get-at-eol (property n)
+  "Get text property PROPERTY at the end of line less N characters."
+  (get-text-property (- (point-at-eol) n) property))
 
 (defun org-find-text-property-in-string (prop s)
   "Return the first non-nil value of property PROP in string S."
@@ -21291,19 +21961,9 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
       (get-text-property (or (next-single-property-change 0 prop s) 0)
                         prop s)))
 
-(defun org-display-warning (message) ;; Copied from Emacs-Muse
+(defun org-display-warning (message)
   "Display the given MESSAGE as a warning."
-  (if (fboundp 'display-warning)
-      (display-warning 'org message
-                       (if (featurep 'xemacs) 'warning :warning))
-    (let ((buf (get-buffer-create "*Org warnings*")))
-      (with-current-buffer buf
-        (goto-char (point-max))
-        (insert "Warning (Org): " message)
-        (unless (bolp)
-          (newline)))
-      (display-buffer buf)
-      (sit-for 0))))
+  (display-warning 'org message :warning))
 
 (defun org-eval (form)
   "Eval FORM and return result."
@@ -21322,17 +21982,6 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
           (>= (match-end 0) pos)
           start))))
 
-(defun org-in-commented-line ()
-  "Is point in a line starting with `#'?"
-  (equal (char-after (point-at-bol)) ?#))
-
-(defun org-in-indented-comment-line ()
-  "Is point in a line starting with `#' after some white space?"
-  (save-excursion
-    (save-match-data
-      (goto-char (point-at-bol))
-      (looking-at "[ \t]*#"))))
-
 (defun org-in-verbatim-emphasis ()
   (save-match-data
     (and (org-in-regexp org-emph-re 2)
@@ -21340,14 +21989,35 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions."
         (<= (point) (match-end 4))
         (member (match-string 3) '("=" "~")))))
 
+(defun org-overlay-display (ovl text &optional face evap)
+  "Make overlay OVL display TEXT with face FACE."
+  (overlay-put ovl 'display text)
+  (if face (overlay-put ovl 'face face))
+  (if evap (overlay-put ovl 'evaporate t)))
+
+(defun org-overlay-before-string (ovl text &optional face evap)
+  "Make overlay OVL display TEXT with face FACE."
+  (if face (org-add-props text nil 'face face))
+  (overlay-put ovl 'before-string text)
+  (if evap (overlay-put ovl 'evaporate t)))
+
+(defun org-find-overlays (prop &optional pos delete)
+  "Find all overlays specifying PROP at POS or point.
+If DELETE is non-nil, delete all those overlays."
+  (let (found)
+    (dolist (ov (overlays-at (or pos (point))) found)
+      (cond ((not (overlay-get ov prop)))
+           (delete (delete-overlay ov))
+           (t (push ov found))))))
+
 (defun org-goto-marker-or-bmk (marker &optional bookmark)
   "Go to MARKER, widen if necessary.  When marker is not live, try BOOKMARK."
   (if (and marker (marker-buffer marker)
           (buffer-live-p (marker-buffer marker)))
       (progn
-       (org-pop-to-buffer-same-window (marker-buffer marker))
-       (if (or (> marker (point-max)) (< marker (point-min)))
-           (widen))
+       (pop-to-buffer-same-window (marker-buffer marker))
+       (when (or (> marker (point-max)) (< marker (point-min)))
+         (widen))
        (goto-char marker)
        (org-show-context 'org-goto))
     (if bookmark
@@ -21390,7 +22060,7 @@ upon the next fontification round."
     l))
 
 (defun org-shorten-string (s maxlength)
-  "Shorten string S so tht it is no longer than MAXLENGTH characters.
+  "Shorten string S so that it is no longer than MAXLENGTH characters.
 If the string is shorter or has length MAXLENGTH, just return the
 original string.  If it is longer, the functions finds a space in the
 string, breaks this string off at that locations and adds three dots
@@ -21410,8 +22080,8 @@ if necessary."
   "Get the indentation of the current line, interpreting tabs.
 When LINE is given, assume it represents a line and compute its indentation."
   (if line
-      (if (string-match "^ *" (org-remove-tabs line))
-         (match-end 0))
+      (when (string-match "^ *" (org-remove-tabs line))
+       (match-end 0))
     (save-excursion
       (beginning-of-line 1)
       (skip-chars-forward " \t")
@@ -21448,35 +22118,45 @@ leave it alone.  If it is larger than ind, set it to 
the target."
   (let* ((l (org-remove-tabs line))
         (i (org-get-indentation l))
         (i1 (car ind)) (i2 (cdr ind)))
-    (if (>= i i2) (setq l (substring line i2)))
+    (when (>= i i2) (setq l (substring line i2)))
     (if (> i1 0)
        (concat (make-string i1 ?\ ) l)
       l)))
 
 (defun org-remove-indentation (code &optional n)
-  "Remove the maximum common indentation from the lines in CODE.
-N may optionally be the number of spaces to remove."
+  "Remove maximum common indentation in string CODE and return it.
+N may optionally be the number of columns to remove.  Return CODE
+as-is if removal failed."
   (with-temp-buffer
     (insert code)
-    (org-do-remove-indentation n)
-    (buffer-string)))
+    (if (org-do-remove-indentation n) (buffer-string) code)))
 
 (defun org-do-remove-indentation (&optional n)
-  "Remove the maximum common indentation from the buffer."
-  (untabify (point-min) (point-max))
-  (let ((min 10000) re)
-    (if n
-       (setq min n)
-      (goto-char (point-min))
-      (while (re-search-forward "^ *[^ \n]" nil t)
-       (setq min (min min (1- (- (match-end 0) (match-beginning 0)))))))
-    (unless (or (= min 0) (= min 10000))
-      (setq re (format "^ \\{%d\\}" min))
-      (goto-char (point-min))
-      (while (re-search-forward re nil t)
-       (replace-match "")
-       (end-of-line 1))
-      min)))
+  "Remove the maximum common indentation from the buffer.
+When optional argument N is a positive integer, remove exactly
+that much characters from indentation, if possible.  Return nil
+if it fails."
+  (catch :exit
+    (goto-char (point-min))
+    ;; Find maximum common indentation, if not specified.
+    (let ((n (or n
+                (let ((min-ind (point-max)))
+                  (save-excursion
+                    (while (re-search-forward "^[ \t]*\\S-" nil t)
+                      (let ((ind (1- (current-column))))
+                        (if (zerop ind) (throw :exit nil)
+                          (setq min-ind (min min-ind ind))))))
+                  min-ind))))
+      (if (zerop n) (throw :exit nil)
+       ;; Remove exactly N indentation, but give up if not possible.
+       (while (not (eobp))
+         (let ((ind (progn (skip-chars-forward " \t") (current-column))))
+           (cond ((eolp) (delete-region (line-beginning-position) (point)))
+                 ((< ind n) (throw :exit nil))
+                 (t (indent-line-to (- ind n))))
+           (forward-line)))
+       ;; Signal success.
+       t))))
 
 (defun org-fill-template (template alist)
   "Find each %key of ALIST in TEMPLATE and replace it."
@@ -21496,12 +22176,6 @@ N may optionally be the number of spaces to remove."
     (or (buffer-base-buffer buffer)
        buffer)))
 
-(defun org-trim (s)
-  "Remove whitespace at beginning and end of string."
-  (if (string-match "\\`[ \t\n\r]+" s) (setq s (replace-match "" t t s)))
-  (if (string-match "[ \t\n\r]+\\'" s) (setq s (replace-match "" t t s)))
-  s)
-
 (defun org-wrap (string &optional width lines)
   "Wrap string to either a number of lines, or a width in characters.
 If WIDTH is non-nil, the string is wrapped to that width, however many lines
@@ -21539,13 +22213,12 @@ The return value is a list of lines, without newlines 
at the end."
 
 (defun org-split-string (string &optional separators)
   "Splits STRING into substrings at SEPARATORS.
+SEPARATORS is a regular expression.
 No empty strings are returned if there are matches at the beginning
 and end of string."
-  (let ((rexp (or separators "[ \f\t\n\r\v]+"))
-       (start 0)
-       notfirst
-       (list nil))
-    (while (and (string-match rexp string
+  ;; FIXME: why not use (split-string STRING SEPARATORS t)?
+  (let ((start 0) notfirst list)
+    (while (and (string-match (or separators "[ \f\t\n\r\v]+") string
                              (if (and notfirst
                                       (= start (match-beginning 0))
                                       (< start (length string)))
@@ -21555,14 +22228,10 @@ and end of string."
       (or (eq (match-beginning 0) 0)
          (and (eq (match-beginning 0) (match-end 0))
               (eq (match-beginning 0) start))
-         (setq list
-               (cons (substring string start (match-beginning 0))
-                     list)))
+         (push (substring string start (match-beginning 0)) list))
       (setq start (match-end 0)))
     (or (eq start (length string))
-       (setq list
-             (cons (substring string start)
-                   list)))
+       (push (substring string start) list))
     (nreverse list)))
 
 (defun org-quote-vert (s)
@@ -21579,10 +22248,8 @@ and end of string."
   "Whether point is in a code source block.
 When INSIDE is non-nil, don't consider we are within a src block
 when point is at #+BEGIN_SRC or #+END_SRC."
-  (let ((case-fold-search t) ov)
-    (or (and (setq ov (overlays-at (point)))
-            (memq 'org-block-background
-                  (overlay-properties (car ov))))
+  (let ((case-fold-search t))
+    (or (and (eq (get-char-property (point) 'src-block) t))
        (and (not inside)
             (save-match-data
               (save-excursion
@@ -21604,13 +22271,13 @@ contexts are:
 :item             on the first line of a plain list item
 :item-bullet      on the bullet/number of a plain list item
 :checkbox         on the checkbox in a plain list item
-:table            in an org-mode table
+:table            in an Org table
 :table-special    on a special filed in a table
 :table-table      in a table.el table
 :clocktable       in a clocktable
 :src-block        in a source block
 :link             on a hyperlink
-:keyword          on a keyword: SCHEDULED, DEADLINE, CLOSE, COMMENT, QUOTE.
+:keyword          on a keyword: SCHEDULED, DEADLINE, CLOSE, COMMENT.
 :target           on a <<target>>
 :radio-target     on a <<<radio-target>>>
 :latex-fragment   on a LaTeX fragment
@@ -21635,8 +22302,8 @@ and :keyword."
        (push (org-point-in-group p 4 :tags) clist))
       (goto-char p)
       (skip-chars-backward "^[\n\r \t") (or (bobp) (backward-char 1))
-      (if (looking-at "\\[#[A-Z0-9]\\]")
-         (push (org-point-in-group p 0 :priority) clist)))
+      (when (looking-at "\\[#[A-Z0-9]\\]")
+       (push (org-point-in-group p 0 :priority) clist)))
 
      ((org-at-item-p)
       (push (org-point-in-group p 2 :item-bullet) clist)
@@ -21648,10 +22315,10 @@ and :keyword."
 
      ((org-at-table-p)
       (push (list :table (org-table-begin) (org-table-end)) clist)
-      (if (memq 'org-formula faces)
-         (push (list :table-special
-                     (previous-single-property-change p 'face)
-                     (next-single-property-change p 'face)) clist)))
+      (when (memq 'org-formula faces)
+       (push (list :table-special
+                   (previous-single-property-change p 'face)
+                   (next-single-property-change p 'face)) clist)))
      ((org-at-table-p 'any)
       (push (list :table-table) clist)))
     (goto-char p)
@@ -21660,16 +22327,16 @@ and :keyword."
       ;; New the "medium" contexts: clocktables, source blocks
       (cond ((org-in-clocktable-p)
             (push (list :clocktable
-                        (and (or (looking-at "#\\+BEGIN: clocktable")
-                                 (search-backward "#+BEGIN: clocktable" nil t))
-                             (match-beginning 0))
-                        (and (re-search-forward "#\\+END:?" nil t)
+                        (and (or (looking-at "[ \t]*\\(#\\+BEGIN: 
clocktable\\)")
+                                 (re-search-backward "[ \t]*\\(#+BEGIN: 
clocktable\\)" nil t))
+                             (match-beginning 1))
+                        (and (re-search-forward "[ \t]*#\\+END:?" nil t)
                              (match-end 0))) clist))
            ((org-in-src-block-p)
             (push (list :src-block
-                        (and (or (looking-at "#\\+BEGIN_SRC")
-                                 (search-backward "#+BEGIN_SRC" nil t))
-                             (match-beginning 0))
+                        (and (or (looking-at "[ \t]*\\(#\\+BEGIN_SRC\\)")
+                                 (re-search-backward "[ \t]*\\(#+BEGIN_SRC\\)" 
nil t))
+                             (match-beginning 1))
                         (and (search-forward "#+END_SRC" nil t)
                              (match-beginning 0))) clist))))
     (goto-char p)
@@ -21689,14 +22356,14 @@ and :keyword."
      ((org-at-target-p)
       (push (org-point-in-group p 0 :target) clist)
       (goto-char (1- (match-beginning 0)))
-      (if (looking-at org-radio-target-regexp)
-         (push (org-point-in-group p 0 :radio-target) clist))
+      (when (looking-at org-radio-target-regexp)
+       (push (org-point-in-group p 0 :radio-target) clist))
       (goto-char p))
-     ((setq o (car (delq nil
-                        (mapcar
-                         (lambda (x)
-                           (if (memq x org-latex-fragment-image-overlays) x))
-                         (overlays-at (point))))))
+     ((setq o (cl-some
+              (lambda (o)
+                (and (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)
+                     o))
+              (overlays-at (point))))
       (push (list :latex-fragment
                  (overlay-start o) (overlay-end o)) clist)
       (push (list :latex-preview
@@ -21708,35 +22375,27 @@ and :keyword."
     (setq clist (nreverse (delq nil clist)))
     clist))
 
-;; FIXME: Compare with at-regexp-p Do we need both?
-(defun org-in-regexp (re &optional nlines visually)
-  "Check if point is inside a match of regexp.
-Normally only the current line is checked, but you can include NLINES extra
-lines both before and after point into the search.
-If VISUALLY is set, require that the cursor is not after the match but
-really on, so that the block visually is on the match."
-  (catch 'exit
+(defun org-in-regexp (regexp &optional nlines visually)
+  "Check if point is inside a match of REGEXP.
+
+Normally only the current line is checked, but you can include
+NLINES extra lines around point into the search.  If VISUALLY is
+set, require that the cursor is not after the match but really
+on, so that the block visually is on the match.
+
+Return nil or a cons cell (BEG . END) where BEG and END are,
+respectively, the positions at the beginning and the end of the
+match."
+  (catch :exit
     (let ((pos (point))
-          (eol (point-at-eol (+ 1 (or nlines 0))))
-         (inc (if visually 1 0)))
+          (eol (line-end-position (if nlines (1+ nlines) 1))))
       (save-excursion
        (beginning-of-line (- 1 (or nlines 0)))
-       (while (re-search-forward re eol t)
-         (if (and (<= (match-beginning 0) pos)
-                  (>= (+ inc (match-end 0)) pos))
-             (throw 'exit (cons (match-beginning 0) (match-end 0)))))))))
-
-(defun org-at-regexp-p (regexp)
-  "Is point inside a match of REGEXP in the current line?"
-  (catch 'exit
-    (save-excursion
-      (let ((pos (point)) (end (point-at-eol)))
-       (beginning-of-line 1)
-       (while (re-search-forward regexp end t)
-         (if (and (<= (match-beginning 0) pos)
-                  (>= (match-end 0) pos))
-             (throw 'exit t)))
-       nil))))
+       (while (and (re-search-forward regexp eol t)
+                   (<= (match-beginning 0) pos))
+         (let ((end (match-end 0)))
+           (when (or (> end pos) (and (= end pos) (not visually)))
+             (throw :exit (cons (match-beginning 0) (match-end 0))))))))))
 
 (defun org-between-regexps-p (start-re end-re &optional lim-up lim-down)
   "Non-nil when point is between matches of START-RE and END-RE.
@@ -21757,7 +22416,7 @@ position before START-RE (resp. after END-RE)."
       (save-excursion
        ;; Point is on a block when on START-RE or if START-RE can be
        ;; found before it...
-       (and (or (org-at-regexp-p start-re)
+       (and (or (org-in-regexp start-re)
                 (re-search-backward start-re limit-up t))
             (setq beg (match-beginning 0))
             ;; ... and END-RE after it...
@@ -21783,27 +22442,15 @@ block from point."
       (let ((case-fold-search t)
            (lim-up (save-excursion (outline-previous-heading)))
            (lim-down (save-excursion (outline-next-heading))))
-       (mapc (lambda (name)
-               (let ((n (regexp-quote name)))
-                 (when (org-between-regexps-p
-                        (concat "^[ \t]*#\\+begin_" n)
-                        (concat "^[ \t]*#\\+end_" n)
-                        lim-up lim-down)
-                   (throw 'exit n))))
-             names))
+       (dolist (name names)
+         (let ((n (regexp-quote name)))
+           (when (org-between-regexps-p
+                  (concat "^[ \t]*#\\+begin_" n)
+                  (concat "^[ \t]*#\\+end_" n)
+                  lim-up lim-down)
+             (throw 'exit n)))))
       nil)))
 
-(defun org-in-drawer-p ()
-  "Is point within a drawer?"
-  (save-match-data
-    (let ((case-fold-search t)
-         (lim-up (save-excursion (outline-previous-heading)))
-         (lim-down (save-excursion (outline-next-heading))))
-      (org-between-regexps-p
-       (concat "^[ \t]*:" (regexp-opt org-drawers) ":")
-       "^[ \t]*:end:.*$"
-       lim-up lim-down))))
-
 (defun org-occur-in-agenda-files (regexp &optional _nlines)
   "Call `multi-occur' with buffers for all agenda files."
   (interactive "sOrg-files matching: ")
@@ -21815,40 +22462,21 @@ block from point."
       (setq files (org-add-archive-files files)))
     (dolist (f extra)
       (unless (member (file-truename f) tnames)
-        (unless (member f files) (setq files (append files (list f))))
-        (setq tnames (append tnames (list (file-truename f))))))
+       (unless (member f files) (setq files (append files (list f))))
+       (setq tnames (append tnames (list (file-truename f))))))
     (multi-occur
      (mapcar (lambda (x)
               (with-current-buffer
-                   ;; FIXME: Why not just (find-file-noselect x)?
-                   ;; Is it to avoid the "revert buffer" prompt?
+                  ;; FIXME: Why not just (find-file-noselect x)?
+                  ;; Is it to avoid the "revert buffer" prompt?
                   (or (get-file-buffer x) (find-file-noselect x))
                 (widen)
                 (current-buffer)))
             files)
      regexp)))
 
-(if (boundp 'occur-mode-find-occurrence-hook)
-    ;; Emacs 23
-    (add-hook 'occur-mode-find-occurrence-hook
-             (lambda ()
-               (when (derived-mode-p 'org-mode)
-                 (org-reveal))))
-  ;; Emacs 22
-  (defadvice occur-mode-goto-occurrence
-    (after org-occur-reveal activate)
-    (and (derived-mode-p 'org-mode) (org-reveal)))
-  (defadvice occur-mode-goto-occurrence-other-window
-    (after org-occur-reveal activate)
-    (and (derived-mode-p 'org-mode) (org-reveal)))
-  (defadvice occur-mode-display-occurrence
-    (after org-occur-reveal activate)
-    (when (derived-mode-p 'org-mode)
-      (let ((pos (occur-mode-find-occurrence)))
-       (with-current-buffer (marker-buffer pos)
-         (save-excursion
-           (goto-char pos)
-           (org-reveal)))))))
+(add-hook 'occur-mode-find-occurrence-hook
+         (lambda () (when (derived-mode-p 'org-mode) (org-reveal))))
 
 (defun org-occur-link-in-agenda-files ()
   "Create a link and search for it in the agendas.
@@ -21878,81 +22506,27 @@ merge (a 1) and (a 3) into (a 1 3).
 
 The function returns the new ALIST."
   (let (rtn)
-    (mapc
-     (lambda (e)
-       (let (n)
-        (if (not (assoc (car e) rtn))
-            (push e rtn)
-          (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e))))
-          (setq rtn (assq-delete-all (car e) rtn))
-          (push n rtn))))
-         alist)
-    rtn))
+    (dolist (e alist rtn)
+      (let (n)
+       (if (not (assoc (car e) rtn))
+           (push e rtn)
+         (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e))))
+         (setq rtn (assq-delete-all (car e) rtn))
+         (push n rtn))))))
 
 (defun org-delete-all (elts list)
-  "Remove all elements in ELTS from LIST."
+  "Remove all elements in ELTS from LIST.
+Comparison is done with `equal'.  It is a destructive operation
+that may remove elements by altering the list structure."
   (while elts
     (setq list (delete (pop elts) list)))
   list)
 
-(defun org-count (cl-item cl-seq)
-  "Count the number of occurrences of ITEM in SEQ.
-Taken from `count' in cl-seq.el with all keyword arguments removed."
-  (let ((cl-end (length cl-seq)) (cl-start 0) (cl-count 0)  cl-x)
-    (when (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq)))
-    (while (< cl-start cl-end)
-      (setq cl-x (if (consp cl-seq) (pop cl-seq) (aref cl-seq cl-start)))
-      (if (equal cl-item cl-x) (setq cl-count (1+ cl-count)))
-      (setq cl-start (1+ cl-start)))
-    cl-count))
-
-(defun org-remove-if (predicate seq)
-  "Remove everything from SEQ that fulfills PREDICATE."
-  (let (res e)
-    (while seq
-      (setq e (pop seq))
-      (if (not (funcall predicate e)) (push e res)))
-    (nreverse res)))
-
-(defun org-remove-if-not (predicate seq)
-  "Remove everything from SEQ that does not fulfill PREDICATE."
-  (let (res e)
-    (while seq
-      (setq e (pop seq))
-      (if (funcall predicate e) (push e res)))
-    (nreverse res)))
-
-(defun org-reduce (cl-func cl-seq &rest cl-keys)
-  "Reduce two-argument FUNCTION across SEQ.
-Taken from `reduce' in cl-seq.el with all keyword arguments but
-\":initial-value\" removed."
-  (let ((cl-accum (cond ((memq :initial-value cl-keys)
-                         (cadr (memq :initial-value cl-keys)))
-                        (cl-seq (pop cl-seq))
-                        (t (funcall cl-func)))))
-    (while cl-seq
-      (setq cl-accum (funcall cl-func cl-accum (pop cl-seq))))
-    cl-accum))
-
-(defun org-every (pred seq)
-  "Return true if PREDICATE is true of every element of SEQ.
-Adapted from `every' in cl.el."
-  (catch 'org-every
-    (mapc (lambda (e) (unless (funcall pred e) (throw 'org-every nil))) seq)
-    t))
-
-(defun org-some (pred seq)
-  "Return true if PREDICATE is true of any element of SEQ.
-Adapted from `some' in cl.el."
-  (catch 'org-some
-    (mapc (lambda (e) (when (funcall pred e) (throw 'org-some t))) seq)
-    nil))
-
 (defun org-back-over-empty-lines ()
   "Move backwards over whitespace, to the beginning of the first empty line.
 Returns the number of empty lines passed."
   (let ((pos (point)))
-    (if (cdr (assoc 'heading org-blank-before-new-entry))
+    (if (cdr (assq 'heading org-blank-before-new-entry))
        (skip-chars-backward " \t\n\r")
       (unless (eobp)
        (forward-line -1)))
@@ -22005,7 +22579,7 @@ so values can contain further %-escapes if they are 
define later in TABLE."
   (let ((tbl (copy-alist table))
        (case-fold-search nil)
         (pchg 0)
-        e re rpl)
+        re rpl)
     (dolist (e tbl)
       (setq re (concat "%-?[0-9.]*" (substring (car e) 1)))
       (when (and (cdr e) (string-match re (cdr e)))
@@ -22023,16 +22597,6 @@ so values can contain further %-escapes if they are 
define later in TABLE."
          (setq string (replace-match sref t t string)))))
     string))
 
-(defun org-sublist (list start end)
-  "Return a section of LIST, from START to END.
-Counting starts at 1."
-  (let (rtn (c start))
-    (setq list (nthcdr (1- start) list))
-    (while (and list (<= c end))
-      (push (pop list) rtn)
-      (setq c (1+ c)))
-    (nreverse rtn)))
-
 (defun org-find-base-buffer-visiting (file)
   "Like `find-buffer-visiting' but always return the base buffer and
 not an indirect buffer."
@@ -22042,26 +22606,12 @@ not an indirect buffer."
        (or (buffer-base-buffer buf) buf)
       nil)))
 
-(defun org-image-file-name-regexp (&optional extensions)
-  "Return regexp matching the file names of images.
-If EXTENSIONS is given, only match these."
-  (if (and (not extensions) (fboundp 'image-file-name-regexp))
-      (image-file-name-regexp)
-    (let ((image-file-name-extensions
-          (or extensions
-              '("png" "jpeg" "jpg" "gif" "tiff" "tif"
-                "xbm" "xpm" "pbm" "pgm" "ppm"))))
-      (concat "\\."
-             (regexp-opt (nconc (mapcar 'upcase
-                                        image-file-name-extensions)
-                                image-file-name-extensions)
-                         t)
-             "\\'"))))
-
-(defun org-file-image-p (file &optional extensions)
+;;; TODO: Only called once, from ox-odt which should probably use
+;;; org-export-inline-image-p or something.
+(defun org-file-image-p (file)
   "Return non-nil if FILE is an image."
   (save-match-data
-    (string-match (org-image-file-name-regexp extensions) file)))
+    (string-match (image-file-name-regexp) file)))
 
 (defun org-get-cursor-date (&optional with-time)
   "Return the date at cursor in as a time.
@@ -22085,10 +22635,10 @@ the agenda) or the current time of the day."
                              (nth 1 date) (nth 0 date) (nth 2 date))))
      ((eq major-mode 'org-agenda-mode)
       (setq day (get-text-property (point) 'day))
-      (if day
-         (setq date (calendar-gregorian-from-absolute day)
-               defd (encode-time 0 (or mod 0) (or hod 0)
-                                 (nth 1 date) (nth 0 date) (nth 2 date))))))
+      (when day
+       (setq date (calendar-gregorian-from-absolute day)
+             defd (encode-time 0 (or mod 0) (or hod 0)
+                               (nth 1 date) (nth 0 date) (nth 2 date))))))
     (or defd (current-time))))
 
 (defun org-mark-subtree (&optional up)
@@ -22101,177 +22651,440 @@ hierarchy of headlines by UP levels before marking 
the subtree."
    (cond ((org-at-heading-p) (beginning-of-line))
         ((org-before-first-heading-p) (user-error "Not in a subtree"))
         (t (outline-previous-visible-heading 1))))
-  (when up (while (and (> up 0) (org-up-heading-safe)) (decf up)))
-  (if (org-called-interactively-p 'any)
+  (when up (while (and (> up 0) (org-up-heading-safe)) (cl-decf up)))
+  (if (called-interactively-p 'any)
       (call-interactively 'org-mark-element)
     (org-mark-element)))
 
+(defun org-file-newer-than-p (file time)
+  "Non-nil if FILE is newer than TIME.
+FILE is a filename, as a string, TIME is a list of integers, as
+returned by, e.g., `current-time'."
+  (and (file-exists-p file)
+       ;; Only compare times up to whole seconds as some file-systems
+       ;; (e.g. HFS+) do not retain any finer granularity.  As
+       ;; a consequence, make sure we return non-nil when the two
+       ;; times are equal.
+       (not (time-less-p (cl-subseq (nth 5 (file-attributes file)) 0 2)
+                        (cl-subseq time 0 2)))))
+
+(defun org-compile-file (source process ext &optional err-msg log-buf spec)
+  "Compile a SOURCE file using PROCESS.
+
+PROCESS is either a function or a list of shell commands, as
+strings.  EXT is a file extension, without the leading dot, as
+a string.  It is used to check if the process actually succeeded.
+
+PROCESS must create a file with the same base name and directory
+as SOURCE, but ending with EXT.  The function then returns its
+filename.  Otherwise, it raises an error.  The error message can
+then be refined by providing string ERR-MSG, which is appended to
+the standard message.
+
+If PROCESS is a function, it is called with a single argument:
+the SOURCE file.
+
+If it is a list of commands, each of them is called using
+`shell-command'.  By default, in each command, %b, %f, %F, %o and
+%O are replaced with, respectively, SOURCE base name, name, full
+name, directory and absolute output file name.  It is possible,
+however, to use more place-holders by specifying them in optional
+argument SPEC, as an alist following the pattern
+
+  (CHARACTER . REPLACEMENT-STRING).
+
+When PROCESS is a list of commands, optional argument LOG-BUF can
+be set to a buffer or a buffer name.  `shell-command' then uses
+it for output."
+  (let* ((base-name (file-name-base source))
+        (full-name (file-truename source))
+        (out-dir (or (file-name-directory source) "./"))
+        (output (expand-file-name (concat base-name "." ext) out-dir))
+        (time (current-time))
+        (err-msg (if (stringp err-msg) (concat ".  " err-msg) "")))
+    (save-window-excursion
+      (pcase process
+       ((pred functionp) (funcall process (shell-quote-argument source)))
+       ((pred consp)
+        (let ((log-buf (and log-buf (get-buffer-create log-buf)))
+              (spec (append spec
+                            `((?b . ,(shell-quote-argument base-name))
+                              (?f . ,(shell-quote-argument source))
+                              (?F . ,(shell-quote-argument full-name))
+                              (?o . ,(shell-quote-argument out-dir))
+                              (?O . ,(shell-quote-argument output))))))
+          (dolist (command process)
+            (shell-command (format-spec command spec) log-buf))))
+       (_ (error "No valid command to process %S%s" source err-msg))))
+    ;; Check for process failure.  Output file is expected to be
+    ;; located in the same directory as SOURCE.
+    (unless (org-file-newer-than-p output time)
+      (error (format "File %S wasn't produced%s" output err-msg)))
+    output))
 
 ;;; Indentation
 
+(defvar org-element-greater-elements)
+(defun org--get-expected-indentation (element contentsp)
+  "Expected indentation column for current line, according to ELEMENT.
+ELEMENT is an element containing point.  CONTENTSP is non-nil
+when indentation is to be computed according to contents of
+ELEMENT."
+  (let ((type (org-element-type element))
+       (start (org-element-property :begin element))
+       (post-affiliated (org-element-property :post-affiliated element)))
+    (org-with-wide-buffer
+     (cond
+      (contentsp
+       (cl-case type
+        ((diary-sexp footnote-definition) 0)
+        ((headline inlinetask nil)
+         (if (not org-adapt-indentation) 0
+           (let ((level (org-current-level)))
+             (if level (1+ level) 0))))
+        ((item plain-list) (org-list-item-body-column post-affiliated))
+        (t
+         (goto-char start)
+         (org-get-indentation))))
+      ((memq type '(headline inlinetask nil))
+       (if (org-match-line "[ \t]*$")
+          (org--get-expected-indentation element t)
+        0))
+      ((memq type '(diary-sexp footnote-definition)) 0)
+      ;; First paragraph of a footnote definition or an item.
+      ;; Indent like parent.
+      ((< (line-beginning-position) start)
+       (org--get-expected-indentation
+       (org-element-property :parent element) t))
+      ;; At first line: indent according to previous sibling, if any,
+      ;; ignoring footnote definitions and inline tasks, or parent's
+      ;; contents.
+      ((= (line-beginning-position) start)
+       (catch 'exit
+        (while t
+          (if (= (point-min) start) (throw 'exit 0)
+            (goto-char (1- start))
+            (let* ((previous (org-element-at-point))
+                   (parent previous))
+              (while (and parent (<= (org-element-property :end parent) start))
+                (setq previous parent
+                      parent (org-element-property :parent parent)))
+              (cond
+               ((not previous) (throw 'exit 0))
+               ((> (org-element-property :end previous) start)
+                (throw 'exit (org--get-expected-indentation previous t)))
+               ((memq (org-element-type previous)
+                      '(footnote-definition inlinetask))
+                (setq start (org-element-property :begin previous)))
+               (t (goto-char (org-element-property :begin previous))
+                  (throw 'exit
+                         (if (bolp) (org-get-indentation)
+                           ;; At first paragraph in an item or
+                           ;; a footnote definition.
+                           (org--get-expected-indentation
+                            (org-element-property :parent previous) t))))))))))
+      ;; Otherwise, move to the first non-blank line above.
+      (t
+       (beginning-of-line)
+       (let ((pos (point)))
+        (skip-chars-backward " \r\t\n")
+        (cond
+         ;; Two blank lines end a footnote definition or a plain
+         ;; list.  When we indent an empty line after them, the
+         ;; containing list or footnote definition is over, so it
+         ;; qualifies as a previous sibling.  Therefore, we indent
+         ;; like its first line.
+         ((and (memq type '(footnote-definition plain-list))
+               (> (count-lines (point) pos) 2))
+          (goto-char start)
+          (org-get-indentation))
+         ;; Line above is the first one of a paragraph at the
+         ;; beginning of an item or a footnote definition.  Indent
+         ;; like parent.
+         ((< (line-beginning-position) start)
+          (org--get-expected-indentation
+           (org-element-property :parent element) t))
+         ;; Line above is the beginning of an element, i.e., point
+         ;; was originally on the blank lines between element's start
+         ;; and contents.
+         ((= (line-beginning-position) post-affiliated)
+          (org--get-expected-indentation element t))
+         ;; POS is after contents in a greater element.  Indent like
+         ;; the beginning of the element.
+         ((and (memq type org-element-greater-elements)
+               (let ((cend (org-element-property :contents-end element)))
+                 (and cend (<= cend pos))))
+          ;; As a special case, if point is at the end of a footnote
+          ;; definition or an item, indent like the very last element
+          ;; within.  If that last element is an item, indent like
+          ;; its contents.
+          (if (memq type '(footnote-definition item plain-list))
+              (let ((last (org-element-at-point)))
+                (goto-char pos)
+                (org--get-expected-indentation
+                 last (eq (org-element-type last) 'item)))
+            (goto-char start)
+            (org-get-indentation)))
+         ;; In any other case, indent like the current line.
+         (t (org-get-indentation)))))))))
+
+(defun org--align-node-property ()
+  "Align node property at point.
+Alignment is done according to `org-property-format', which see."
+  (when (save-excursion
+         (beginning-of-line)
+         (looking-at org-property-re))
+    (replace-match
+     (concat (match-string 4)
+            (org-trim
+             (format org-property-format (match-string 1) (match-string 3))))
+     t t)))
+
 (defun org-indent-line ()
-  "Indent line depending on context."
+  "Indent line depending on context.
+
+Indentation is done according to the following rules:
+
+  - Footnote definitions, diary sexps, headlines and inline tasks
+    have to start at column 0.
+
+  - On the very first line of an element, consider, in order, the
+    next rules until one matches:
+
+    1. If there's a sibling element before, ignoring footnote
+       definitions and inline tasks, indent like its first line.
+
+    2. If element has a parent, indent like its contents.  More
+       precisely, if parent is an item, indent after the
+       description part, if any, or the bullet (see
+       `org-list-description-max-indent').  Else, indent like
+       parent's first line.
+
+    3. Otherwise, indent relatively to current level, if
+       `org-adapt-indentation' is non-nil, or to left margin.
+
+  - On a blank line at the end of an element, indent according to
+    the type of the element.  More precisely
+
+    1. If element is a plain list, an item, or a footnote
+       definition, indent like the very last element within.
+
+    2. If element is a paragraph, indent like its last non blank
+       line.
+
+    3. Otherwise, indent like its very first line.
+
+  - In the code part of a source block, use language major mode
+    to indent current line if `org-src-tab-acts-natively' is
+    non-nil.  If it is nil, do nothing.
+
+  - Otherwise, indent like the first non-blank line above.
+
+The function doesn't indent an item as it could break the whole
+list structure.  Instead, use \\<org-mode-map>`\\[org-shiftmetaleft]' or \
+`\\[org-shiftmetaright]'.
+
+Also align node properties according to `org-property-format'."
   (interactive)
-  (let* ((pos (point))
-        (itemp (org-at-item-p))
-        (case-fold-search t)
-        (org-drawer-regexp (or org-drawer-regexp "\000"))
-        (inline-task-p (and (featurep 'org-inlinetask)
-                            (org-inlinetask-in-task-p)))
-        (inline-re (and inline-task-p
-                        (org-inlinetask-outline-regexp)))
-        column)
-    (if (and orgstruct-is-++ (eq pos (point)))
-       (let ((indent-line-function (cadadr (assoc 'indent-line-function 
org-fb-vars))))
-         (indent-according-to-mode))
-      (beginning-of-line 1)
-      (cond
-       ;; Headings
-       ((looking-at org-outline-regexp) (setq column 0))
-       ;; Footnote definition
-       ((looking-at org-footnote-definition-re) (setq column 0))
-       ;; Literal examples
-       ((looking-at "[ \t]*:\\( \\|$\\)")
-       (setq column (org-get-indentation))) ; do nothing
-       ;; Lists
-       ((ignore-errors (goto-char (org-in-item-p)))
-       (setq column (if itemp
-                        (org-get-indentation)
-                      (org-list-item-body-column (point))))
-       (goto-char pos))
-       ;; Drawers
-       ((and (looking-at "[ \t]*:END:")
-            (save-excursion (re-search-backward org-drawer-regexp nil t)))
-       (save-excursion
-         (goto-char (1- (match-beginning 1)))
-         (setq column (current-column))))
-       ;; Special blocks
-       ((and (looking-at "[ \t]*#\\+end_\\([a-z]+\\)")
-            (save-excursion
-              (re-search-backward
-               (concat "^[ \t]*#\\+begin_" (downcase (match-string 1))) nil 
t)))
-       (setq column (org-get-indentation (match-string 0))))
-       ((and (not (looking-at "[ \t]*#\\+begin_"))
-            (org-between-regexps-p "^[ \t]*#\\+begin_" "[ \t]*#\\+end_"))
-       (save-excursion
-         (re-search-backward "^[ \t]*#\\+begin_\\([a-z]+\\)" nil t))
-       (setq column
-             (cond ((equal (downcase (match-string 1)) "src")
-                    ;; src blocks: let `org-edit-src-exit' handle them
-                    (org-get-indentation))
-                   ((equal (downcase (match-string 1)) "example")
-                    (max (org-get-indentation)
-                         (org-get-indentation (match-string 0))))
-                   (t
-                    (org-get-indentation (match-string 0))))))
-       ;; This line has nothing special, look at the previous relevant
-       ;; line to compute indentation
-       (t
-       (beginning-of-line 0)
-       (while (and (not (bobp))
-                   (not (looking-at org-table-line-regexp))
-                   (not (looking-at org-drawer-regexp))
-                   ;; When point started in an inline task, do not move
-                   ;; above task starting line.
-                   (not (and inline-task-p (looking-at inline-re)))
-                   ;; Skip drawers, blocks, empty lines, verbatim,
-                   ;; comments, tables, footnotes definitions, lists,
-                   ;; inline tasks.
-                   (or (and (looking-at "[ \t]*:END:")
-                            (re-search-backward org-drawer-regexp nil t))
-                       (and (looking-at "[ \t]*#\\+end_")
-                            (re-search-backward "[ \t]*#\\+begin_"nil t))
-                       (looking-at "[ \t]*[\n:#|]")
-                       (looking-at org-footnote-definition-re)
-                       (and (not inline-task-p)
-                            (featurep 'org-inlinetask)
-                            (org-inlinetask-in-task-p)
-                            (or (org-inlinetask-goto-beginning) t))))
-         (beginning-of-line 0))
-       (cond
-        ;; There was a list item above.
-        ((ignore-errors (goto-char (org-in-item-p)))
-         (goto-char (org-list-get-top-point (org-list-struct)))
-         (setq column (org-get-indentation)))
-        ;; There was an heading above.
-        ((looking-at "\\*+[ \t]+")
-         (if (not org-adapt-indentation)
-             (setq column 0)
-           (goto-char (match-end 0))
-           (setq column (current-column))))
-        ;; A drawer had started and is unfinished
-        ((looking-at org-drawer-regexp)
-         (goto-char (1- (match-beginning 1)))
-         (setq column (current-column)))
-        ;; Else, nothing noticeable found: get indentation and go on.
-        (t (setq column (org-get-indentation))))))
-      ;; Now apply indentation and move cursor accordingly
-      (goto-char pos)
-      (if (<= (current-column) (current-indentation))
-         (org-indent-line-to column)
-       (save-excursion (org-indent-line-to column)))
-      ;; Special polishing for properties, see `org-property-format'
-      (setq column (current-column))
-      (beginning-of-line 1)
-      (if (looking-at org-property-re)
-         (replace-match (concat (match-string 4)
-                                (format org-property-format
-                                        (match-string 1) (match-string 3)))
-                        t t))
-      (org-move-to-column column))))
+  (cond
+   (orgstruct-is-++
+    (let ((indent-line-function
+          (cl-cadadr (assq 'indent-line-function org-fb-vars))))
+      (indent-according-to-mode)))
+   ((org-at-heading-p) 'noindent)
+   (t
+    (let* ((element (save-excursion (beginning-of-line) 
(org-element-at-point)))
+          (type (org-element-type element)))
+      (cond ((and (memq type '(plain-list item))
+                 (= (line-beginning-position)
+                    (org-element-property :post-affiliated element)))
+            'noindent)
+           ((and (eq type 'latex-environment)
+                 (>= (point) (org-element-property :post-affiliated element))
+                 (< (point) (org-with-wide-buffer
+                             (goto-char (org-element-property :end element))
+                             (skip-chars-backward " \r\t\n")
+                             (line-beginning-position 2))))
+            'noindent)
+           ((and (eq type 'src-block)
+                 org-src-tab-acts-natively
+                 (> (line-beginning-position)
+                    (org-element-property :post-affiliated element))
+                 (< (line-beginning-position)
+                    (org-with-wide-buffer
+                     (goto-char (org-element-property :end element))
+                     (skip-chars-backward " \r\t\n")
+                     (line-beginning-position))))
+            (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))
+           (t
+            (let ((column (org--get-expected-indentation element nil)))
+              ;; Preserve current column.
+              (if (<= (current-column) (current-indentation))
+                  (indent-line-to column)
+                (save-excursion (indent-line-to column))))
+            ;; Align node property.  Also preserve current column.
+            (when (eq type 'node-property)
+              (let ((column (current-column)))
+                (org--align-node-property)
+                (org-move-to-column column)))))))))
+
+(defun org-indent-region (start end)
+  "Indent each non-blank line in the region.
+Called from a program, START and END specify the region to
+indent.  The function will not indent contents of example blocks,
+verse blocks and export blocks as leading white spaces are
+assumed to be significant there."
+  (interactive "r")
+  (save-excursion
+    (goto-char start)
+    (skip-chars-forward " \r\t\n")
+    (unless (eobp) (beginning-of-line))
+    (let ((indent-to
+          (lambda (ind pos)
+            ;; Set IND as indentation for all lines between point and
+            ;; POS.  Blank lines are ignored.  Leave point after POS
+            ;; once done.
+            (let ((limit (copy-marker pos)))
+              (while (< (point) limit)
+                (unless (looking-at-p "[ \t]*$") (indent-line-to ind))
+                (forward-line))
+              (set-marker limit nil))))
+         (end (copy-marker end)))
+      (while (< (point) end)
+       (if (or (looking-at-p " \r\t\n") (org-at-heading-p)) (forward-line)
+         (let* ((element (org-element-at-point))
+                (type (org-element-type element))
+                (element-end (copy-marker (org-element-property :end element)))
+                (ind (org--get-expected-indentation element nil)))
+           (cond
+            ;; Element indented as a single block.  Example blocks
+            ;; preserving indentation are a special case since the
+            ;; "contents" must not be indented whereas the block
+            ;; boundaries can.
+            ((or (memq type '(export-block latex-environment))
+                 (and (eq type 'example-block)
+                      (not
+                       (or org-src-preserve-indentation
+                           (org-element-property :preserve-indent element)))))
+             (let ((offset (- ind (org-get-indentation))))
+               (unless (zerop offset)
+                 (indent-rigidly (org-element-property :begin element)
+                                 (org-element-property :end element)
+                                 offset)))
+             (goto-char element-end))
+            ;; Elements indented line wise.  Be sure to exclude
+            ;; example blocks (preserving indentation) and source
+            ;; blocks from this category as they are treated
+            ;; specially later.
+            ((or (memq type '(paragraph table table-row))
+                 (not (or (org-element-property :contents-begin element)
+                          (memq type '(example-block src-block)))))
+             (when (eq type 'node-property)
+               (org--align-node-property)
+               (beginning-of-line))
+             (funcall indent-to ind (min element-end end)))
+            ;; Elements consisting of three parts: before the
+            ;; contents, the contents, and after the contents.  The
+            ;; contents are treated specially, according to the
+            ;; element type, or not indented at all.  Other parts are
+            ;; indented as a single block.
+            (t
+             (let* ((post (copy-marker
+                           (org-element-property :post-affiliated element)))
+                    (cbeg
+                     (copy-marker
+                      (cond
+                       ((not (org-element-property :contents-begin element))
+                        ;; Fake contents for source blocks.
+                        (org-with-wide-buffer
+                         (goto-char post)
+                         (line-beginning-position 2)))
+                       ((memq type '(footnote-definition item plain-list))
+                        ;; Contents in these elements could start on
+                        ;; the same line as the beginning of the
+                        ;; element.  Make sure we start indenting
+                        ;; from the second line.
+                        (org-with-wide-buffer
+                         (goto-char post)
+                         (end-of-line)
+                         (skip-chars-forward " \r\t\n")
+                         (if (eobp) (point) (line-beginning-position))))
+                       (t (org-element-property :contents-begin element)))))
+                    (cend (copy-marker
+                           (or (org-element-property :contents-end element)
+                               ;; Fake contents for source blocks.
+                               (org-with-wide-buffer
+                                (goto-char element-end)
+                                (skip-chars-backward " \r\t\n")
+                                (line-beginning-position)))
+                           t)))
+               ;; Do not change items indentation individually as it
+               ;; might break the list as a whole.  On the other
+               ;; hand, when at a plain list, indent it as a whole.
+               (cond ((eq type 'plain-list)
+                      (let ((offset (- ind (org-get-indentation))))
+                        (unless (zerop offset)
+                          (indent-rigidly (org-element-property :begin element)
+                                          (org-element-property :end element)
+                                          offset))
+                        (goto-char cbeg)))
+                     ((eq type 'item) (goto-char cbeg))
+                     (t (funcall indent-to ind (min cbeg end))))
+               (when (< (point) end)
+                 (cl-case type
+                   ((example-block verse-block))
+                   (src-block
+                    ;; In a source block, indent source code
+                    ;; according to language major mode, but only if
+                    ;; `org-src-tab-acts-natively' is non-nil.
+                    (when (and (< (point) end) org-src-tab-acts-natively)
+                      (ignore-errors
+                        (org-babel-do-in-edit-buffer
+                         (indent-region (point-min) (point-max))))))
+                   (t (org-indent-region (point) (min cend end))))
+                 (goto-char (min cend end))
+                 (when (< (point) end)
+                   (funcall indent-to ind (min element-end end))))
+               (set-marker post nil)
+               (set-marker cbeg nil)
+               (set-marker cend nil))))
+           (set-marker element-end nil))))
+      (set-marker end nil))))
 
 (defun org-indent-drawer ()
   "Indent the drawer at point."
   (interactive)
-  (let ((p (point))
-       (e (and (save-excursion (re-search-forward ":END:" nil t))
-               (match-end 0)))
-       (folded
-        (save-excursion
-          (end-of-line)
-          (when (overlays-at (point))
-            (member 'invisible (overlay-properties
-                                (car (overlays-at (point)))))))))
-    (when folded (org-cycle))
-    (indent-for-tab-command)
-    (while (and (move-beginning-of-line 2) (< (point) e))
-      (indent-for-tab-command))
-    (goto-char p)
-    (when folded (org-cycle)))
+  (unless (save-excursion
+           (beginning-of-line)
+           (looking-at-p org-drawer-regexp))
+    (user-error "Not at a drawer"))
+  (let ((element (org-element-at-point)))
+    (unless (memq (org-element-type element) '(drawer property-drawer))
+      (user-error "Not at a drawer"))
+    (org-with-wide-buffer
+     (org-indent-region (org-element-property :begin element)
+                       (org-element-property :end element))))
   (message "Drawer at point indented"))
 
 (defun org-indent-block ()
   "Indent the block at point."
   (interactive)
-  (let ((p (point))
-       (case-fold-search t)
-       (e (and (save-excursion (re-search-forward "#\\+end_?\\(?:[a-z]+\\)?" 
nil t))
-               (match-end 0)))
-       (folded
-        (save-excursion
-          (end-of-line)
-          (when (overlays-at (point))
-            (member 'invisible (overlay-properties
-                                (car (overlays-at (point)))))))))
-    (when folded (org-cycle))
-    (indent-for-tab-command)
-    (while (and (move-beginning-of-line 2) (< (point) e))
-      (indent-for-tab-command))
-    (goto-char p)
-    (when folded (org-cycle)))
+  (unless (save-excursion
+           (beginning-of-line)
+           (let ((case-fold-search t))
+             (looking-at-p "[ \t]*#\\+\\(begin\\|end\\)_")))
+    (user-error "Not at a block"))
+  (let ((element (org-element-at-point)))
+    (unless (memq (org-element-type element)
+                 '(comment-block center-block dynamic-block example-block
+                                 export-block quote-block special-block
+                                 src-block verse-block))
+      (user-error "Not at a block"))
+    (org-with-wide-buffer
+     (org-indent-region (org-element-property :begin element)
+                       (org-element-property :end element))))
   (message "Block at point indented"))
 
-(defun org-indent-region (start end)
-  "Indent region."
-  (interactive "r")
-  (save-excursion
-    (let ((line-end (org-current-line end)))
-      (goto-char start)
-      (while (< (org-current-line) line-end)
-       (cond ((org-in-src-block-p t) (org-src-native-tab-command-maybe))
-             (t (call-interactively 'org-indent-line)))
-       (move-beginning-of-line 2)))))
-
 
 ;;; Filling
 
@@ -22294,20 +23107,20 @@ hierarchy of headlines by UP levels before marking 
the subtree."
   (require 'org-element)
   ;; Prevent auto-fill from inserting unwanted new items.
   (when (boundp 'fill-nobreak-predicate)
-    (org-set-local
-     'fill-nobreak-predicate
+    (setq-local
+     fill-nobreak-predicate
      (org-uniquify
       (append fill-nobreak-predicate
              '(org-fill-line-break-nobreak-p
                org-fill-paragraph-with-timestamp-nobreak-p)))))
   (let ((paragraph-ending (substring org-element-paragraph-separate 1)))
-    (org-set-local 'paragraph-start paragraph-ending)
-    (org-set-local 'paragraph-separate paragraph-ending))
-  (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
-  (org-set-local 'auto-fill-inhibit-regexp nil)
-  (org-set-local 'adaptive-fill-function 'org-adaptive-fill-function)
-  (org-set-local 'normal-auto-fill-function 'org-auto-fill-function)
-  (org-set-local 'comment-line-break-function 
'org-comment-line-break-function))
+    (setq-local paragraph-start paragraph-ending)
+    (setq-local paragraph-separate paragraph-ending))
+  (setq-local fill-paragraph-function 'org-fill-paragraph)
+  (setq-local auto-fill-inhibit-regexp nil)
+  (setq-local adaptive-fill-function 'org-adaptive-fill-function)
+  (setq-local normal-auto-fill-function 'org-auto-fill-function)
+  (setq-local comment-line-break-function 'org-comment-line-break-function))
 
 (defun org-fill-line-break-nobreak-p ()
   "Non-nil when a new line at point would create an Org line break."
@@ -22332,69 +23145,64 @@ matches in paragraphs or comments, use it."
     (when (derived-mode-p 'message-mode)
       (save-excursion
        (beginning-of-line)
-       (cond ((or (not (message-in-body-p))
-                  (looking-at orgtbl-line-start-regexp))
-              (throw 'exit nil))
+       (cond ((not (message-in-body-p)) (throw 'exit nil))
+             ((looking-at-p org-table-line-regexp) (throw 'exit nil))
              ((looking-at message-cite-prefix-regexp)
               (throw 'exit (match-string-no-properties 0)))
              ((looking-at org-outline-regexp)
-              (throw 'exit (make-string (length (match-string 0)) ? ))))))
+              (throw 'exit (make-string (length (match-string 0)) ?\s))))))
     (org-with-wide-buffer
-     (let* ((p (line-beginning-position))
-           (element (save-excursion
-                      (beginning-of-line)
-                      (or (ignore-errors (org-element-at-point))
-                          (user-error "An element cannot be parsed line %d"
-                                      (line-number-at-pos (point))))))
-           (type (org-element-type element))
-           (post-affiliated (org-element-property :post-affiliated element)))
-       (unless (and post-affiliated (< p post-affiliated))
-        (case type
-          (comment
-           (save-excursion
-             (beginning-of-line)
-             (looking-at "[ \t]*")
-             (concat (match-string 0) "# ")))
-          (footnote-definition "")
-          ((item plain-list)
-           (make-string (org-list-item-body-column
-                         (or post-affiliated
-                             (org-element-property :begin element)))
-                        ? ))
-          (paragraph
-           ;; Fill prefix is usually the same as the current line,
-           ;; unless the paragraph is at the beginning of an item.
-           (let ((parent (org-element-property :parent element)))
+     (unless (org-at-heading-p)
+       (let* ((p (line-beginning-position))
+             (element (save-excursion
+                        (beginning-of-line)
+                        (org-element-at-point)))
+             (type (org-element-type element))
+             (post-affiliated (org-element-property :post-affiliated element)))
+        (unless (< p post-affiliated)
+          (cl-case type
+            (comment
              (save-excursion
                (beginning-of-line)
-               (cond ((eq (org-element-type parent) 'item)
-                      (make-string (org-list-item-body-column
-                                    (org-element-property :begin parent))
-                                   ? ))
-                     ((and adaptive-fill-regexp
-                           ;; Locally disable
-                           ;; `adaptive-fill-function' to let
-                           ;; `fill-context-prefix' handle
-                           ;; `adaptive-fill-regexp' variable.
-                           (let (adaptive-fill-function)
-                             (fill-context-prefix
-                              post-affiliated
-                              (org-element-property :end element)))))
-                     ((looking-at "[ \t]+") (match-string 0))
-                     (t  "")))))
-          (comment-block
-           ;; Only fill contents if P is within block boundaries.
-           (let* ((cbeg (save-excursion (goto-char post-affiliated)
-                                        (forward-line)
-                                        (point)))
-                  (cend (save-excursion
-                          (goto-char (org-element-property :end element))
-                          (skip-chars-backward " \r\t\n")
-                          (line-beginning-position))))
-             (when (and (>= p cbeg) (< p cend))
-               (if (save-excursion (beginning-of-line) (looking-at "[ \t]+"))
-                   (match-string 0)
-                 ""))))))))))
+               (looking-at "[ \t]*")
+               (concat (match-string 0) "# ")))
+            (footnote-definition "")
+            ((item plain-list)
+             (make-string (org-list-item-body-column post-affiliated) ?\s))
+            (paragraph
+             ;; Fill prefix is usually the same as the current line,
+             ;; unless the paragraph is at the beginning of an item.
+             (let ((parent (org-element-property :parent element)))
+               (save-excursion
+                 (beginning-of-line)
+                 (cond ((eq (org-element-type parent) 'item)
+                        (make-string (org-list-item-body-column
+                                      (org-element-property :begin parent))
+                                     ?\s))
+                       ((and adaptive-fill-regexp
+                             ;; Locally disable
+                             ;; `adaptive-fill-function' to let
+                             ;; `fill-context-prefix' handle
+                             ;; `adaptive-fill-regexp' variable.
+                             (let (adaptive-fill-function)
+                               (fill-context-prefix
+                                post-affiliated
+                                (org-element-property :end element)))))
+                       ((looking-at "[ \t]+") (match-string 0))
+                       (t  "")))))
+            (comment-block
+             ;; Only fill contents if P is within block boundaries.
+             (let* ((cbeg (save-excursion (goto-char post-affiliated)
+                                          (forward-line)
+                                          (point)))
+                    (cend (save-excursion
+                            (goto-char (org-element-property :end element))
+                            (skip-chars-backward " \r\t\n")
+                            (line-beginning-position))))
+               (when (and (>= p cbeg) (< p cend))
+                 (if (save-excursion (beginning-of-line) (looking-at "[ \t]+"))
+                     (match-string 0)
+                   "")))))))))))
 
 (declare-function message-goto-body "message" ())
 (defvar message-cite-prefix-regexp)    ; From message.el
@@ -22420,11 +23228,11 @@ a footnote definition, try to fill the first 
paragraph within."
                               (looking-at message-cite-prefix-regexp))))
       ;; First ensure filling is correct in message-mode.
       (let ((fill-paragraph-function
-            (cadadr (assoc 'fill-paragraph-function org-fb-vars)))
-           (fill-prefix (cadadr (assoc 'fill-prefix org-fb-vars)))
-           (paragraph-start (cadadr (assoc 'paragraph-start org-fb-vars)))
+            (cl-cadadr (assq 'fill-paragraph-function org-fb-vars)))
+           (fill-prefix (cl-cadadr (assq 'fill-prefix org-fb-vars)))
+           (paragraph-start (cl-cadadr (assq 'paragraph-start org-fb-vars)))
            (paragraph-separate
-            (cadadr (assoc 'paragraph-separate org-fb-vars))))
+            (cl-cadadr (assq 'paragraph-separate org-fb-vars))))
        (fill-paragraph nil))
     (with-syntax-table org-mode-transpose-word-syntax-table
       ;; Move to end of line in order to get the first paragraph
@@ -22436,7 +23244,7 @@ a footnote definition, try to fill the first paragraph 
within."
                                       (line-number-at-pos (point)))))))
        ;; First check if point is in a blank line at the beginning of
        ;; the buffer.  In that case, ignore filling.
-       (case (org-element-type element)
+       (cl-case (org-element-type element)
          ;; Use major mode filling function is src blocks.
          (src-block (org-babel-do-key-sequence-in-edit-buffer (kbd "M-q")))
          ;; Align Org tables, leave table.el tables as-is.
@@ -22465,25 +23273,18 @@ a footnote definition, try to fill the first 
paragraph within."
                          (concat "^" message-cite-prefix-regexp) end t))
                   (setq end (match-beginning 0))))
               ;; Fill paragraph, taking line breaks into account.
-              ;; For that, slice the paragraph using line breaks as
-              ;; separators, and fill the parts in reverse order to
-              ;; avoid messing with markers.
               (save-excursion
-                (goto-char end)
-                (mapc
-                 (lambda (pos)
-                   (fill-region-as-paragraph pos (point) justify)
-                   (goto-char pos))
-                 ;; Find the list of ending positions for line breaks
-                 ;; in the current paragraph.  Add paragraph
-                 ;; beginning to include first slice.
-                 (nreverse
-                  (cons beg
-                        (org-element-map
-                            (org-element--parse-objects
-                             beg end nil (org-element-restriction 'paragraph))
-                            'line-break
-                          (lambda (lb) (org-element-property :end lb)))))))
+                (goto-char beg)
+                (let ((cuts (list beg)))
+                  (while (re-search-forward "\\\\\\\\[ \t]*\n" end t)
+                    (when (eq 'line-break
+                              (org-element-type
+                               (save-excursion (backward-char)
+                                               (org-element-context))))
+                      (push (point) cuts)))
+                  (dolist (c (delq end cuts))
+                    (fill-region-as-paragraph c end justify)
+                    (setq end c))))
               t)))
          ;; Contents of `comment-block' type elements should be
          ;; filled as plain text, but only if point is within block
@@ -22564,6 +23365,130 @@ non-nil."
   (insert-before-markers-and-inherit fill-prefix))
 
 
+;;; Fixed Width Areas
+
+(defun org-toggle-fixed-width ()
+  "Toggle fixed-width markup.
+
+Add or remove fixed-width markup on current line, whenever it
+makes sense.  Return an error otherwise.
+
+If a region is active and if it contains only fixed-width areas
+or blank lines, remove all fixed-width markup in it.  If the
+region contains anything else, convert all non-fixed-width lines
+to fixed-width ones.
+
+Blank lines at the end of the region are ignored unless the
+region only contains such lines."
+  (interactive)
+  (if (not (org-region-active-p))
+      ;; No region:
+      ;;
+      ;; Remove fixed width marker only in a fixed-with element.
+      ;;
+      ;; Add fixed width maker in paragraphs, in blank lines after
+      ;; elements or at the beginning of a headline or an inlinetask,
+      ;; and before any one-line elements (e.g., a clock).
+      (progn
+        (beginning-of-line)
+        (let* ((element (org-element-at-point))
+               (type (org-element-type element)))
+          (cond
+           ((and (eq type 'fixed-width)
+                 (looking-at "[ \t]*\\(:\\(?: \\|$\\)\\)"))
+            (replace-match
+            "" nil nil nil (if (= (line-end-position) (match-end 0)) 0 1)))
+           ((and (memq type '(babel-call clock comment diary-sexp headline
+                                        horizontal-rule keyword paragraph
+                                        planning))
+                (<= (org-element-property :post-affiliated element) (point)))
+            (skip-chars-forward " \t")
+            (insert ": "))
+           ((and (looking-at-p "[ \t]*$")
+                 (or (eq type 'inlinetask)
+                     (save-excursion
+                       (skip-chars-forward " \r\t\n")
+                       (<= (org-element-property :end element) (point)))))
+            (delete-region (point) (line-end-position))
+            (org-indent-line)
+            (insert ": "))
+           (t (user-error "Cannot insert a fixed-width line here")))))
+    ;; Region active.
+    (let* ((begin (save-excursion
+                    (goto-char (region-beginning))
+                    (line-beginning-position)))
+           (end (copy-marker
+                 (save-excursion
+                   (goto-char (region-end))
+                   (unless (eolp) (beginning-of-line))
+                   (if (save-excursion (re-search-backward "\\S-" begin t))
+                       (progn (skip-chars-backward " \r\t\n") (point))
+                     (point)))))
+           (all-fixed-width-p
+            (catch 'not-all-p
+              (save-excursion
+                (goto-char begin)
+                (skip-chars-forward " \r\t\n")
+                (when (eobp) (throw 'not-all-p nil))
+                (while (< (point) end)
+                  (let ((element (org-element-at-point)))
+                    (if (eq (org-element-type element) 'fixed-width)
+                        (goto-char (org-element-property :end element))
+                      (throw 'not-all-p nil))))
+                t))))
+      (if all-fixed-width-p
+          (save-excursion
+            (goto-char begin)
+            (while (< (point) end)
+              (when (looking-at "[ \t]*\\(:\\(?: \\|$\\)\\)")
+                (replace-match
+                 "" nil nil nil
+                 (if (= (line-end-position) (match-end 0)) 0 1)))
+              (forward-line)))
+        (let ((min-ind (point-max)))
+          ;; Find minimum indentation across all lines.
+          (save-excursion
+            (goto-char begin)
+            (if (not (save-excursion (re-search-forward "\\S-" end t)))
+                (setq min-ind 0)
+              (catch 'zerop
+                (while (< (point) end)
+                  (unless (looking-at-p "[ \t]*$")
+                    (let ((ind (org-get-indentation)))
+                      (setq min-ind (min min-ind ind))
+                      (when (zerop ind) (throw 'zerop t))))
+                  (forward-line)))))
+          ;; Loop over all lines and add fixed-width markup everywhere
+          ;; but in fixed-width lines.
+          (save-excursion
+            (goto-char begin)
+            (while (< (point) end)
+              (cond
+               ((org-at-heading-p)
+                (insert ": ")
+                (forward-line)
+                (while (and (< (point) end) (looking-at-p "[ \t]*$"))
+                  (insert ":")
+                  (forward-line)))
+               ((looking-at-p "[ \t]*:\\( \\|$\\)")
+                (let* ((element (org-element-at-point))
+                       (element-end (org-element-property :end element)))
+                  (if (eq (org-element-type element) 'fixed-width)
+                      (progn (goto-char element-end)
+                             (skip-chars-backward " \r\t\n")
+                             (forward-line))
+                    (let ((limit (min end element-end)))
+                      (while (< (point) limit)
+                        (org-move-to-column min-ind t)
+                        (insert ": ")
+                        (forward-line))))))
+               (t
+                (org-move-to-column min-ind t)
+                (insert ": ")
+                (forward-line)))))))
+      (set-marker end nil))))
+
+
 ;;; Comments
 
 ;; Org comments syntax is quite complex.  It requires the entire line
@@ -22584,87 +23509,139 @@ non-nil."
 
 (defun org-setup-comments-handling ()
   (interactive)
-  (org-set-local 'comment-use-syntax nil)
-  (org-set-local 'comment-start "# ")
-  (org-set-local 'comment-start-skip "^\\s-*#\\(?: \\|$\\)")
-  (org-set-local 'comment-insert-comment-function 'org-insert-comment)
-  (org-set-local 'comment-region-function 'org-comment-or-uncomment-region)
-  (org-set-local 'uncomment-region-function 'org-comment-or-uncomment-region))
+  (setq-local comment-use-syntax nil)
+  (setq-local comment-start "# ")
+  (setq-local comment-start-skip "^\\s-*#\\(?: \\|$\\)")
+  (setq-local comment-insert-comment-function 'org-insert-comment)
+  (setq-local comment-region-function 'org-comment-or-uncomment-region)
+  (setq-local uncomment-region-function 'org-comment-or-uncomment-region))
 
 (defun org-insert-comment ()
   "Insert an empty comment above current line.
-If the line is empty, insert comment at its beginning."
-  (beginning-of-line)
-  (if (looking-at "\\s-*$") (replace-match "") (open-line 1))
-  (org-indent-line)
-  (insert "# "))
+If the line is empty, insert comment at its beginning.  When
+point is within a source block, comment according to the related
+major mode."
+  (if (let ((element (org-element-at-point)))
+       (and (eq (org-element-type element) 'src-block)
+            (< (save-excursion
+                 (goto-char (org-element-property :post-affiliated element))
+                 (line-end-position))
+               (point))
+            (> (save-excursion
+                 (goto-char (org-element-property :end element))
+                 (skip-chars-backward " \r\t\n")
+                 (line-beginning-position))
+               (point))))
+      (org-babel-do-in-edit-buffer (call-interactively 'comment-dwim))
+    (beginning-of-line)
+    (if (looking-at "\\s-*$") (delete-region (point) (point-at-eol))
+      (open-line 1))
+    (org-indent-line)
+    (insert "# ")))
 
 (defvar comment-empty-lines)           ; From newcomment.el.
 (defun org-comment-or-uncomment-region (beg end &rest _)
   "Comment or uncomment each non-blank line in the region.
 Uncomment each non-blank line between BEG and END if it only
-contains commented lines.  Otherwise, comment them."
-  (save-restriction
-    ;; Restrict region
-    (narrow-to-region (save-excursion (goto-char beg)
-                                     (skip-chars-forward " \r\t\n" end)
-                                     (line-beginning-position))
-                     (save-excursion (goto-char end)
-                                     (skip-chars-backward " \r\t\n" beg)
-                                     (line-end-position)))
-    (let ((uncommentp
-          ;; UNCOMMENTP is non-nil when every non blank line between
-          ;; BEG and END is a comment.
-          (save-excursion
-            (goto-char (point-min))
-            (while (and (not (eobp))
-                        (let ((element (org-element-at-point)))
-                          (and (eq (org-element-type element) 'comment)
-                               (goto-char (min (point-max)
-                                               (org-element-property
-                                                :end element)))))))
-            (eobp))))
-      (if uncommentp
-         ;; Only blank lines and comments in region: uncomment it.
-         (save-excursion
-           (goto-char (point-min))
-           (while (not (eobp))
-             (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)")
-               (replace-match "" nil nil nil 1))
-             (forward-line)))
-       ;; Comment each line in region.
-       (let ((min-indent (point-max)))
-         ;; First find the minimum indentation across all lines.
-         (save-excursion
-           (goto-char (point-min))
-           (while (and (not (eobp)) (not (zerop min-indent)))
-             (unless (looking-at "[ \t]*$")
-               (setq min-indent (min min-indent (current-indentation))))
-             (forward-line)))
-         ;; Then loop over all lines.
-         (save-excursion
-           (goto-char (point-min))
-           (while (not (eobp))
-             (unless (and (not comment-empty-lines) (looking-at "[ \t]*$"))
-               ;; Don't get fooled by invisible text (e.g. link path)
-               ;; when moving to column MIN-INDENT.
-               (let ((buffer-invisibility-spec nil))
-                 (org-move-to-column min-indent t))
-               (insert comment-start))
-             (forward-line))))))))
+contains commented lines.  Otherwise, comment them.  If region is
+strictly within a source block, use appropriate comment syntax."
+  (if (let ((element (org-element-at-point)))
+       (and (eq (org-element-type element) 'src-block)
+            (< (save-excursion
+                 (goto-char (org-element-property :post-affiliated element))
+                 (line-end-position))
+               beg)
+            (>= (save-excursion
+                  (goto-char (org-element-property :end element))
+                  (skip-chars-backward " \r\t\n")
+                  (line-beginning-position))
+                end)))
+      ;; Translate region boundaries for the Org buffer to the source
+      ;; buffer.
+      (let ((offset (- end beg)))
+       (save-excursion
+         (goto-char beg)
+         (org-babel-do-in-edit-buffer
+          (comment-or-uncomment-region (point) (+ offset (point))))))
+    (save-restriction
+      ;; Restrict region
+      (narrow-to-region (save-excursion (goto-char beg)
+                                       (skip-chars-forward " \r\t\n" end)
+                                       (line-beginning-position))
+                       (save-excursion (goto-char end)
+                                       (skip-chars-backward " \r\t\n" beg)
+                                       (line-end-position)))
+      (let ((uncommentp
+            ;; UNCOMMENTP is non-nil when every non blank line between
+            ;; BEG and END is a comment.
+            (save-excursion
+              (goto-char (point-min))
+              (while (and (not (eobp))
+                          (let ((element (org-element-at-point)))
+                            (and (eq (org-element-type element) 'comment)
+                                 (goto-char (min (point-max)
+                                                 (org-element-property
+                                                  :end element)))))))
+              (eobp))))
+       (if uncommentp
+           ;; Only blank lines and comments in region: uncomment it.
+           (save-excursion
+             (goto-char (point-min))
+             (while (not (eobp))
+               (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)")
+                 (replace-match "" nil nil nil 1))
+               (forward-line)))
+         ;; Comment each line in region.
+         (let ((min-indent (point-max)))
+           ;; First find the minimum indentation across all lines.
+           (save-excursion
+             (goto-char (point-min))
+             (while (and (not (eobp)) (not (zerop min-indent)))
+               (unless (looking-at "[ \t]*$")
+                 (setq min-indent (min min-indent (current-indentation))))
+               (forward-line)))
+           ;; Then loop over all lines.
+           (save-excursion
+             (goto-char (point-min))
+             (while (not (eobp))
+               (unless (and (not comment-empty-lines) (looking-at "[ \t]*$"))
+                 ;; Don't get fooled by invisible text (e.g. link path)
+                 ;; when moving to column MIN-INDENT.
+                 (let ((buffer-invisibility-spec nil))
+                   (org-move-to-column min-indent t))
+                 (insert comment-start))
+               (forward-line)))))))))
+
+(defun org-comment-dwim (_arg)
+  "Call `comment-dwim' within a source edit buffer if needed."
+  (interactive "*P")
+  (if (org-in-src-block-p)
+      (org-babel-do-in-edit-buffer (call-interactively 'comment-dwim))
+    (call-interactively 'comment-dwim)))
 
 
-;;; Planning
+;;; Timestamps API
 
 ;; This section contains tools to operate on timestamp objects, as
 ;; returned by, e.g. `org-element-context'.
 
+(defun org-timestamp--to-internal-time (timestamp &optional end)
+  "Encode TIMESTAMP object into Emacs internal time.
+Use end of date range or time range when END is non-nil."
+  (apply #'encode-time
+        (cons 0
+              (mapcar
+               (lambda (prop) (or (org-element-property prop timestamp) 0))
+               (if end '(:minute-end :hour-end :day-end :month-end :year-end)
+                 '(:minute-start :hour-start :day-start :month-start
+                                 :year-start))))))
+
 (defun org-timestamp-has-time-p (timestamp)
   "Non-nil when TIMESTAMP has a time specified."
   (org-element-property :hour-start timestamp))
 
-(defun org-timestamp-format (timestamp format &optional end zone)
-  "Format a TIMESTAMP element into a string.
+(defun org-timestamp-format (timestamp format &optional end utc)
+  "Format a TIMESTAMP object into a string.
 
 FORMAT is a format specifier to be passed to
 `format-time-string'.
@@ -22672,33 +23649,22 @@ FORMAT is a format specifier to be passed to
 When optional argument END is non-nil, use end of date-range or
 time-range, if possible.
 
-The optional ZONE is omitted or nil for Emacs local time, t for
-Universal Time, `wall' for system wall clock time, or a string as
-in the TZ environment variable.  It can also be a list (as from
-`current-time-zone') or an integer (as from `decode-time')
-applied without consideration for daylight saving time."
+When optional argument UTC is non-nil, time will be expressed as
+Universal Time."
   (format-time-string
-   format
-   (apply 'encode-time
-          (cons 0
-                (mapcar
-                 (lambda (prop) (or (org-element-property prop timestamp) 0))
-                 (if end '(:minute-end :hour-end :day-end :month-end :year-end)
-                   '(:minute-start :hour-start :day-start :month-start
-                                   :year-start)))))
-   zone))
+   format (org-timestamp--to-internal-time timestamp end)
+   (and utc t)))
 
 (defun org-timestamp-split-range (timestamp &optional end)
-  "Extract a timestamp object from a date or time range.
+  "Extract a TIMESTAMP object from a date or time range.
 
-TIMESTAMP is a timestamp object. END, when non-nil, means extract
-the end of the range.  Otherwise, extract its start.
+END, when non-nil, means extract the end of the range.
+Otherwise, extract its start.
 
-Return a new timestamp object sharing the same parent as
-TIMESTAMP."
+Return a new timestamp object."
   (let ((type (org-element-property :type timestamp)))
     (if (memq type '(active inactive diary)) timestamp
-      (let ((split-ts (list 'timestamp (copy-sequence (nth 1 timestamp)))))
+      (let ((split-ts (org-element-copy timestamp)))
        ;; Set new type.
        (org-element-put-property
         split-ts :type (if (eq type 'active-range) 'active 'inactive))
@@ -22712,91 +23678,43 @@ TIMESTAMP."
          (dolist (p-cell p-alist)
            (org-element-put-property
             split-ts
-            (funcall (if end 'car 'cdr) p-cell)
+            (funcall (if end #'car #'cdr) p-cell)
             (org-element-property
-             (funcall (if end 'cdr 'car) p-cell) split-ts)))
+             (funcall (if end #'cdr #'car) p-cell) split-ts)))
          ;; Eventually refresh `:raw-value'.
          (org-element-put-property split-ts :raw-value nil)
          (org-element-put-property
           split-ts :raw-value (org-element-interpret-data split-ts)))))))
 
 (defun org-timestamp-translate (timestamp &optional boundary)
-  "Apply `org-translate-time' on a TIMESTAMP object.
+  "Translate TIMESTAMP object to custom format.
+
+Format string is defined in `org-time-stamp-custom-formats',
+which see.
+
 When optional argument BOUNDARY is non-nil, it is either the
 symbol `start' or `end'.  In this case, only translate the
 starting or ending part of TIMESTAMP if it is a date or time
-range.  Otherwise, translate both parts."
-  (if (and (not boundary)
-          (memq (org-element-property :type timestamp)
-                '(active-range inactive-range)))
-      (concat
-       (org-translate-time
-       (org-element-property :raw-value
-                             (org-timestamp-split-range timestamp)))
-       "--"
-       (org-translate-time
-       (org-element-property :raw-value
-                             (org-timestamp-split-range timestamp t))))
-    (org-translate-time
-     (org-element-property
-      :raw-value
-      (if (not boundary) timestamp
-       (org-timestamp-split-range timestamp (eq boundary 'end)))))))
+range.  Otherwise, translate both parts.
 
+Return timestamp as-is if `org-display-custom-times' is nil or if
+it has a `diary' type."
+  (let ((type (org-element-property :type timestamp)))
+    (if (or (not org-display-custom-times) (eq type 'diary))
+       (org-element-interpret-data timestamp)
+      (let ((fmt (funcall (if (org-timestamp-has-time-p timestamp) #'cdr #'car)
+                         org-time-stamp-custom-formats)))
+       (if (and (not boundary) (memq type '(active-range inactive-range)))
+           (concat (org-timestamp-format timestamp fmt)
+                   "--"
+                   (org-timestamp-format timestamp fmt t))
+         (org-timestamp-format timestamp fmt (eq boundary 'end)))))))
 
 
-;;; Other stuff.
 
-(defun org-toggle-fixed-width-section (arg)
-  "Toggle the fixed-width export.
-If there is no active region, the QUOTE keyword at the current headline is
-inserted or removed.  When present, it causes the text between this headline
-and the next to be exported as fixed-width text, and unmodified.
-If there is an active region, this command adds or removes a colon as the
-first character of this line.  If the first character of a line is a colon,
-this line is also exported in fixed-width font."
-  (interactive "P")
-  (let* ((cc 0)
-        (regionp (org-region-active-p))
-        (beg (if regionp (region-beginning) (point)))
-        (end (if regionp (region-end)))
-        (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
-        (case-fold-search nil)
-        (re "[ \t]*\\(:\\(?: \\|$\\)\\)")
-        off)
-    (if regionp
-       (save-excursion
-         (goto-char beg)
-         (setq cc (current-column))
-         (beginning-of-line 1)
-         (setq off (looking-at re))
-         (while (> nlines 0)
-           (setq nlines (1- nlines))
-           (beginning-of-line 1)
-           (cond
-            (arg
-             (org-move-to-column cc t)
-             (insert ": \n")
-             (forward-line -1))
-            ((and off (looking-at re))
-             (replace-match "" t t nil 1))
-            ((not off) (org-move-to-column cc t) (insert ": ")))
-           (forward-line 1)))
-      (save-excursion
-       (org-back-to-heading)
-       (cond
-        ((looking-at (format org-heading-keyword-regexp-format
-                             org-quote-string))
-         (goto-char (match-end 1))
-         (looking-at (concat " +" org-quote-string))
-         (replace-match "" t t)
-         (when (eolp) (insert " ")))
-        ((looking-at org-outline-regexp)
-         (goto-char (match-end 0))
-         (insert org-quote-string " ")))))))
+;;; Other stuff.
 
 (defvar reftex-docstruct-symbol)
-(defvar reftex-cite-format)
 (defvar org--rds)
 
 (defun org-reftex-citation ()
@@ -22814,131 +23732,137 @@ Export of such citations to both LaTeX and HTML is 
handled by the contributed
 package ox-bibtex by Taru Karttunen."
   (interactive)
   (let ((reftex-docstruct-symbol 'org--rds)
-       (reftex-cite-format "\\cite{%l}")
        org--rds bib)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (let ((case-fold-search t)
-             (re "^#\\+bibliography:[ \t]+\\([^ \t\n]+\\)"))
-         (if (not (save-excursion
-                    (or (re-search-forward re nil t)
-                        (re-search-backward re nil t))))
-             (error "No bibliography defined in file")
-           (setq bib (concat (match-string 1) ".bib")
-                 org--rds (list (list 'bib bib)))))))
+    (org-with-wide-buffer
+     (let ((case-fold-search t)
+          (re "^[ \t]*#\\+BIBLIOGRAPHY:[ \t]+\\([^ \t\n]+\\)"))
+       (if (not (save-excursion
+                 (or (re-search-forward re nil t)
+                     (re-search-backward re nil t))))
+          (user-error "No bibliography defined in file")
+        (setq bib (concat (match-string 1) ".bib")
+              org--rds (list (list 'bib bib))))))
     (call-interactively 'reftex-citation)))
 
 ;;;; Functions extending outline functionality
 
-(defun org-beginning-of-line (&optional arg)
-  "Go to the beginning of the current line.  If that is invisible, continue
-to a visible line beginning.  This makes the function of C-a more intuitive.
-If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the
-first attempt, and only move to after the tags when the cursor is already
-beyond the end of the headline."
-  (interactive "P")
-  (let ((pos (point))
-       (special (if (consp org-special-ctrl-a/e)
-                    (car org-special-ctrl-a/e)
-                  org-special-ctrl-a/e))
-       deactivate-mark refpos)
-    (if (org-bound-and-true-p visual-line-mode)
-       (beginning-of-visual-line 1)
-      (beginning-of-line 1))
-    (if (and arg (fboundp 'move-beginning-of-line))
-       (call-interactively 'move-beginning-of-line)
-      (if (bobp)
-         nil
-       (backward-char 1)
-       (if (org-truely-invisible-p)
-           (while (and (not (bobp)) (org-truely-invisible-p))
-             (backward-char 1)
-             (beginning-of-line 1))
-         (forward-char 1))))
-    (when special
-      (cond
-       ((and (looking-at org-complex-heading-regexp)
-            (= (char-after (match-end 1)) ?\ ))
-       (setq refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1)))
-                         (point-at-eol)))
-       (goto-char
-        (if (eq special t)
-            (cond ((> pos refpos) refpos)
-                  ((= pos (point)) refpos)
-                  (t (point)))
-          (cond ((> pos (point)) (point))
-                ((not (eq last-command this-command)) (point))
-                (t refpos)))))
-       ((org-at-item-p)
-       ;; Being at an item and not looking at an the item means point
-       ;; was previously moved to beginning of a visual line, which
-       ;; doesn't contain the item.  Therefore, do nothing special,
-       ;; just stay here.
-       (when (looking-at org-list-full-item-re)
-         ;; Set special position at first white space character after
-         ;; bullet, and check-box, if any.
-         (let ((after-bullet
-                (let ((box (match-end 3)))
-                  (if (not box) (match-end 1)
-                    (let ((after (char-after box)))
-                      (if (and after (= after ? )) (1+ box) box))))))
-           ;; Special case: Move point to special position when
-           ;; currently after it or at beginning of line.
-           (if (eq special t)
-               (when (or (> pos after-bullet) (= (point) pos))
-                 (goto-char after-bullet))
-             ;; Reversed case: Move point to special position when
-             ;; point was already at beginning of line and command is
-             ;; repeated.
-             (when (and (= (point) pos) (eq last-command this-command))
-               (goto-char after-bullet))))))))
-    (org-no-warnings
-     (and (featurep 'xemacs) (setq zmacs-region-stays t))))
-  (setq disable-point-adjustment
-        (or (not (invisible-p (point)))
-            (not (invisible-p (max (point-min) (1- (point))))))))
-
-(defun org-end-of-line (&optional arg)
-  "Go to the end of the line.
+(defun org-beginning-of-line (&optional n)
+  "Go to the beginning of the current visible line.
+
 If this is a headline, and `org-special-ctrl-a/e' is set, ignore
 tags on the first attempt, and only move to after the tags when
-the cursor is already beyond the end of the headline."
-  (interactive "P")
-  (let ((special (if (consp org-special-ctrl-a/e) (cdr org-special-ctrl-a/e)
-                  org-special-ctrl-a/e))
-       (move-fun (cond ((org-bound-and-true-p visual-line-mode)
-                        'end-of-visual-line)
-                       ((fboundp 'move-end-of-line) 'move-end-of-line)
-                       (t 'end-of-line)))
+the cursor is already beyond the end of the headline.
+
+With argument N not nil or 1, move forward N - 1 lines first."
+  (interactive "^p")
+  (let ((origin (point))
+       (special (pcase org-special-ctrl-a/e
+                  (`(,C-a . ,_) C-a) (_ org-special-ctrl-a/e)))
        deactivate-mark)
-    (if (or (not special) arg) (call-interactively move-fun)
-      (let* ((element (save-excursion (beginning-of-line)
-                                     (org-element-at-point)))
-            (type (org-element-type element)))
-       (cond
-        ((memq type '(headline inlinetask))
-         (let ((pos (point)))
-           (beginning-of-line 1)
-           (if (looking-at (org-re ".*?\\(?:\\([ 
\t]*\\)\\(:[[:alnum:address@hidden:]+:\\)?[ \t]*\\)?$"))
-               (if (eq special t)
-                   (if (or (< pos (match-beginning 1)) (= pos (match-end 0)))
-                       (goto-char (match-beginning 1))
-                     (goto-char (match-end 0)))
-                 (if (or (< pos (match-end 0))
-                         (not (eq this-command last-command)))
-                     (goto-char (match-end 0))
-                   (goto-char (match-beginning 1))))
-             (call-interactively move-fun))))
-        ((org-element-property :hiddenp element)
-         ;; If element is hidden, `move-end-of-line' would put point
-         ;; after it.  Use `end-of-line' to stay on current line.
-         (call-interactively 'end-of-line))
-        (t (call-interactively move-fun)))))
-    (org-no-warnings (and (featurep 'xemacs) (setq zmacs-region-stays t))))
-  (setq disable-point-adjustment
-        (or (not (invisible-p (point)))
-            (not (invisible-p (max (point-min) (1- (point))))))))
+    ;; First move to a visible line.
+    (if (bound-and-true-p visual-line-mode)
+       (beginning-of-visual-line n)
+      (move-beginning-of-line n)
+      ;; `move-beginning-of-line' may leave point after invisible
+      ;; characters if line starts with such of these (e.g., with
+      ;; a link at column 0).  Really move to the beginning of the
+      ;; current visible line.
+      (beginning-of-line))
+    (cond
+     ;; No special behavior.  Point is already at the beginning of
+     ;; a line, logical or visual.
+     ((not special))
+     ;; `beginning-of-visual-line' left point before logical beginning
+     ;; of line: point is at the beginning of a visual line.  Bail
+     ;; out.
+     ((and (bound-and-true-p visual-line-mode) (not (bolp))))
+     ((let ((case-fold-search nil)) (looking-at org-complex-heading-regexp))
+      ;; At a headline, special position is before the title, but
+      ;; after any TODO keyword or priority cookie.
+      (let ((refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1)))
+                        (line-end-position)))
+           (bol (point)))
+       (if (eq special 'reversed)
+           (when (and (= origin bol) (eq last-command this-command))
+             (goto-char refpos))
+         (when (or (> origin refpos) (= origin bol))
+           (goto-char refpos)))))
+     ((and (looking-at org-list-full-item-re)
+          (memq (org-element-type (save-match-data (org-element-at-point)))
+                '(item plain-list)))
+      ;; Set special position at first white space character after
+      ;; bullet, and check-box, if any.
+      (let ((after-bullet
+            (let ((box (match-end 3)))
+              (cond ((not box) (match-end 1))
+                    ((eq (char-after box) ?\s) (1+ box))
+                    (t box)))))
+       (if (eq special 'reversed)
+           (when (and (= (point) origin) (eq last-command this-command))
+             (goto-char after-bullet))
+         (when (or (> origin after-bullet) (= (point) origin))
+           (goto-char after-bullet)))))
+     ;; No special context.  Point is already at beginning of line.
+     (t nil))))
+
+(defun org-end-of-line (&optional n)
+  "Go to the end of the line, but before ellipsis, if any.
+
+If this is a headline, and `org-special-ctrl-a/e' is set, ignore
+tags on the first attempt, and only move to after the tags when
+the cursor is already beyond the end of the headline.
+
+With argument N not nil or 1, move forward N - 1 lines first."
+  (interactive "^p")
+  (let ((origin (point))
+       (special (pcase org-special-ctrl-a/e
+                  (`(,_ . ,C-e) C-e) (_ org-special-ctrl-a/e)))
+       deactivate-mark)
+    ;; First move to a visible line.
+    (if (bound-and-true-p visual-line-mode)
+       (beginning-of-visual-line n)
+      (move-beginning-of-line n))
+    (cond
+     ;; At a headline, with tags.
+     ((and special
+          (save-excursion
+            (beginning-of-line)
+            (let ((case-fold-search nil))
+              (looking-at org-complex-heading-regexp)))
+          (match-end 5))
+      (let ((tags (save-excursion
+                   (goto-char (match-beginning 5))
+                   (skip-chars-backward " \t")
+                   (point)))
+           (visual-end (and (bound-and-true-p visual-line-mode)
+                            (save-excursion
+                              (end-of-visual-line)
+                              (point)))))
+       ;; If `end-of-visual-line' brings us before end of line or
+       ;; even tags, i.e., the headline spans over multiple visual
+       ;; lines, move there.
+       (cond ((and visual-end
+                   (< visual-end tags)
+                   (<= origin visual-end))
+              (goto-char visual-end))
+             ((eq special 'reversed)
+              (if (and (= origin (line-end-position))
+                       (eq this-command last-command))
+                  (goto-char tags)
+                (end-of-line)))
+             (t
+              (if (or (< origin tags) (= origin (line-end-position)))
+                  (goto-char tags)
+                (end-of-line))))))
+     ((bound-and-true-p visual-line-mode)
+      (let ((bol (line-beginning-position)))
+       (end-of-visual-line)
+       ;; If `end-of-visual-line' gets us past the ellipsis at the
+       ;; end of a line, backtrack and use `end-of-line' instead.
+       (when (/= bol (line-beginning-position))
+         (goto-char bol)
+         (end-of-line))))
+     (t (end-of-line)))))
 
 (define-key org-mode-map "\C-a" 'org-beginning-of-line)
 (define-key org-mode-map "\C-e" 'org-end-of-line)
@@ -22948,18 +23872,43 @@ the cursor is already beyond the end of the headline."
 This will call `backward-sentence' or `org-table-beginning-of-field',
 depending on context."
   (interactive)
-  (cond
-   ((org-at-table-p) (call-interactively 'org-table-beginning-of-field))
-   (t (call-interactively 'backward-sentence))))
+  (let* ((element (org-element-at-point))
+        (contents-begin (org-element-property :contents-begin element))
+        (table (org-element-lineage element '(table) t)))
+    (if (and table
+            (> (point) contents-begin)
+            (<= (point) (org-element-property :contents-end table)))
+       (call-interactively #'org-table-beginning-of-field)
+      (save-restriction
+       (when (and contents-begin
+                  (< (point-min) contents-begin)
+                  (> (point) contents-begin))
+         (narrow-to-region contents-begin
+                           (org-element-property :contents-end element)))
+       (call-interactively #'backward-sentence)))))
 
 (defun org-forward-sentence (&optional _arg)
   "Go to end of sentence, or end of table field.
 This will call `forward-sentence' or `org-table-end-of-field',
 depending on context."
   (interactive)
-  (cond
-   ((org-at-table-p) (call-interactively 'org-table-end-of-field))
-   (t (call-interactively 'forward-sentence))))
+  (let* ((element (org-element-at-point))
+        (contents-end (org-element-property :contents-end element))
+        (table (org-element-lineage element '(table) t)))
+    (if (and table
+            (>= (point) (org-element-property :contents-begin table))
+            (< (point) contents-end))
+       (call-interactively #'org-table-end-of-field)
+      (save-restriction
+       (when (and contents-end
+                  (> (point-max) contents-end)
+                  ;; Skip blank lines between elements.
+                  (< (org-element-property :end element)
+                     (save-excursion (goto-char contents-end)
+                                     (skip-chars-forward " \r\t\n"))))
+         (narrow-to-region (org-element-property :contents-begin element)
+                           contents-end))
+       (call-interactively #'forward-sentence)))))
 
 (define-key org-mode-map "\M-a" 'org-backward-sentence)
 (define-key org-mode-map "\M-e" 'org-forward-sentence)
@@ -22971,14 +23920,14 @@ depending on context."
    ((or (not org-special-ctrl-k)
        (bolp)
        (not (org-at-heading-p)))
-    (if (and (get-char-property (min (point-max) (point-at-eol)) 'invisible)
-            org-ctrl-k-protect-subtree)
-       (if (or (eq org-ctrl-k-protect-subtree 'error)
-               (not (y-or-n-p "Kill hidden subtree along with headline? ")))
-           (user-error "C-k aborted as it would kill a hidden subtree")))
+    (when (and (get-char-property (min (point-max) (point-at-eol)) 'invisible)
+              org-ctrl-k-protect-subtree
+              (or (eq org-ctrl-k-protect-subtree 'error)
+                  (not (y-or-n-p "Kill hidden subtree along with headline? 
"))))
+      (user-error "C-k aborted as it would kill a hidden subtree"))
     (call-interactively
-     (if (org-bound-and-true-p visual-line-mode) 'kill-visual-line 
'kill-line)))
-   ((looking-at (org-re ".*?\\S-\\([ 
\t]+\\(:[[:alnum:address@hidden:]+:\\)\\)[ \t]*$"))
+     (if (bound-and-true-p visual-line-mode) 'kill-visual-line 'kill-line)))
+   ((looking-at ".*?\\S-\\([ \t]+\\(:[[:alnum:address@hidden:]+:\\)\\)[ \t]*$")
     (kill-region (point) (match-beginning 1))
     (org-set-tags nil t))
    (t (kill-region (point) (point-at-eol)))))
@@ -22991,24 +23940,25 @@ This command will look at the current kill and check 
if is a single
 subtree, or a series of subtrees[1].  If it passes the test, and if the
 cursor is at the beginning of a line or after the stars of a currently
 empty headline, then the yank is handled specially.  How exactly depends
-on the value of the following variables, both set by default.
+on the value of the following variables.
 
-org-yank-folded-subtrees
-    When set, the subtree(s) will be folded after insertion, but only
-    if doing so would now swallow text after the yanked text.
+`org-yank-folded-subtrees'
+    By default, this variable is non-nil, which results in
+    subtree(s) being folded after insertion, except if doing so
+    would swallow text after the yanked text.
 
-org-yank-adjusted-subtrees
-    When set, the subtree will be promoted or demoted in order to
-    fit into the local outline tree structure, which means that the level
-    will be adjusted so that it becomes the smaller one of the two
-    *visible* surrounding headings.
+`org-yank-adjusted-subtrees'
+    When non-nil (the default value is nil), the subtree will be
+    promoted or demoted in order to fit into the local outline tree
+    structure, which means that the level will be adjusted so that it
+    becomes the smaller one of the two *visible* surrounding headings.
 
 Any prefix to this command will cause `yank' to be called directly with
-no special treatment.  In particular, a simple \\[universal-argument] prefix \
+no special treatment.  In particular, a simple `\\[universal-argument]' prefix 
\
 will just
 plainly yank the text as it is.
 
-[1] The test checks if the first non-white line is a heading
+\[1] The test checks if the first non-white line is a heading
     and if there are no other headings with fewer stars."
   (interactive "P")
   (org-yank-generic 'yank arg))
@@ -23051,7 +24001,7 @@ interactive command with similar behavior."
             (or (looking-at org-outline-regexp)
                 (re-search-forward org-outline-regexp-bol end t))
             (while (and (< (point) end) (looking-at org-outline-regexp))
-              (hide-subtree)
+              (outline-hide-subtree)
               (org-cycle-show-empty-lines 'folded)
               (condition-case nil
                   (outline-forward-same-level 1)
@@ -23082,11 +24032,9 @@ interactive command with similar behavior."
         (setq level (org-outline-level)))
        (goto-char end)
        (skip-chars-forward " \t\r\n\v\f")
-       (if (or (eobp)
-              (and (bolp) (looking-at org-outline-regexp)
-                   (<= (org-outline-level) level)))
-          nil                          ; Nothing would be swallowed
-        t)))))                         ; something would swallow
+       (not (or (eobp)
+               (and (bolp) (looking-at-p org-outline-regexp)
+                    (<= (org-outline-level) level))))))))
 
 (define-key org-mode-map "\C-y" 'org-yank)
 
@@ -23094,17 +24042,18 @@ interactive command with similar behavior."
   "Check if point is at a character currently not visible.
 This version does not only check the character property, but also
 `visible-mode'."
-  ;; Early versions of noutline don't have `outline-invisible-p'.
-  (if (org-bound-and-true-p visible-mode)
-      nil
-    (outline-invisible-p)))
+  (unless (bound-and-true-p visible-mode)
+    (org-invisible-p)))
 
 (defun org-invisible-p2 ()
-  "Check if point is at a character currently not visible."
+  "Check if point is at a character currently not visible.
+
+If the point is at EOL (and not at the beginning of a buffer too),
+move it back by one char before doing this check."
   (save-excursion
-    (if (and (eolp) (not (bobp))) (backward-char 1))
-    ;; Early versions of noutline don't have `outline-invisible-p'.
-    (outline-invisible-p)))
+    (when (and (eolp) (not (bobp)))
+      (backward-char 1))
+    (org-invisible-p)))
 
 (defun org-back-to-heading (&optional invisible-ok)
   "Call `outline-back-to-heading', but provide a better error message."
@@ -23121,14 +24070,28 @@ This version does not only check the character 
property, but also
 
 (defun org-at-heading-p (&optional ignored)
   (outline-on-heading-p t))
-;; Compatibility alias with Org versions < 7.8.03
-(defalias 'org-on-heading-p 'org-at-heading-p)
+
+(defun org-in-commented-heading-p (&optional no-inheritance)
+  "Non-nil if point is under a commented heading.
+This function also checks ancestors of the current headline,
+unless optional argument NO-INHERITANCE is non-nil."
+  (cond
+   ((org-before-first-heading-p) nil)
+   ((let ((headline (nth 4 (org-heading-components))))
+      (and headline
+          (let ((case-fold-search nil))
+            (string-match-p (concat "^" org-comment-string "\\(?: \\|$\\)")
+                            headline)))))
+   (no-inheritance nil)
+   (t
+    (save-excursion (and (org-up-heading-safe) 
(org-in-commented-heading-p))))))
 
 (defun org-at-comment-p nil
-  "Is cursor in a line starting with a # character?"
+  "Is cursor in a commented line?"
   (save-excursion
-    (beginning-of-line)
-    (looking-at "^#")))
+    (save-match-data
+      (beginning-of-line)
+      (looking-at "^[ \t]*# "))))
 
 (defun org-at-drawer-p nil
   "Is cursor at a drawer keyword?"
@@ -23146,13 +24109,13 @@ This version does not only check the character 
property, but also
   "If point is at the end of an empty headline, return t, else nil.
 If the heading only contains a TODO keyword, it is still still considered
 empty."
-  (and (looking-at "[ \t]*$")
-       (when org-todo-line-regexp
+  (let ((case-fold-search nil))
+    (and (looking-at "[ \t]*$")
+        org-todo-line-regexp
         (save-excursion
-          (beginning-of-line 1)
-          (let ((case-fold-search nil))
-            (looking-at org-todo-line-regexp)
-            (string= (match-string 3) ""))))))
+          (beginning-of-line)
+          (looking-at org-todo-line-regexp)
+          (string= (match-string 3) "")))))
 
 (defun org-at-heading-or-item-p ()
   (or (org-at-heading-p) (org-at-item-p)))
@@ -23167,9 +24130,7 @@ empty."
   "Move to the heading line of which the present line is a subheading.
 This function considers both visible and invisible heading lines.
 With argument, move up ARG levels."
-  (if (fboundp 'outline-up-heading-all)
-      (outline-up-heading-all arg)   ; emacs 21 version of outline.el
-    (outline-up-heading arg t)))     ; emacs 22 version of outline.el
+  (outline-up-heading arg t))
 
 (defun org-up-heading-safe ()
   "Move to the heading line of which the present line is a subheading.
@@ -23179,14 +24140,11 @@ headline found, or nil if no higher level is found.
 Also, this function will be a lot faster than `outline-up-heading',
 because it relies on stars being the outline starters.  This can really
 make a significant difference in outlines with very many siblings."
-  (let (start-level re)
-    (org-back-to-heading t)
-    (setq start-level (funcall outline-level))
-    (if (equal start-level 1)
-       nil
-      (setq re (concat "^\\*\\{1," (number-to-string (1- start-level)) "\\} "))
-      (if (re-search-backward re nil t)
-         (funcall outline-level)))))
+  (when (ignore-errors (org-back-to-heading t))
+    (let ((level-up (1- (funcall outline-level))))
+      (and (> level-up 0)
+          (re-search-backward (format "^\\*\\{1,%d\\} " level-up) nil t)
+          (funcall outline-level)))))
 
 (defun org-first-sibling-p ()
   "Is this heading the first child of its parents?"
@@ -23211,7 +24169,7 @@ move point."
        (pos (point))
        (re org-outline-regexp-bol)
        level l)
-    (when (condition-case nil (org-back-to-heading t) (error nil))
+    (when (ignore-errors (org-back-to-heading t))
       (setq level (funcall outline-level))
       (catch 'exit
        (or previous (forward-char 1))
@@ -23235,7 +24193,7 @@ move point."
 Return t when a child was found.  Otherwise don't move point and
 return nil."
   (let (level (pos (point)) (re org-outline-regexp-bol))
-    (when (condition-case nil (org-back-to-heading t) (error nil))
+    (when (ignore-errors (org-back-to-heading t))
       (setq level (outline-level))
       (forward-char 1)
       (if (and (re-search-forward re nil t) (> (outline-level) level))
@@ -23271,8 +24229,7 @@ This is like outline-next-sibling, but invisible 
headings are ok."
     (outline-next-heading)
     (while (and (not (eobp)) (> (funcall outline-level) level))
       (outline-next-heading))
-    (if (or (eobp) (< (funcall outline-level) level))
-       nil
+    (unless (or (eobp) (< (funcall outline-level) level))
       (point))))
 
 (defun org-get-last-sibling ()
@@ -23285,8 +24242,7 @@ If there is no such heading, return nil."
       (while (and (> (funcall outline-level) level)
                  (not (bobp)))
        (outline-previous-heading))
-      (if (< (funcall outline-level) level)
-         nil
+      (unless (< (funcall outline-level) level)
         (point)))))
 
 (defun org-end-of-subtree (&optional invisible-ok to-heading)
@@ -23302,7 +24258,7 @@ If there is no such heading, return nil."
   (let ((first t)
        (level (funcall outline-level)))
     (if (and (derived-mode-p 'org-mode) (< level 1000))
-       ;; A true heading (not a plain list item), in Org-mode
+       ;; A true heading (not a plain list item), in Org
        ;; This means we can easily find the end by looking
        ;; only for the right number of stars.  Using a regexp to do
        ;; this is so much faster than using a Lisp loop.
@@ -23315,33 +24271,36 @@ If there is no such heading, return nil."
        (setq first nil)
        (outline-next-heading)))
     (unless to-heading
-      (if (memq (preceding-char) '(?\n ?\^M))
-         (progn
-           ;; Go to end of line before heading
-           (forward-char -1)
-           (if (memq (preceding-char) '(?\n ?\^M))
-               ;; leave blank line before heading
-               (forward-char -1))))))
+      (when (memq (preceding-char) '(?\n ?\^M))
+       ;; Go to end of line before heading
+       (forward-char -1)
+       (when (memq (preceding-char) '(?\n ?\^M))
+         ;; leave blank line before heading
+         (forward-char -1)))))
   (point))
 
-(defun org-end-of-meta-data-and-drawers ()
-  "Jump to the first text after meta data and drawers in the current entry.
-This will move over empty lines, lines with planning time stamps,
-clocking lines, and drawers."
+(defun org-end-of-meta-data (&optional full)
+  "Skip planning line and properties drawer in current entry.
+When optional argument FULL is non-nil, also skip empty lines,
+clocking lines and regular drawers at the beginning of the
+entry."
   (org-back-to-heading t)
-  (let ((end (save-excursion (outline-next-heading) (point)))
-       (re (concat "\\(" org-drawer-regexp "\\)"
-                   "\\|" "[ \t]*" org-keyword-time-regexp)))
-    (forward-line 1)
-    (while (re-search-forward re end t)
-      (if (not (match-end 1))
-         ;; empty or planning line
-         (forward-line 1)
-       ;; a drawer, find the end
-       (re-search-forward "^[ \t]*:END:" end 'move)
-       (forward-line 1)))
-    (and (re-search-forward "[^\n]" nil t) (backward-char 1))
-    (point)))
+  (forward-line)
+  (when (looking-at-p org-planning-line-re) (forward-line))
+  (when (looking-at org-property-drawer-re)
+    (goto-char (match-end 0))
+    (forward-line))
+  (when (and full (not (org-at-heading-p)))
+    (catch 'exit
+      (let ((end (save-excursion (outline-next-heading) (point)))
+           (re (concat "[ \t]*$" "\\|" org-clock-line-re)))
+       (while (not (eobp))
+         (cond ((looking-at-p org-drawer-regexp)
+                (if (re-search-forward "^[ \t]*:END:[ \t]*$" end t)
+                    (forward-line)
+                  (throw 'exit t)))
+               ((looking-at-p re) (forward-line))
+               (t (throw 'exit t))))))))
 
 (defun org-forward-heading-same-level (arg &optional invisible-ok)
   "Move forward to the ARG'th subheading at same level as this one.
@@ -23349,32 +24308,27 @@ Stop at the first and last subheadings of a superior 
heading.
 Normally this only looks at visible headings, but when INVISIBLE-OK is
 non-nil it will also look at invisible ones."
   (interactive "p")
-  (if (not (ignore-errors (org-back-to-heading invisible-ok)))
-      (if (and arg (< arg 0))
-          (goto-char (point-min))
-        (outline-next-heading))
-    (org-at-heading-p)
-    (let ((level (- (match-end 0) (match-beginning 0) 1))
-          (f (if (and arg (< arg 0))
-                 're-search-backward
-               're-search-forward))
-          (count (if arg (abs arg) 1))
-          (result (point)))
-      (while (and (prog1 (> count 0)
-                   (forward-char (if (and arg (< arg 0)) -1 1)))
-                  (funcall f org-outline-regexp-bol nil 'move))
-        (let ((l (- (match-end 0) (match-beginning 0) 1)))
-          (cond ((< l level) (setq count 0))
-                ((and (= l level)
-                      (or invisible-ok
-                          (progn
-                            (goto-char (line-beginning-position))
-                            (not (outline-invisible-p)))))
-                 (setq count (1- count))
-                 (when (eq l level)
-                   (setq result (point)))))))
-      (goto-char result))
-    (beginning-of-line 1)))
+  (let ((backward? (and arg (< arg 0))))
+    (if (org-before-first-heading-p)
+       (if backward? (goto-char (point-min)) (outline-next-heading))
+      (org-back-to-heading invisible-ok)
+      (unless backward? (end-of-line)) ;do not match current headline
+      (let ((level (- (match-end 0) (match-beginning 0) 1))
+           (f (if backward? #'re-search-backward #'re-search-forward))
+           (count (if arg (abs arg) 1))
+           (result (point)))
+       (while (and (> count 0)
+                   (funcall f org-outline-regexp-bol nil 'move))
+         (let ((l (- (match-end 0) (match-beginning 0) 1)))
+           (cond ((< l level) (setq count 0))
+                 ((and (= l level)
+                       (or invisible-ok
+                           (not (org-invisible-p
+                                 (line-beginning-position)))))
+                  (cl-decf count)
+                  (when (= l level) (setq result (point)))))))
+       (goto-char result))
+      (beginning-of-line))))
 
 (defun org-backward-heading-same-level (arg &optional invisible-ok)
   "Move backward to the ARG'th subheading at same level as this one.
@@ -23382,20 +24336,64 @@ Stop at the first and last subheadings of a superior 
heading."
   (interactive "p")
   (org-forward-heading-same-level (if arg (- arg) -1) invisible-ok))
 
+(defun org-next-visible-heading (arg)
+  "Move to the next visible heading.
+
+This function wraps `outline-next-visible-heading' with
+`org-with-limited-levels' in order to skip over inline tasks and
+respect customization of `org-odd-levels-only'."
+  (interactive "p")
+  (org-with-limited-levels
+   (outline-next-visible-heading arg)))
+
+(defun org-previous-visible-heading (arg)
+  "Move to the previous visible heading.
+
+This function wraps `outline-previous-visible-heading' with
+`org-with-limited-levels' in order to skip over inline tasks and
+respect customization of `org-odd-levels-only'."
+  (interactive "p")
+  (org-with-limited-levels
+   (outline-previous-visible-heading arg)))
+
 (defun org-next-block (arg &optional backward block-regexp)
   "Jump to the next block.
-With a prefix argument ARG, jump forward ARG many source blocks.
+
+With a prefix argument ARG, jump forward ARG many blocks.
+
 When BACKWARD is non-nil, jump to the previous block.
-When BLOCK-REGEXP is non-nil, use this regexp to find blocks."
+
+When BLOCK-REGEXP is non-nil, use this regexp to find blocks.
+Match data is set according to this regexp when the function
+returns.
+
+Return point at beginning of the opening line of found block.
+Throw an error if no block is found."
   (interactive "p")
-  (let ((re (or block-regexp org-block-regexp))
-       (re-search-fn (or (and backward 're-search-backward)
-                          're-search-forward)))
-    (if (looking-at re) (forward-char 1))
-    (condition-case nil
-       (funcall re-search-fn re nil nil arg)
-      (error (error "No %s code blocks" (if backward "previous" "further" ))))
-    (goto-char (match-beginning 0)) (org-show-context)))
+  (let ((re (or block-regexp "^[ \t]*#\\+BEGIN"))
+       (case-fold-search t)
+       (search-fn (if backward #'re-search-backward #'re-search-forward))
+       (count (or arg 1))
+       (origin (point))
+       last-element)
+    (if backward (beginning-of-line) (end-of-line))
+    (while (and (> count 0) (funcall search-fn re nil t))
+      (let ((element (save-excursion
+                      (goto-char (match-beginning 0))
+                      (save-match-data (org-element-at-point)))))
+       (when (and (memq (org-element-type element)
+                        '(center-block comment-block dynamic-block
+                                       example-block export-block quote-block
+                                       special-block src-block verse-block))
+                  (<= (match-beginning 0)
+                      (org-element-property :post-affiliated element)))
+         (setq last-element element)
+         (cl-decf count))))
+    (if (= count 0)
+       (prog1 (goto-char (org-element-property :post-affiliated last-element))
+         (save-match-data (org-show-context)))
+      (goto-char origin)
+      (user-error "No %s code blocks" (if backward "previous" "further")))))
 
 (defun org-previous-block (arg &optional block-regexp)
   "Jump to the previous block.
@@ -23434,7 +24432,7 @@ item, etc.  It also provides some special moves for 
convenience:
            (skip-chars-forward " \r\t\n")
            (or (eobp) (beginning-of-line)))
           ;; On affiliated keywords, move to element's beginning.
-          ((and post-affiliated (< (point) post-affiliated))
+          ((< (point) post-affiliated)
            (goto-char post-affiliated))
           ;; At a table row, move to the end of the table.  Similarly,
           ;; at a node property, move to the end of the property
@@ -23461,8 +24459,8 @@ item, etc.  It also provides some special moves for 
convenience:
           ;; With no contents, just skip element.
           ((not contents-begin) (goto-char end))
           ;; If contents are invisible, skip the element altogether.
-          ((outline-invisible-p (line-end-position))
-           (case type
+          ((org-invisible-p (line-end-position))
+           (cl-case type
              (headline
               (org-with-limited-levels (outline-next-visible-heading 1)))
              ;; At a plain list, make sure we move to the next item
@@ -23473,7 +24471,7 @@ item, etc.  It also provides some special moves for 
convenience:
           ((>= (point) contents-end) (goto-char end))
           ((>= (point) contents-begin)
            ;; This can only happen on paragraphs and plain lists.
-           (case type
+           (cl-case type
              (paragraph (goto-char end))
              ;; At a plain list, try to move to second element in
              ;; first item, if possible.
@@ -23513,7 +24511,7 @@ convenience:
      ((= (point) begin)
       (backward-char)
       (org-backward-paragraph))
-     ((and post-affiliated (<= (point) post-affiliated)) (goto-char begin))
+     ((<= (point) post-affiliated) (goto-char begin))
      ((memq type '(node-property table-row))
       (goto-char (org-element-property
                   :post-affiliated (org-element-property :parent element))))
@@ -23548,7 +24546,7 @@ convenience:
       (org-backward-paragraph))
      (t (goto-char (or post-affiliated begin))))
     ;; Ensure we never leave point invisible.
-    (when (outline-invisible-p (point)) (beginning-of-visual-line))))
+    (when (org-invisible-p (point)) (beginning-of-visual-line))))
 
 (defun org-forward-element ()
   "Move forward by one element.
@@ -23587,18 +24585,21 @@ Move to the previous element at the same level, when 
possible."
                 (progn (goto-char origin)
                        (user-error "Cannot move further up"))))))
        (t
-        (let* ((trail (org-element-at-point 'keep-trail))
-               (elem (car trail))
-               (prev-elem (nth 1 trail))
+        (let* ((elem (org-element-at-point))
                (beg (org-element-property :begin elem)))
           (cond
            ;; Move to beginning of current element if point isn't
            ;; there already.
            ((null beg) (message "No element at point"))
            ((/= (point) beg) (goto-char beg))
-           (prev-elem (goto-char (org-element-property :begin prev-elem)))
-           ((org-before-first-heading-p) (goto-char (point-min)))
-           (t (org-back-to-heading)))))))
+           (t (goto-char beg)
+              (skip-chars-backward " \r\t\n")
+              (unless (bobp)
+                (let ((prev (org-element-at-point)))
+                  (goto-char (org-element-property :begin prev))
+                  (while (and (setq prev (org-element-property :parent prev))
+                              (<= (org-element-property :end prev) beg))
+                    (goto-char (org-element-property :begin prev)))))))))))
 
 (defun org-up-element ()
   "Move to upper element."
@@ -23612,7 +24613,6 @@ Move to the previous element at the same level, when 
possible."
            (user-error "No surrounding element")
          (org-with-limited-levels (org-back-to-heading)))))))
 
-(defvar org-element-greater-elements)
 (defun org-down-element ()
   "Move to inner element."
   (interactive)
@@ -23623,7 +24623,7 @@ Move to the previous element at the same level, when 
possible."
       (forward-char))
      ((memq (org-element-type element) org-element-greater-elements)
       ;; If contents are hidden, first disclose them.
-      (when (org-element-property :hiddenp element) (org-cycle))
+      (when (org-invisible-p (line-end-position)) (org-cycle))
       (goto-char (or (org-element-property :contents-begin element)
                     (user-error "No content for this element"))))
      (t (user-error "No inner element")))))
@@ -23631,24 +24631,41 @@ Move to the previous element at the same level, when 
possible."
 (defun org-drag-element-backward ()
   "Move backward element at point."
   (interactive)
-  (if (org-with-limited-levels (org-at-heading-p)) (org-move-subtree-up)
-    (let* ((trail (org-element-at-point 'keep-trail))
-          (elem (car trail))
-          (prev-elem (nth 1 trail)))
-      ;; Error out if no previous element or previous element is
-      ;; a parent of the current one.
-      (if (or (not prev-elem) (org-element-nested-p elem prev-elem))
-         (user-error "Cannot drag element backward")
-       (let ((pos (point)))
-         (org-element-swap-A-B prev-elem elem)
-         (goto-char (+ (org-element-property :begin prev-elem)
-                       (- pos (org-element-property :begin elem)))))))))
+  (let ((elem (or (org-element-at-point)
+                 (user-error "No element at point"))))
+    (if (eq (org-element-type elem) 'headline)
+       ;; Preserve point when moving a whole tree, even if point was
+       ;; on blank lines below the headline.
+       (let ((offset (skip-chars-backward " \t\n")))
+         (unwind-protect (org-move-subtree-up)
+           (forward-char (- offset))))
+      (let ((prev-elem
+            (save-excursion
+              (goto-char (org-element-property :begin elem))
+              (skip-chars-backward " \r\t\n")
+              (unless (bobp)
+                (let* ((beg (org-element-property :begin elem))
+                       (prev (org-element-at-point))
+                       (up prev))
+                  (while (and (setq up (org-element-property :parent up))
+                              (<= (org-element-property :end up) beg))
+                    (setq prev up))
+                  prev)))))
+       ;; Error out if no previous element or previous element is
+       ;; a parent of the current one.
+       (if (or (not prev-elem) (org-element-nested-p elem prev-elem))
+           (user-error "Cannot drag element backward")
+         (let ((pos (point)))
+           (org-element-swap-A-B prev-elem elem)
+           (goto-char (+ (org-element-property :begin prev-elem)
+                         (- pos (org-element-property :begin elem))))))))))
 
 (defun org-drag-element-forward ()
   "Move forward element at point."
   (interactive)
   (let* ((pos (point))
-        (elem (org-element-at-point)))
+        (elem (or (org-element-at-point)
+                  (user-error "No element at point"))))
     (when (= (point-max) (org-element-property :end elem))
       (user-error "Cannot drag element forward"))
     (goto-char (org-element-property :end elem))
@@ -23681,7 +24698,7 @@ Move to the previous element at the same level, when 
possible."
 (defun org-drag-line-forward (arg)
   "Drag the line at point ARG lines forward."
   (interactive "p")
-  (dotimes (n (abs arg))
+  (dotimes (_ (abs arg))
     (let ((c (current-column)))
       (if (< 0 arg)
          (progn
@@ -23705,7 +24722,7 @@ mode) if the mark is active, it marks the next element 
after the
 ones already marked."
   (interactive)
   (let (deactivate-mark)
-    (if (and (org-called-interactively-p 'any)
+    (if (and (called-interactively-p 'any)
             (or (and (eq last-command this-command) (mark t))
                 (and transient-mark-mode mark-active)))
        (set-mark
@@ -23751,13 +24768,10 @@ modified."
   (interactive)
   (unless (eq major-mode 'org-mode)
     (user-error "Cannot un-indent a buffer not in Org mode"))
-  (let* ((parse-tree (org-element-parse-buffer 'greater-element))
-        unindent-tree                  ; For byte-compiler.
-        (unindent-tree
-         (function
-          (lambda (contents)
-            (mapc
-             (lambda (element)
+  (letrec ((parse-tree (org-element-parse-buffer 'greater-element))
+          (unindent-tree
+           (lambda (contents)
+             (dolist (element (reverse contents))
                (if (memq (org-element-type element) '(headline section))
                    (funcall unindent-tree (org-element-contents element))
                  (save-excursion
@@ -23765,10 +24779,49 @@ modified."
                      (narrow-to-region
                       (org-element-property :begin element)
                       (org-element-property :end element))
-                     (org-do-remove-indentation)))))
-             (reverse contents))))))
+                     (org-do-remove-indentation))))))))
     (funcall unindent-tree (org-element-contents parse-tree))))
 
+(defun org-show-children (&optional level)
+  "Show all direct subheadings of this heading.
+Prefix arg LEVEL is how many levels below the current level
+should be shown.  Default is enough to cause the following
+heading to appear."
+  (interactive "p")
+  ;; If `orgstruct-mode' is active, use the slower version.
+  (if orgstruct-mode (call-interactively #'outline-show-children)
+    (save-excursion
+      (org-back-to-heading t)
+      (let* ((current-level (funcall outline-level))
+            (max-level (org-get-valid-level
+                        current-level
+                        (if level (prefix-numeric-value level) 1)))
+            (end (save-excursion (org-end-of-subtree t t)))
+            (regexp-fmt "^\\*\\{%d,%s\\}\\(?: \\|$\\)")
+            (past-first-child nil)
+            ;; Make sure to skip inlinetasks.
+            (re (format regexp-fmt
+                        current-level
+                        (cond
+                         ((not (featurep 'org-inlinetask)) "")
+                         (org-odd-levels-only (- (* 2 org-inlinetask-min-level)
+                                                 3))
+                         (t (1- org-inlinetask-min-level))))))
+       ;; Display parent heading.
+       (outline-flag-region (line-end-position 0) (line-end-position) nil)
+       (forward-line)
+       ;; Display children.  First child may be deeper than expected
+       ;; MAX-LEVEL.  Since we want to display it anyway, adjust
+       ;; MAX-LEVEL accordingly.
+       (while (re-search-forward re end t)
+         (unless past-first-child
+           (setq re (format regexp-fmt
+                            current-level
+                            (max (funcall outline-level) max-level)))
+           (setq past-first-child t))
+         (outline-flag-region
+          (line-end-position 0) (line-end-position) nil))))))
+
 (defun org-show-subtree ()
   "Show everything after this heading at deeper levels."
   (interactive)
@@ -23783,58 +24836,33 @@ modified."
 Show the heading too, if it is currently invisible."
   (interactive)
   (save-excursion
-    (condition-case nil
-       (progn
-         (org-back-to-heading t)
-         (outline-flag-region
-          (max (point-min) (1- (point)))
-          (save-excursion
-            (if (re-search-forward
-                 (concat "[\r\n]\\(" org-outline-regexp "\\)") nil t)
-                (match-beginning 1)
-              (point-max)))
-          nil)
-         (org-cycle-hide-drawers 'children))
-      (error nil))))
+    (ignore-errors
+      (org-back-to-heading t)
+      (outline-flag-region
+       (max (point-min) (1- (point)))
+       (save-excursion
+        (if (re-search-forward
+             (concat "[\r\n]\\(" org-outline-regexp "\\)") nil t)
+            (match-beginning 1)
+          (point-max)))
+       nil)
+      (org-cycle-hide-drawers 'children))))
 
 (defun org-make-options-regexp (kwds &optional extra)
-  "Make a regular expression for keyword lines."
-  (concat
-   "^#\\+\\("
-   (mapconcat 'regexp-quote kwds "\\|")
-   (if extra (concat "\\|" extra))
-   "\\):[ \t]*\\(.*\\)"))
-
-;; Make isearch reveal the necessary context
-(defun org-isearch-end ()
-  "Reveal context after isearch exits."
-  (when isearch-success ; only if search was successful
-    (if (featurep 'xemacs)
-       ;; Under XEmacs, the hook is run in the correct place,
-       ;; we directly show the context.
-       (org-show-context 'isearch)
-      ;; In Emacs the hook runs *before* restoring the overlays.
-      ;; So we have to use a one-time post-command-hook to do this.
-      ;; (Emacs 22 has a special variable, see function `org-mode')
-      (unless (and (boundp 'isearch-mode-end-hook-quit)
-                  isearch-mode-end-hook-quit)
-       ;; Only when the isearch was not quitted.
-       (org-add-hook 'post-command-hook 'org-isearch-post-command
-                     'append 'local)))))
-
-(defun org-isearch-post-command ()
-  "Remove self from hook, and show context."
-  (remove-hook 'post-command-hook 'org-isearch-post-command 'local)
-  (org-show-context 'isearch))
-
+  "Make a regular expression for keyword lines.
+KWDS is a list of keywords, as strings.  Optional argument EXTRA,
+when non-nil, is a regexp matching keywords names."
+  (concat "^[ \t]*#\\+\\("
+         (regexp-opt kwds)
+         (and extra (concat (and kwds "\\|") extra))
+         "\\):[ \t]*\\(.*\\)"))
 
 ;;;; Integration with and fixes for other packages
 
 ;;; Imenu support
 
-(defvar org-imenu-markers nil
+(defvar-local org-imenu-markers nil
   "All markers currently used by Imenu.")
-(make-variable-buffer-local 'org-imenu-markers)
 
 (defun org-imenu-new-marker (&optional pos)
   "Return a new marker for use by Imenu, and remember the marker."
@@ -23845,50 +24873,48 @@ Show the heading too, if it is currently invisible."
 
 (defun org-imenu-get-tree ()
   "Produce the index for Imenu."
-  (mapc (lambda (x) (move-marker x nil)) org-imenu-markers)
+  (dolist (x org-imenu-markers) (move-marker x nil))
   (setq org-imenu-markers nil)
-  (let* ((n org-imenu-depth)
+  (let* ((case-fold-search nil)
+        (n org-imenu-depth)
         (re (concat "^" (org-get-limited-outline-regexp)))
         (subs (make-vector (1+ n) nil))
         (last-level 0)
         m level head0 head)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-max))
-       (while (re-search-backward re nil t)
-         (setq level (org-reduced-level (funcall outline-level)))
-         (when (and (<= level n)
-                    (looking-at org-complex-heading-regexp)
-                    (setq head0 (org-match-string-no-properties 4)))
-           (setq head (org-link-display-format head0)
-                 m (org-imenu-new-marker))
-           (org-add-props head nil 'org-imenu-marker m 'org-imenu t)
-           (if (>= level last-level)
-               (push (cons head m) (aref subs level))
-             (push (cons head (aref subs (1+ level))) (aref subs level))
-             (loop for i from (1+ level) to n do (aset subs i nil)))
-           (setq last-level level)))))
+    (org-with-wide-buffer
+     (goto-char (point-max))
+     (while (re-search-backward re nil t)
+       (setq level (org-reduced-level (funcall outline-level)))
+       (when (and (<= level n)
+                 (looking-at org-complex-heading-regexp)
+                 (setq head0 (match-string-no-properties 4)))
+        (setq head (org-link-display-format head0)
+              m (org-imenu-new-marker))
+        (org-add-props head nil 'org-imenu-marker m 'org-imenu t)
+        (if (>= level last-level)
+            (push (cons head m) (aref subs level))
+          (push (cons head (aref subs (1+ level))) (aref subs level))
+          (cl-loop for i from (1+ level) to n do (aset subs i nil)))
+        (setq last-level level))))
     (aref subs 1)))
 
 (eval-after-load "imenu"
   '(progn
      (add-hook 'imenu-after-jump-hook
               (lambda ()
-                (if (derived-mode-p 'org-mode)
-                    (org-show-context 'org-goto))))))
+                (when (derived-mode-p 'org-mode)
+                  (org-show-context 'org-goto))))))
 
-(defun org-link-display-format (link)
-  "Replace a link with its the description.
+(defun org-link-display-format (s)
+  "Replace links in string S with their description.
 If there is no description, use the link target."
   (save-match-data
-    (if (string-match org-bracket-link-analytic-regexp link)
-       (replace-match (if (match-end 5)
-                          (match-string 5 link)
-                        (concat (match-string 1 link)
-                                (match-string 3 link)))
-                      nil t link)
-      link)))
+    (replace-regexp-in-string
+     org-bracket-link-analytic-regexp
+     (lambda (m)
+       (if (match-end 5) (match-string 5 m)
+        (concat (match-string 1 m) (match-string 3 m))))
+     s nil t)))
 
 (defun org-toggle-link-display ()
   "Toggle the literal or descriptive display of links."
@@ -23909,11 +24935,11 @@ If there is no description, use the link target."
             'face 'org-agenda-restriction-lock)
 (overlay-put org-speedbar-restriction-lock-overlay
             'help-echo "Agendas are currently limited to this item.")
-(org-detach-overlay org-speedbar-restriction-lock-overlay)
+(delete-overlay org-speedbar-restriction-lock-overlay)
 
 (defun org-speedbar-set-agenda-restriction ()
   "Restrict future agenda commands to the location at point in speedbar.
-To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]."
+To get rid of the restriction, use `\\[org-agenda-remove-restriction-lock]'."
   (interactive)
   (require 'org-agenda)
   (let (p m tp np dir txt)
@@ -23937,9 +24963,9 @@ To get rid of the restriction, use 
\\[org-agenda-remove-restriction-lock]."
                            (let ((default-directory dir))
                              (expand-file-name txt)))
        (unless (derived-mode-p 'org-mode)
-         (user-error "Cannot restrict to non-Org-mode file"))
+         (user-error "Cannot restrict to non-Org mode file"))
        (org-agenda-set-restriction-lock 'file)))
-     (t (user-error "Don't know how to restrict Org-mode's agenda")))
+     (t (user-error "Don't know how to restrict Org mode agenda")))
     (move-overlay org-speedbar-restriction-lock-overlay
                  (point-at-bol) (point-at-eol))
     (setq current-prefix-arg nil)
@@ -23959,34 +24985,98 @@ To get rid of the restriction, use 
\\[org-agenda-remove-restriction-lock]."
 
 ;;; Fixes and Hacks for problems with other packages
 
-;; Make flyspell not check words in links, to not mess up our keymap
-(defvar org-element-affiliated-keywords) ; From org-element.el
-(defvar org-element-block-name-alist)   ; From org-element.el
+(defun org--flyspell-object-check-p (element)
+  "Non-nil when Flyspell can check object at point.
+ELEMENT is the element at point."
+  (let ((object (save-excursion
+                 (when (looking-at-p "\\>") (backward-char))
+                 (org-element-context element))))
+    (cl-case (org-element-type object)
+      ;; Prevent checks in links due to keybinding conflict with
+      ;; Flyspell.
+      ((code entity export-snippet inline-babel-call
+            inline-src-block line-break latex-fragment link macro
+            statistics-cookie target timestamp verbatim)
+       nil)
+      (footnote-reference
+       ;; Only in inline footnotes, within the definition.
+       (and (eq (org-element-property :type object) 'inline)
+           (< (save-excursion
+                (goto-char (org-element-property :begin object))
+                (search-forward ":" nil t 2))
+              (point))))
+      (otherwise t))))
+
 (defun org-mode-flyspell-verify ()
-  "Don't let flyspell put overlays at active buttons, or on
-   {todo,all-time,additional-option-like}-keywords."
-  (require 'org-element) ; For `org-element-affiliated-keywords'
-  (let ((pos (max (1- (point)) (point-min)))
-       (word (thing-at-point 'word)))
-    (and (not (get-text-property pos 'keymap))
-        (not (get-text-property pos 'org-no-flyspell))
-        (not (member word org-todo-keywords-1))
-        (not (member word org-all-time-keywords))
-        (not (member word org-options-keywords))
-        (not (member word (mapcar 'car org-startup-options)))
-        (not (member-ignore-case word org-element-affiliated-keywords))
-        (not (member-ignore-case word (org-get-export-keywords)))
-        (not (member-ignore-case
-              word (mapcar 'car org-element-block-name-alist)))
-        (not (member-ignore-case word '("BEGIN" "END" "ATTR")))
-        (not (org-in-src-block-p)))))
+  "Function used for `flyspell-generic-check-word-predicate'."
+  (if (org-at-heading-p)
+      ;; At a headline or an inlinetask, check title only.  This is
+      ;; faster than relying on `org-element-at-point'.
+      (and (save-excursion (beginning-of-line)
+                          (and (let ((case-fold-search t))
+                                 (not (looking-at-p "\\*+ END[ \t]*$")))
+                               (let ((case-fold-search nil))
+                                 (looking-at org-complex-heading-regexp))))
+          (match-beginning 4)
+          (>= (point) (match-beginning 4))
+          (or (not (match-beginning 5))
+              (< (point) (match-beginning 5))))
+    (let* ((element (org-element-at-point))
+          (post-affiliated (org-element-property :post-affiliated element)))
+      (cond
+       ;; Ignore checks in all affiliated keywords but captions.
+       ((< (point) post-affiliated)
+       (and (save-excursion
+              (beginning-of-line)
+              (let ((case-fold-search t)) (looking-at "[ \t]*#\\+CAPTION:")))
+            (> (point) (match-end 0))
+            (org--flyspell-object-check-p element)))
+       ;; Ignore checks in LOGBOOK (or equivalent) drawer.
+       ((let ((log (org-log-into-drawer)))
+         (and log
+              (let ((drawer (org-element-lineage element '(drawer))))
+                (and drawer
+                     (eq (compare-strings
+                          log nil nil
+                          (org-element-property :drawer-name drawer) nil nil t)
+                         t)))))
+       nil)
+       (t
+       (cl-case (org-element-type element)
+         ((comment quote-section) t)
+         (comment-block
+          ;; Allow checks between block markers, not on them.
+          (and (> (line-beginning-position) post-affiliated)
+               (save-excursion
+                 (end-of-line)
+                 (skip-chars-forward " \r\t\n")
+                 (< (point) (org-element-property :end element)))))
+         ;; Arbitrary list of keywords where checks are meaningful.
+         ;; Make sure point is on the value part of the element.
+         (keyword
+          (and (member (org-element-property :key element)
+                       '("DESCRIPTION" "TITLE"))
+               (save-excursion
+                 (search-backward ":" (line-beginning-position) t))))
+         ;; Check is globally allowed in paragraphs verse blocks and
+         ;; table rows (after affiliated keywords) but some objects
+         ;; must not be affected.
+         ((paragraph table-row verse-block)
+          (let ((cbeg (org-element-property :contents-begin element))
+                (cend (org-element-property :contents-end element)))
+            (and cbeg (>= (point) cbeg) (< (point) cend)
+                 (org--flyspell-object-check-p element))))))))))
+(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
 
 (defun org-remove-flyspell-overlays-in (beg end)
   "Remove flyspell overlays in region."
-  (and (org-bound-and-true-p flyspell-mode)
+  (and (bound-and-true-p flyspell-mode)
        (fboundp 'flyspell-delete-region-overlays)
-       (flyspell-delete-region-overlays beg end))
-  (add-text-properties beg end '(org-no-flyspell t)))
+       (flyspell-delete-region-overlays beg end)))
+
+(defvar flyspell-delayed-commands)
+(eval-after-load "flyspell"
+  '(add-to-list 'flyspell-delayed-commands 'org-self-insert-command))
 
 ;; Make `bookmark-jump' shows the jump location if it was hidden.
 (eval-after-load "bookmark"
@@ -24008,17 +25098,38 @@ To get rid of the restriction, use 
\\[org-agenda-remove-restriction-lock]."
 (eval-after-load "ecb"
   '(defadvice ecb-method-clicked (after esf/org-show-context activate)
      "Make hierarchy visible when jumping into location from ECB tree buffer."
-     (if (derived-mode-p 'org-mode)
-        (org-show-context))))
+     (when (derived-mode-p 'org-mode)
+       (org-show-context))))
 
 (defun org-bookmark-jump-unhide ()
   "Unhide the current position, to show the bookmark location."
   (and (derived-mode-p 'org-mode)
-       (or (outline-invisible-p)
+       (or (org-invisible-p)
           (save-excursion (goto-char (max (point-min) (1- (point))))
-                          (outline-invisible-p)))
+                          (org-invisible-p)))
        (org-show-context 'bookmark-jump)))
 
+(defun org-mark-jump-unhide ()
+  "Make the point visible with `org-show-context' after jumping to the mark."
+  (when (and (derived-mode-p 'org-mode)
+            (org-invisible-p))
+    (org-show-context 'mark-goto)))
+
+(eval-after-load "simple"
+  '(defadvice pop-to-mark-command (after org-make-visible activate)
+     "Make the point visible with `org-show-context'."
+     (org-mark-jump-unhide)))
+
+(eval-after-load "simple"
+  '(defadvice exchange-point-and-mark (after org-make-visible activate)
+     "Make the point visible with `org-show-context'."
+     (org-mark-jump-unhide)))
+
+(eval-after-load "simple"
+  '(defadvice pop-global-mark (after org-make-visible activate)
+     "Make the point visible with `org-show-context'."
+     (org-mark-jump-unhide)))
+
 ;; Make session.el ignore our circular variable
 (defvar session-globals-exclude)
 (eval-after-load "session"
diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el
index 6ba70d7..2a129e9 100644
--- a/lisp/org/ox-ascii.el
+++ b/lisp/org/ox-ascii.el
@@ -1,4 +1,4 @@
-;;; ox-ascii.el --- ASCII Back-End for Org Export Engine
+;;; ox-ascii.el --- ASCII Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -27,9 +27,9 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
 (require 'ox)
 (require 'ox-publish)
+(require 'cl-lib)
 
 (declare-function aa2u "ext:ascii-art-to-unicode" ())
 
@@ -49,8 +49,6 @@
     (center-block . org-ascii-center-block)
     (clock . org-ascii-clock)
     (code . org-ascii-code)
-    (comment . (lambda (&rest args) ""))
-    (comment-block . (lambda (&rest args) ""))
     (drawer . org-ascii-drawer)
     (dynamic-block . org-ascii-dynamic-block)
     (entity . org-ascii-entity)
@@ -71,12 +69,13 @@
     (latex-fragment . org-ascii-latex-fragment)
     (line-break . org-ascii-line-break)
     (link . org-ascii-link)
+    (node-property . org-ascii-node-property)
     (paragraph . org-ascii-paragraph)
     (plain-list . org-ascii-plain-list)
     (plain-text . org-ascii-plain-text)
     (planning . org-ascii-planning)
+    (property-drawer . org-ascii-property-drawer)
     (quote-block . org-ascii-quote-block)
-    (quote-section . org-ascii-quote-section)
     (radio-target . org-ascii-radio-target)
     (section . org-ascii-section)
     (special-block . org-ascii-special-block)
@@ -94,7 +93,6 @@
     (underline . org-ascii-underline)
     (verbatim . org-ascii-verbatim)
     (verse-block . org-ascii-verse-block))
-  :export-block "ASCII"
   :menu-entry
   '(?t "Export to Plain Text"
        ((?A "As ASCII buffer"
@@ -119,7 +117,30 @@
                   (:filter-parse-tree org-ascii-filter-paragraph-spacing
                                       org-ascii-filter-comment-spacing)
                   (:filter-section . org-ascii-filter-headline-blank-lines))
-  :options-alist '((:ascii-charset nil nil org-ascii-charset)))
+  :options-alist
+  '((:subtitle "SUBTITLE" nil nil parse)
+    (:ascii-bullets nil nil org-ascii-bullets)
+    (:ascii-caption-above nil nil org-ascii-caption-above)
+    (:ascii-charset nil nil org-ascii-charset)
+    (:ascii-global-margin nil nil org-ascii-global-margin)
+    (:ascii-format-drawer-function nil nil org-ascii-format-drawer-function)
+    (:ascii-format-inlinetask-function
+     nil nil org-ascii-format-inlinetask-function)
+    (:ascii-headline-spacing nil nil org-ascii-headline-spacing)
+    (:ascii-indented-line-width nil nil org-ascii-indented-line-width)
+    (:ascii-inlinetask-width nil nil org-ascii-inlinetask-width)
+    (:ascii-inner-margin nil nil org-ascii-inner-margin)
+    (:ascii-links-to-notes nil nil org-ascii-links-to-notes)
+    (:ascii-list-margin nil nil org-ascii-list-margin)
+    (:ascii-paragraph-spacing nil nil org-ascii-paragraph-spacing)
+    (:ascii-quote-margin nil nil org-ascii-quote-margin)
+    (:ascii-table-keep-all-vertical-lines
+     nil nil org-ascii-table-keep-all-vertical-lines)
+    (:ascii-table-use-ascii-art nil nil org-ascii-table-use-ascii-art)
+    (:ascii-table-widen-columns nil nil org-ascii-table-widen-columns)
+    (:ascii-text-width nil nil org-ascii-text-width)
+    (:ascii-underline nil nil org-ascii-underline)
+    (:ascii-verbatim-format nil nil org-ascii-verbatim-format)))
 
 
 
@@ -162,6 +183,15 @@ This margin is applied on both sides of the text."
   :package-version '(Org . "8.0")
   :type 'integer)
 
+(defcustom org-ascii-list-margin 0
+  "Width of margin used for plain lists, in characters.
+This margin applies to top level list only, not to its
+sub-lists."
+  :group 'org-export-ascii
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'integer)
+
 (defcustom org-ascii-inlinetask-width 30
   "Width of inline tasks, in number of characters.
 This number ignores any margin."
@@ -339,7 +369,7 @@ Otherwise, place it right after it."
   :type 'string)
 
 (defcustom org-ascii-format-drawer-function
-  (lambda (name contents width) contents)
+  (lambda (_name contents _width) contents)
   "Function called to format a drawer in ASCII.
 
 The function must accept three parameters:
@@ -384,14 +414,18 @@ nil to ignore the inline task."
 
 ;; Internal functions fall into three categories.
 
-;; The first one is about text formatting.  The core function is
-;; `org-ascii--current-text-width', which determines the current
-;; text width allowed to a given element.  In other words, it helps
-;; keeping each line width within maximum text width defined in
-;; `org-ascii-text-width'.  Once this information is known,
-;; `org-ascii--fill-string', `org-ascii--justify-string',
-;; `org-ascii--box-string' and `org-ascii--indent-string' can
-;; operate on a given output string.
+;; The first one is about text formatting.  The core functions are
+;; `org-ascii--current-text-width' and
+;; `org-ascii--current-justification', which determine, respectively,
+;; the current text width allowed to a given element and its expected
+;; justification.  Once this information is known,
+;; `org-ascii--fill-string', `org-ascii--justify-lines',
+;; `org-ascii--justify-element' `org-ascii--box-string' and
+;; `org-ascii--indent-string' can operate on a given output string.
+;; In particular, justification happens at the regular (i.e.,
+;; non-greater) element level, which means that when the exporting
+;; process reaches a container (e.g., a center block) content are
+;; already justified.
 
 ;; The second category contains functions handling elements listings,
 ;; triggered by "#+TOC:" keyword.  As such, `org-ascii--build-toc'
@@ -420,7 +454,8 @@ a communication channel.
 Optional argument JUSTIFY can specify any type of justification
 among `left', `center', `right' or `full'.  A nil value is
 equivalent to `left'.  For a justification that doesn't also fill
-string, see `org-ascii--justify-string'.
+string, see `org-ascii--justify-lines' and
+`org-ascii--justify-block'.
 
 Return nil if S isn't a string."
   (when (stringp s)
@@ -435,8 +470,8 @@ Return nil if S isn't a string."
          (fill-region (point-min) (point-max) justify))
        (buffer-string)))))
 
-(defun org-ascii--justify-string (s text-width how)
-  "Justify string S.
+(defun org-ascii--justify-lines (s text-width how)
+  "Justify all lines in string S.
 TEXT-WIDTH is an integer specifying maximum length of a line.
 HOW determines the type of justification: it can be `left',
 `right', `full' or `center'."
@@ -452,6 +487,48 @@ HOW determines the type of justification: it can be `left',
        (forward-line)))
     (buffer-string)))
 
+(defun org-ascii--justify-element (contents element info)
+  "Justify CONTENTS of ELEMENT.
+INFO is a plist used as a communication channel.  Justification
+is done according to the type of element.  More accurately,
+paragraphs are filled and other elements are justified as blocks,
+that is according to the widest non blank line in CONTENTS."
+  (if (not (org-string-nw-p contents)) contents
+    (let ((text-width (org-ascii--current-text-width element info))
+         (how (org-ascii--current-justification element)))
+      (cond
+       ((eq (org-element-type element) 'paragraph)
+       ;; Paragraphs are treated specially as they need to be filled.
+       (org-ascii--fill-string contents text-width info how))
+       ((eq how 'left) contents)
+       (t (with-temp-buffer
+           (insert contents)
+           (goto-char (point-min))
+           (catch 'exit
+             (let ((max-width 0))
+               ;; Compute maximum width.  Bail out if it is greater
+               ;; than page width, since no justification is
+               ;; possible.
+               (save-excursion
+                 (while (not (eobp))
+                   (unless (looking-at-p "[ \t]*$")
+                     (end-of-line)
+                     (let ((column (current-column)))
+                       (cond
+                        ((>= column text-width) (throw 'exit contents))
+                        ((> column max-width) (setq max-width column)))))
+                   (forward-line)))
+               ;; Justify every line according to TEXT-WIDTH and
+               ;; MAX-WIDTH.
+               (let ((offset (/ (- text-width max-width)
+                                (if (eq how 'right) 1 2))))
+                 (if (zerop offset) (throw 'exit contents)
+                   (while (not (eobp))
+                     (unless (looking-at-p "[ \t]*$")
+                       (indent-to-column offset))
+                     (forward-line)))))
+             (buffer-string))))))))
+
 (defun org-ascii--indent-string (s width)
   "Indent string S by WIDTH white spaces.
 Empty lines are not indented."
@@ -472,26 +549,28 @@ INFO is a plist used as a communication channel."
 (defun org-ascii--current-text-width (element info)
   "Return maximum text width for ELEMENT's contents.
 INFO is a plist used as a communication channel."
-  (case (org-element-type element)
+  (pcase (org-element-type element)
     ;; Elements with an absolute width: `headline' and `inlinetask'.
-    (inlinetask org-ascii-inlinetask-width)
-    (headline
-     (- org-ascii-text-width
+    (`inlinetask (plist-get info :ascii-inlinetask-width))
+    (`headline
+     (- (plist-get info :ascii-text-width)
        (let ((low-level-rank (org-export-low-level-p element info)))
-         (if low-level-rank (* low-level-rank 2) org-ascii-global-margin))))
+         (if low-level-rank (* low-level-rank 2)
+           (plist-get info :ascii-global-margin)))))
     ;; Elements with a relative width: store maximum text width in
     ;; TOTAL-WIDTH.
-    (otherwise
-     (let* ((genealogy (cons element (org-export-get-genealogy element)))
+    (_
+     (let* ((genealogy (org-element-lineage element nil t))
            ;; Total width is determined by the presence, or not, of an
            ;; inline task among ELEMENT parents.
            (total-width
-            (if (loop for parent in genealogy
-                      thereis (eq (org-element-type parent) 'inlinetask))
-                org-ascii-inlinetask-width
+            (if (cl-some (lambda (parent)
+                           (eq (org-element-type parent) 'inlinetask))
+                         genealogy)
+                (plist-get info :ascii-inlinetask-width)
               ;; No inlinetask: Remove global margin from text width.
-              (- org-ascii-text-width
-                 org-ascii-global-margin
+              (- (plist-get info :ascii-text-width)
+                 (plist-get info :ascii-global-margin)
                  (let ((parent (org-export-get-parent-headline element)))
                    ;; Inner margin doesn't apply to text before first
                    ;; headline.
@@ -502,41 +581,67 @@ INFO is a plist used as a communication channel."
                        ;; low level headlines, since they've got their
                        ;; own indentation mechanism.
                        (if low-level-rank (* low-level-rank 2)
-                         org-ascii-inner-margin))))))))
+                         (plist-get info :ascii-inner-margin)))))))))
        (- total-width
-         ;; Each `quote-block', `quote-section' and `verse-block' above
-         ;; narrows text width by twice the standard margin size.
-         (+ (* (loop for parent in genealogy
-                     when (memq (org-element-type parent)
-                                '(quote-block quote-section verse-block))
-                     count parent)
-               2 org-ascii-quote-margin)
+         ;; Each `quote-block' and `verse-block' above narrows text
+         ;; width by twice the standard margin size.
+         (+ (* (cl-count-if (lambda (parent)
+                              (memq (org-element-type parent)
+                                    '(quote-block verse-block)))
+                            genealogy)
+               2
+               (plist-get info :ascii-quote-margin))
+            ;; Apply list margin once per "top-level" plain-list
+            ;; containing current line
+            (* (cl-count-if
+                (lambda (e)
+                  (and (eq (org-element-type e) 'plain-list)
+                       (not (eq (org-element-type (org-export-get-parent e))
+                                'item))))
+                genealogy)
+               (plist-get info :ascii-list-margin))
             ;; Text width within a plain-list is restricted by
             ;; indentation of current item.  If that's the case,
             ;; compute it with the help of `:structure' property from
             ;; parent item, if any.
-            (let ((parent-item
+            (let ((item
                    (if (eq (org-element-type element) 'item) element
-                     (loop for parent in genealogy
-                           when (eq (org-element-type parent) 'item)
-                           return parent))))
-              (if (not parent-item) 0
+                     (cl-find-if (lambda (parent)
+                                   (eq (org-element-type parent) 'item))
+                                 genealogy))))
+              (if (not item) 0
                 ;; Compute indentation offset of the current item,
                 ;; that is the sum of the difference between its
                 ;; indentation and the indentation of the top item in
                 ;; the list and current item bullet's length.  Also
                 ;; remove checkbox length, and tag length (for
                 ;; description lists) or bullet length.
-                (let ((struct (org-element-property :structure parent-item))
-                      (beg-item (org-element-property :begin parent-item)))
+                (let ((struct (org-element-property :structure item))
+                      (beg-item (org-element-property :begin item)))
                   (+ (- (org-list-get-ind beg-item struct)
                         (org-list-get-ind
                          (org-list-get-top-point struct) struct))
-                     (string-width (or (org-ascii--checkbox parent-item info)
+                     (string-width (or (org-ascii--checkbox item info)
                                        ""))
                      (string-width
-                      (or (org-list-get-tag beg-item struct)
-                          (org-list-get-bullet beg-item struct)))))))))))))
+                      (let ((tag (org-element-property :tag item)))
+                        (if tag (org-export-data tag info)
+                          (org-element-property :bullet item))))))))))))))
+
+(defun org-ascii--current-justification (element)
+  "Return expected justification for ELEMENT's contents.
+Return value is a symbol among `left', `center', `right' and
+`full'."
+  (let (justification)
+    (while (and (not justification)
+               (setq element (org-element-property :parent element)))
+      (pcase (org-element-type element)
+       (`center-block (setq justification 'center))
+       (`special-block
+        (let ((name (org-element-property :type element)))
+          (cond ((string= name "JUSTIFYRIGHT") (setq justification 'right))
+                ((string= name "JUSTIFYLEFT") (setq justification 'left)))))))
+    (or justification 'left)))
 
 (defun org-ascii--build-title
   (element info text-width &optional underline notags toc)
@@ -601,14 +706,14 @@ possible.  It doesn't apply to `inlinetask' elements."
        (let ((under-char
              (nth (1- (org-export-get-relative-level element info))
                   (cdr (assq (plist-get info :ascii-charset)
-                             org-ascii-underline)))))
+                             (plist-get info :ascii-underline))))))
         (and under-char
              (concat "\n"
                      (make-string (/ (string-width first-part)
                                      (char-width under-char))
                                   under-char))))))))
 
-(defun org-ascii--has-caption-p (element info)
+(defun org-ascii--has-caption-p (element _info)
   "Non-nil when ELEMENT has a caption affiliated keyword.
 INFO is a plist used as a communication channel.  This function
 is meant to be used as a predicate for `org-export-get-ordinal'."
@@ -630,9 +735,9 @@ caption keyword."
             (org-export-get-ordinal
              element info nil 'org-ascii--has-caption-p))
            (title-fmt (org-ascii--translate
-                       (case (org-element-type element)
-                         (table "Table %d:")
-                         (src-block "Listing %d:"))
+                       (pcase (org-element-type element)
+                         (`table "Table %d:")
+                         (`src-block "Listing %d:"))
                        info)))
        (org-ascii--fill-string
         (concat (format title-fmt reference)
@@ -640,7 +745,7 @@ caption keyword."
                 (org-export-data caption info))
         (org-ascii--current-text-width element info) info)))))
 
-(defun org-ascii--build-toc (info &optional n keyword)
+(defun org-ascii--build-toc (info &optional n keyword local)
   "Return a table of contents.
 
 INFO is a plist used as a communication channel.
@@ -649,28 +754,34 @@ Optional argument N, when non-nil, is an integer 
specifying the
 depth of the table.
 
 Optional argument KEYWORD specifies the TOC keyword, if any, from
-which the table of contents generation has been initiated."
-  (let ((title (org-ascii--translate "Table of Contents" info)))
-    (concat
-     title "\n"
-     (make-string (string-width title)
-                 (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
-     "\n\n"
-     (let ((text-width
-           (if keyword (org-ascii--current-text-width keyword info)
-             (- org-ascii-text-width org-ascii-global-margin))))
-       (mapconcat
-       (lambda (headline)
-         (let* ((level (org-export-get-relative-level headline info))
-                (indent (* (1- level) 3)))
-           (concat
-            (unless (zerop indent) (concat (make-string (1- indent) ?.) " "))
-            (org-ascii--build-title
-             headline info (- text-width indent) nil
-             (or (not (plist-get info :with-tags))
-                 (eq (plist-get info :with-tags) 'not-in-toc))
-             'toc))))
-       (org-export-collect-headlines info n) "\n")))))
+which the table of contents generation has been initiated.
+
+When optional argument LOCAL is non-nil, build a table of
+contents according to the current headline."
+  (concat
+   (unless local
+     (let ((title (org-ascii--translate "Table of Contents" info)))
+       (concat title "\n"
+              (make-string
+               (string-width title)
+               (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
+              "\n\n")))
+   (let ((text-width
+         (if keyword (org-ascii--current-text-width keyword info)
+           (- (plist-get info :ascii-text-width)
+              (plist-get info :ascii-global-margin)))))
+     (mapconcat
+      (lambda (headline)
+       (let* ((level (org-export-get-relative-level headline info))
+              (indent (* (1- level) 3)))
+         (concat
+          (unless (zerop indent) (concat (make-string (1- indent) ?.) " "))
+          (org-ascii--build-title
+           headline info (- text-width indent) nil
+           (or (not (plist-get info :with-tags))
+               (eq (plist-get info :with-tags) 'not-in-toc))
+           'toc))))
+      (org-export-collect-headlines info n (and local keyword)) "\n"))))
 
 (defun org-ascii--list-listings (keyword info)
   "Return a list of listings.
@@ -685,7 +796,8 @@ generation.  INFO is a plist used as a communication 
channel."
      "\n\n"
      (let ((text-width
            (if keyword (org-ascii--current-text-width keyword info)
-             (- org-ascii-text-width org-ascii-global-margin)))
+             (- (plist-get info :ascii-text-width)
+                (plist-get info :ascii-global-margin))))
           ;; Use a counter instead of retrieving ordinal of each
           ;; src-block.
           (count 0))
@@ -696,7 +808,7 @@ generation.  INFO is a plist used as a communication 
channel."
          ;; filling (like contents of a description list item).
          (let* ((initial-text
                  (format (org-ascii--translate "Listing %d:" info)
-                         (incf count)))
+                         (cl-incf count)))
                 (initial-width (string-width initial-text)))
            (concat
             initial-text " "
@@ -724,7 +836,8 @@ generation.  INFO is a plist used as a communication 
channel."
      "\n\n"
      (let ((text-width
            (if keyword (org-ascii--current-text-width keyword info)
-             (- org-ascii-text-width org-ascii-global-margin)))
+             (- (plist-get info :ascii-text-width)
+                (plist-get info :ascii-global-margin))))
           ;; Use a counter instead of retrieving ordinal of each
           ;; src-block.
           (count 0))
@@ -735,7 +848,7 @@ generation.  INFO is a plist used as a communication 
channel."
          ;; filling (like contents of a description list item).
          (let* ((initial-text
                  (format (org-ascii--translate "Table %d:" info)
-                         (incf count)))
+                         (cl-incf count)))
                 (initial-width (string-width initial-text)))
            (concat
             initial-text " "
@@ -756,69 +869,105 @@ ELEMENT is either a headline element or a section 
element.  INFO
 is a plist used as a communication channel."
   (let* (seen
         (unique-link-p
-         (function
-          ;; Return LINK if it wasn't referenced so far, or nil.
-          ;; Update SEEN links along the way.
-          (lambda (link)
-            (let ((footprint
-                   ;; Normalize description in footprints.
-                   (cons (org-element-property :raw-link link)
-                         (let ((contents (org-element-contents link)))
-                           (and contents
-                                (replace-regexp-in-string
-                                 "[ \r\t\n]+" " "
-                                 (org-trim
-                                  (org-element-interpret-data contents))))))))
-              ;; Ignore LINK if it hasn't been translated already.
-              ;; It can happen if it is located in an affiliated
-              ;; keyword that was ignored.
-              (when (and (org-string-nw-p
-                          (gethash link (plist-get info :exported-data)))
-                         (not (member footprint seen)))
-                (push footprint seen) link)))))
-        ;; If at a section, find parent headline, if any, in order to
-        ;; count links that might be in the title.
-        (headline
-         (if (eq (org-element-type element) 'headline) element
-           (or (org-export-get-parent-headline element) element))))
-    ;; Get all links in HEADLINE.
-    (org-element-map headline 'link
-      (lambda (l) (funcall unique-link-p l)) info nil nil t)))
+         ;; Return LINK if it wasn't referenced so far, or nil.
+         ;; Update SEEN links along the way.
+         (lambda (link)
+           (let ((footprint
+                  ;; Normalize description in footprints.
+                  (cons (org-element-property :raw-link link)
+                        (let ((contents (org-element-contents link)))
+                          (and contents
+                               (replace-regexp-in-string
+                                "[ \r\t\n]+" " "
+                                (org-trim
+                                 (org-element-interpret-data contents))))))))
+             ;; Ignore LINK if it hasn't been translated already.  It
+             ;; can happen if it is located in an affiliated keyword
+             ;; that was ignored.
+             (when (and (org-string-nw-p
+                         (gethash link (plist-get info :exported-data)))
+                        (not (member footprint seen)))
+               (push footprint seen) link)))))
+    (org-element-map (if (eq (org-element-type element) 'section)
+                        element
+                      ;; In a headline, only retrieve links in title
+                      ;; and relative section, not in children.
+                      (list (org-element-property :title element)
+                            (car (org-element-contents element))))
+       'link unique-link-p info nil 'headline t)))
+
+(defun org-ascii--describe-datum (datum info)
+  "Describe DATUM object or element.
+If DATUM is a string, consider it to be a file name, per
+`org-export-resolve-id-link'.  INFO is the communication channel,
+as a plist."
+  (pcase (org-element-type datum)
+    (`plain-text (format "See file %s" datum)) ;External file
+    (`headline
+     (format (org-ascii--translate "See section %s" info)
+            (if (org-export-numbered-headline-p datum info)
+                (mapconcat #'number-to-string
+                           (org-export-get-headline-number datum info)
+                           ".")
+              (org-export-data (org-element-property :title datum) info))))
+    (_
+     (let ((number (org-export-get-ordinal
+                   datum info nil #'org-ascii--has-caption-p))
+          ;; If destination is a target, make sure we can name the
+          ;; container it refers to.
+          (enumerable
+           (org-element-lineage datum '(headline paragrah src-block table) t)))
+       (pcase (org-element-type enumerable)
+        (`headline
+         (format (org-ascii--translate "See section %s" info)
+                 (if (org-export-numbered-headline-p enumerable info)
+                     (mapconcat #'number-to-string number ".")
+                   (org-export-data
+                    (org-element-property :title enumerable) info))))
+        ((guard (not number))
+         (org-ascii--translate "Unknown reference" info))
+        (`paragraph
+         (format (org-ascii--translate "See figure %s" info) number))
+        (`src-block
+         (format (org-ascii--translate "See listing %s" info) number))
+        (`table
+         (format (org-ascii--translate "See table %s" info) number))
+        (_ (org-ascii--translate "Unknown reference" info)))))))
 
 (defun org-ascii--describe-links (links width info)
   "Return a string describing a list of links.
-
 LINKS is a list of link type objects, as returned by
 `org-ascii--unique-links'.  WIDTH is the text width allowed for
 the output string.  INFO is a plist used as a communication
 channel."
   (mapconcat
    (lambda (link)
-     (let ((type (org-element-property :type link))
-          (anchor (let ((desc (org-element-contents link)))
-                    (if desc (org-export-data desc info)
-                      (org-element-property :raw-link link)))))
+     (let* ((type (org-element-property :type link))
+           (description (org-element-contents link))
+           (anchor (org-export-data
+                    (or description (org-element-property :raw-link link))
+                    info)))
        (cond
-       ;; Coderefs, radio links and fuzzy links are ignored.
-       ((member type '("coderef" "radio" "fuzzy")) nil)
-       ;; Id and custom-id links: Headlines refer to their numbering.
-       ((member type '("custom-id" "id"))
-        (let ((dest (org-export-resolve-id-link link info)))
-          (concat
-           (org-ascii--fill-string
-            (format
-             "[%s] %s"
-             anchor
-             (if (not dest) (org-ascii--translate "Unknown reference" info)
-               (format
-                (org-ascii--translate "See section %s" info)
-                (mapconcat 'number-to-string
-                           (org-export-get-headline-number dest info) "."))))
-            width info) "\n\n")))
+       ((member type '("coderef" "radio")) nil)
+       ((member type '("custom-id" "fuzzy" "id"))
+        ;; Only links with a description need an entry.  Other are
+        ;; already handled in `org-ascii-link'.
+        (when description
+          (let ((dest (if (equal type "fuzzy")
+                          (org-export-resolve-fuzzy-link link info)
+                        (org-export-resolve-id-link link info))))
+            (concat
+             (org-ascii--fill-string
+              (format "[%s] %s" anchor (org-ascii--describe-datum dest info))
+              width info)
+             "\n\n"))))
        ;; Do not add a link that cannot be resolved and doesn't have
        ;; any description: destination is already visible in the
        ;; paragraph.
        ((not (org-element-contents link)) nil)
+       ;; Do not add a link already handled by custom export
+       ;; functions.
+       ((org-export-custom-protocol-maybe link anchor 'ascii) nil)
        (t
         (concat
          (org-ascii--fill-string
@@ -831,10 +980,10 @@ channel."
   "Return checkbox string for ITEM or nil.
 INFO is a plist used as a communication channel."
   (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)))
-    (case (org-element-property :checkbox item)
-      (on (if utf8p "☑ " "[X] "))
-      (off (if utf8p "☐ " "[ ] "))
-      (trans (if utf8p "☒ " "[-] ")))))
+    (pcase (org-element-property :checkbox item)
+      (`on (if utf8p "☑ " "[X] "))
+      (`off (if utf8p "☐ " "[ ] "))
+      (`trans (if utf8p "☒ " "[-] ")))))
 
 
 
@@ -843,11 +992,15 @@ INFO is a plist used as a communication channel."
 (defun org-ascii-template--document-title (info)
   "Return document title, as a string.
 INFO is a plist used as a communication channel."
-  (let* ((text-width org-ascii-text-width)
+  (let* ((text-width (plist-get info :ascii-text-width))
         ;; Links in the title will not be resolved later, so we make
         ;; sure their path is located right after them.
-        (org-ascii-links-to-notes nil)
-        (title (org-export-data (plist-get info :title) info))
+        (info (org-combine-plists info '(:ascii-links-to-notes nil)))
+        (with-title (plist-get info :with-title))
+        (title (org-export-data
+                (when with-title (plist-get info :title)) info))
+        (subtitle (org-export-data
+                   (when with-title (plist-get info :subtitle)) info))
         (author (and (plist-get info :with-author)
                      (let ((auth (plist-get info :author)))
                        (and auth (org-export-data auth info)))))
@@ -878,7 +1031,7 @@ INFO is a plist used as a communication channel."
           date "\n\n\n"))
         ((org-string-nw-p date)
          (concat
-          (org-ascii--justify-string date text-width 'right)
+          (org-ascii--justify-lines date text-width 'right)
           "\n\n\n"))
         ((and (org-string-nw-p author) (org-string-nw-p email))
          (concat author "\n" email "\n\n\n"))
@@ -890,8 +1043,14 @@ INFO is a plist used as a communication channel."
       (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))
             ;; Format TITLE.  It may be filled if it is too wide,
             ;; that is wider than the two thirds of the total width.
-            (title-len (min (length title) (/ (* 2 text-width) 3)))
+            (title-len (min (apply #'max
+                                   (mapcar #'length
+                                           (org-split-string
+                                            (concat title "\n" subtitle) 
"\n")))
+                            (/ (* 2 text-width) 3)))
             (formatted-title (org-ascii--fill-string title title-len info))
+            (formatted-subtitle (when (org-string-nw-p subtitle)
+                                  (org-ascii--fill-string subtitle title-len 
info)))
             (line
              (make-string
               (min (+ (max title-len
@@ -899,17 +1058,16 @@ INFO is a plist used as a communication channel."
                            (string-width (or email "")))
                       2)
                    text-width) (if utf8p ?━ ?_))))
-       (org-ascii--justify-string
+       (org-ascii--justify-lines
         (concat line "\n"
                 (unless utf8p "\n")
                 (upcase formatted-title)
+                (and formatted-subtitle (concat "\n" formatted-subtitle))
                 (cond
                  ((and (org-string-nw-p author) (org-string-nw-p email))
-                  (concat (if utf8p "\n\n\n" "\n\n") author "\n" email))
-                 ((org-string-nw-p author)
-                  (concat (if utf8p "\n\n\n" "\n\n") author))
-                 ((org-string-nw-p email)
-                  (concat (if utf8p "\n\n\n" "\n\n") email)))
+                  (concat "\n\n" author "\n" email))
+                 ((org-string-nw-p author) (concat "\n\n" author))
+                 ((org-string-nw-p email) (concat "\n\n" email)))
                 "\n" line
                 (when (org-string-nw-p date) (concat "\n\n\n" date))
                 "\n\n\n") text-width 'center)))))
@@ -919,81 +1077,83 @@ INFO is a plist used as a communication channel."
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
   (org-element-normalize-string
-   (org-ascii--indent-string
-    (concat
-     ;; 1. Document's body.
-     contents
-     ;; 2. Footnote definitions.
-     (let ((definitions (org-export-collect-footnote-definitions
-                        (plist-get info :parse-tree) info))
-          ;; Insert full links right inside the footnote definition
-          ;; as they have no chance to be inserted later.
-          (org-ascii-links-to-notes nil))
-       (when definitions
-        (concat
-         "\n\n\n"
-         (let ((title (org-ascii--translate "Footnotes" info)))
-           (concat
-            title "\n"
-            (make-string
-             (string-width title)
-             (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))))
-         "\n\n"
-         (let ((text-width (- org-ascii-text-width org-ascii-global-margin)))
-           (mapconcat
-            (lambda (ref)
-              (let ((id (format "[%s] " (car ref))))
-                ;; Distinguish between inline definitions and
-                ;; full-fledged definitions.
-                (org-trim
-                 (let ((def (nth 2 ref)))
-                   (if (eq (org-element-type def) 'org-data)
-                       ;; Full-fledged definition: footnote ID is
-                       ;; inserted inside the first parsed paragraph
-                       ;; (FIRST), if any, to be sure filling will
-                       ;; take it into consideration.
-                       (let ((first (car (org-element-contents def))))
-                         (if (not (eq (org-element-type first) 'paragraph))
-                             (concat id "\n" (org-export-data def info))
-                           (push id (nthcdr 2 first))
-                           (org-export-data def info)))
-                     ;; Fill paragraph once footnote ID is inserted
-                     ;; in order to have a correct length for first
-                     ;; line.
-                     (org-ascii--fill-string
-                      (concat id (org-export-data def info))
-                      text-width info))))))
-            definitions "\n\n"))))))
-    org-ascii-global-margin)))
+   (let ((global-margin (plist-get info :ascii-global-margin)))
+     (org-ascii--indent-string
+      (concat
+       ;; 1. Document's body.
+       contents
+       ;; 2. Footnote definitions.
+       (let ((definitions (org-export-collect-footnote-definitions info))
+            ;; Insert full links right inside the footnote definition
+            ;; as they have no chance to be inserted later.
+            (info (org-combine-plists info '(:ascii-links-to-notes nil))))
+        (when definitions
+          (concat
+           "\n\n\n"
+           (let ((title (org-ascii--translate "Footnotes" info)))
+             (concat
+              title "\n"
+              (make-string
+               (string-width title)
+               (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))))
+           "\n\n"
+           (let ((text-width (- (plist-get info :ascii-text-width)
+                                global-margin)))
+             (mapconcat
+              (lambda (ref)
+                (let ((id (format "[%s] " (car ref))))
+                  ;; Distinguish between inline definitions and
+                  ;; full-fledged definitions.
+                  (org-trim
+                   (let ((def (nth 2 ref)))
+                     (if (org-element-map def org-element-all-elements
+                           #'identity info 'first-match)
+                         ;; Full-fledged definition: footnote ID is
+                         ;; inserted inside the first parsed
+                         ;; paragraph (FIRST), if any, to be sure
+                         ;; filling will take it into consideration.
+                         (let ((first (car (org-element-contents def))))
+                           (if (not (eq (org-element-type first) 'paragraph))
+                               (concat id "\n" (org-export-data def info))
+                             (push id (nthcdr 2 first))
+                             (org-export-data def info)))
+                       ;; Fill paragraph once footnote ID is inserted
+                       ;; in order to have a correct length for first
+                       ;; line.
+                       (org-ascii--fill-string
+                        (concat id (org-export-data def info))
+                        text-width info))))))
+              definitions "\n\n"))))))
+      global-margin))))
 
 (defun org-ascii-template (contents info)
   "Return complete document string after ASCII conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
-  (concat
-   ;; 1. Build title block.
-   (org-ascii--indent-string
-    (concat (org-ascii-template--document-title info)
-           ;; 2. Table of contents.
-           (let ((depth (plist-get info :with-toc)))
-             (when depth
-               (concat
-                (org-ascii--build-toc info (and (wholenump depth) depth))
-                "\n\n\n"))))
-    org-ascii-global-margin)
-   ;; 3. Document's body.
-   contents
-   ;; 4. Creator.  Ignore `comment' value as there are no comments in
-   ;;    ASCII.  Justify it to the bottom right.
-   (org-ascii--indent-string
-    (let ((creator-info (plist-get info :with-creator))
-         (text-width (- org-ascii-text-width org-ascii-global-margin)))
-      (unless (or (not creator-info) (eq creator-info 'comment))
-       (concat
-        "\n\n\n"
-        (org-ascii--fill-string
-         (plist-get info :creator) text-width info 'right))))
-    org-ascii-global-margin)))
+  (let ((global-margin (plist-get info :ascii-global-margin)))
+    (concat
+     ;; Build title block.
+     (org-ascii--indent-string
+      (concat (org-ascii-template--document-title info)
+             ;; 2. Table of contents.
+             (let ((depth (plist-get info :with-toc)))
+               (when depth
+                 (concat
+                  (org-ascii--build-toc info (and (wholenump depth) depth))
+                  "\n\n\n"))))
+      global-margin)
+     ;; Document's body.
+     contents
+     ;; Creator.  Justify it to the bottom right.
+     (and (plist-get info :with-creator)
+         (org-ascii--indent-string
+          (let ((text-width
+                 (- (plist-get info :ascii-text-width) global-margin)))
+            (concat
+             "\n\n\n"
+             (org-ascii--fill-string
+              (plist-get info :creator) text-width info 'right)))
+          global-margin)))))
 
 (defun org-ascii--translate (s info)
   "Translate string S according to specified language and charset.
@@ -1007,7 +1167,7 @@ INFO is a plist used as a communication channel."
 
 ;;;; Bold
 
-(defun org-ascii-bold (bold contents info)
+(defun org-ascii-bold (_bold contents _info)
   "Transcode BOLD from Org to ASCII.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
@@ -1016,39 +1176,41 @@ contextual information."
 
 ;;;; Center Block
 
-(defun org-ascii-center-block (center-block contents info)
+(defun org-ascii-center-block (_center-block contents _info)
   "Transcode a CENTER-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (org-ascii--justify-string
-   contents (org-ascii--current-text-width center-block info) 'center))
+  ;; Center has already been taken care of at a lower level, so
+  ;; there's nothing left to do.
+  contents)
 
 
 ;;;; Clock
 
-(defun org-ascii-clock (clock contents info)
+(defun org-ascii-clock (clock _contents info)
   "Transcode a CLOCK object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (concat org-clock-string " "
-         (org-translate-time
-          (org-element-property :raw-value
-                                (org-element-property :value clock)))
-         (let ((time (org-element-property :duration clock)))
-           (and time
-                (concat " => "
-                        (apply 'format
-                               "%2s:%02s"
-                               (org-split-string time ":")))))))
+  (org-ascii--justify-element
+   (concat org-clock-string " "
+          (org-timestamp-translate (org-element-property :value clock))
+          (let ((time (org-element-property :duration clock)))
+            (and time
+                 (concat " => "
+                         (apply 'format
+                                "%2s:%02s"
+                                (org-split-string time ":"))))))
+   clock info))
 
 
 ;;;; Code
 
-(defun org-ascii-code (code contents info)
+(defun org-ascii-code (code _contents info)
   "Return a CODE object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format org-ascii-verbatim-format (org-element-property :value code)))
+  (format (plist-get info :ascii-verbatim-format)
+         (org-element-property :value code)))
 
 
 ;;;; Drawer
@@ -1059,12 +1221,13 @@ CONTENTS holds the contents of the block.  INFO is a 
plist
 holding contextual information."
   (let ((name (org-element-property :drawer-name drawer))
        (width (org-ascii--current-text-width drawer info)))
-    (funcall org-ascii-format-drawer-function name contents width)))
+    (funcall (plist-get info :ascii-format-drawer-function)
+            name contents width)))
 
 
 ;;;; Dynamic Block
 
-(defun org-ascii-dynamic-block (dynamic-block contents info)
+(defun org-ascii-dynamic-block (_dynamic-block contents _info)
   "Transcode a DYNAMIC-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
@@ -1073,7 +1236,7 @@ holding contextual information."
 
 ;;;; Entity
 
-(defun org-ascii-entity (entity contents info)
+(defun org-ascii-entity (entity _contents info)
   "Transcode an ENTITY object from Org to ASCII.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
@@ -1084,16 +1247,18 @@ contextual information."
 
 ;;;; Example Block
 
-(defun org-ascii-example-block (example-block contents info)
+(defun org-ascii-example-block (example-block _contents info)
   "Transcode a EXAMPLE-BLOCK element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (org-ascii--box-string
-   (org-export-format-code-default example-block info) info))
+  (org-ascii--justify-element
+   (org-ascii--box-string
+    (org-export-format-code-default example-block info) info)
+   example-block info))
 
 
 ;;;; Export Snippet
 
-(defun org-ascii-export-snippet (export-snippet contents info)
+(defun org-ascii-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (eq (org-export-snippet-backend export-snippet) 'ascii)
@@ -1102,21 +1267,24 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Export Block
 
-(defun org-ascii-export-block (export-block contents info)
+(defun org-ascii-export-block (export-block _contents info)
   "Transcode a EXPORT-BLOCK element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (string= (org-element-property :type export-block) "ASCII")
-    (org-remove-indentation (org-element-property :value export-block))))
+    (org-ascii--justify-element
+     (org-element-property :value export-block) export-block info)))
 
 
 ;;;; Fixed Width
 
-(defun org-ascii-fixed-width (fixed-width contents info)
+(defun org-ascii-fixed-width (fixed-width _contents info)
   "Transcode a FIXED-WIDTH element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (org-ascii--box-string
-   (org-remove-indentation
-    (org-element-property :value fixed-width)) info))
+  (org-ascii--justify-element
+   (org-ascii--box-string
+    (org-remove-indentation
+     (org-element-property :value fixed-width)) info)
+   fixed-width info))
 
 
 ;;;; Footnote Definition
@@ -1127,7 +1295,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Footnote Reference
 
-(defun org-ascii-footnote-reference (footnote-reference contents info)
+(defun org-ascii-footnote-reference (footnote-reference _contents info)
   "Transcode a FOOTNOTE-REFERENCE element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (format "[%s]" (org-export-get-footnote-number footnote-reference info)))
@@ -1142,57 +1310,62 @@ holding contextual information."
   ;; Don't export footnote section, which will be handled at the end
   ;; of the template.
   (unless (org-element-property :footnote-section-p headline)
-    (let* ((low-level-rank (org-export-low-level-p headline info))
+    (let* ((low-level (org-export-low-level-p headline info))
           (width (org-ascii--current-text-width headline info))
+          ;; Export title early so that any link in it can be
+          ;; exported and seen in `org-ascii--unique-links'.
+          (title (org-ascii--build-title headline info width (not low-level)))
           ;; Blank lines between headline and its contents.
           ;; `org-ascii-headline-spacing', when set, overwrites
           ;; original buffer's spacing.
           (pre-blanks
-           (make-string
-            (if org-ascii-headline-spacing (car org-ascii-headline-spacing)
-              (org-element-property :pre-blank headline)) ?\n))
-          ;; Even if HEADLINE has no section, there might be some
-          ;; links in its title that we shouldn't forget to describe.
-          (links
-           (unless (or (eq (caar (org-element-contents headline)) 'section))
-             (let ((title (org-element-property :title headline)))
-               (when (consp title)
-                 (org-ascii--describe-links
-                  (org-ascii--unique-links title info) width info))))))
+           (make-string (or (car (plist-get info :ascii-headline-spacing))
+                            (org-element-property :pre-blank headline)
+                            0)
+                        ?\n))
+          (links (and (plist-get info :ascii-links-to-notes)
+                      (org-ascii--describe-links
+                       (org-ascii--unique-links headline info) width info)))
+          ;; Re-build contents, inserting section links at the right
+          ;; place.  The cost is low since build results are cached.
+          (body
+           (if (not (org-string-nw-p links)) contents
+             (let* ((contents (org-element-contents headline))
+                    (section (let ((first (car contents)))
+                               (and (eq (org-element-type first) 'section)
+                                    first))))
+               (concat (and section
+                            (concat (org-element-normalize-string
+                                     (org-export-data section info))
+                                    "\n\n"))
+                       links
+                       (mapconcat (lambda (e) (org-export-data e info))
+                                  (if section (cdr contents) contents)
+                                  ""))))))
       ;; Deep subtree: export it as a list item.
-      (if low-level-rank
-         (concat
-          ;; Bullet.
-          (let ((bullets (cdr (assq (plist-get info :ascii-charset)
-                                    org-ascii-bullets))))
-            (char-to-string
-             (nth (mod (1- low-level-rank) (length bullets)) bullets)))
-          " "
-          ;; Title.
-          (org-ascii--build-title headline info width) "\n"
-          ;; Contents, indented by length of bullet.
-          pre-blanks
-          (org-ascii--indent-string
-           (concat contents
-                   (when (org-string-nw-p links) (concat "\n\n" links)))
-           2))
+      (if low-level
+         (let* ((bullets (cdr (assq (plist-get info :ascii-charset)
+                                    (plist-get info :ascii-bullets))))
+                (bullet
+                 (format "%c "
+                         (nth (mod (1- low-level) (length bullets)) bullets))))
+           (concat bullet title "\n" pre-blanks
+                   ;; Contents, indented by length of bullet.
+                   (org-ascii--indent-string body (length bullet))))
        ;; Else: Standard headline.
-       (concat
-        (org-ascii--build-title headline info width 'underline)
-        "\n" pre-blanks
-        (concat (when (org-string-nw-p links) links) contents))))))
+       (concat title "\n" pre-blanks body)))))
 
 
 ;;;; Horizontal Rule
 
-(defun org-ascii-horizontal-rule (horizontal-rule contents info)
+(defun org-ascii-horizontal-rule (horizontal-rule _contents info)
   "Transcode an HORIZONTAL-RULE object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (let ((text-width (org-ascii--current-text-width horizontal-rule info))
        (spec-width
         (org-export-read-attribute :attr_ascii horizontal-rule :width)))
-    (org-ascii--justify-string
+    (org-ascii--justify-lines
      (make-string (if (and spec-width (string-match "^[0-9]+$" spec-width))
                      (string-to-number spec-width)
                    text-width)
@@ -1202,23 +1375,23 @@ information."
 
 ;;;; Inline Src Block
 
-(defun org-ascii-inline-src-block (inline-src-block contents info)
+(defun org-ascii-inline-src-block (inline-src-block _contents info)
   "Transcode an INLINE-SRC-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (format org-ascii-verbatim-format
+  (format (plist-get info :ascii-verbatim-format)
          (org-element-property :value inline-src-block)))
 
 
 ;;;; Inlinetask
 
 (defun org-ascii-format-inlinetask-default
-  (todo type priority name tags contents width inlinetask info)
+  (_todo _type _priority _name _tags contents width inlinetask info)
   "Format an inline task element for ASCII export.
 See `org-ascii-format-inlinetask-function' for a description
 of the parameters."
   (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))
-        (width (or width org-ascii-inlinetask-width)))
+        (width (or width (plist-get info :ascii-inlinetask-width))))
     (org-ascii--indent-string
      (concat
       ;; Top line, with an additional blank line if not in UTF-8.
@@ -1236,9 +1409,9 @@ of the parameters."
       ;; Bottom line.
       (make-string width (if utf8p ?━ ?_)))
      ;; Flush the inlinetask to the right.
-     (- org-ascii-text-width org-ascii-global-margin
+     (- (plist-get info :ascii-text-width) (plist-get info 
:ascii-global-margin)
        (if (not (org-export-get-parent-headline inlinetask)) 0
-         org-ascii-inner-margin)
+         (plist-get info :ascii-inner-margin))
        (org-ascii--current-text-width inlinetask info)))))
 
 (defun org-ascii-inlinetask (inlinetask contents info)
@@ -1246,7 +1419,7 @@ of the parameters."
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   (let ((width (org-ascii--current-text-width inlinetask info)))
-    (funcall org-ascii-format-inlinetask-function
+    (funcall (plist-get info :ascii-format-inlinetask-function)
             ;; todo.
             (and (plist-get info :with-todo-keywords)
                  (let ((todo (org-element-property
@@ -1268,7 +1441,7 @@ holding contextual information."
 
 ;;;; Italic
 
-(defun org-ascii-italic (italic contents info)
+(defun org-ascii-italic (_italic contents _info)
   "Transcode italic from Org to ASCII.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
@@ -1288,12 +1461,12 @@ contextual information."
          ;; First parent of ITEM is always the plain-list.  Get
          ;; `:type' property from it.
          (org-list-bullet-string
-          (case list-type
-            (descriptive
+          (pcase list-type
+            (`descriptive
              (concat checkbox
                      (org-export-data (org-element-property :tag item) info)
                      ": "))
-            (ordered
+            (`ordered
              ;; Return correct number for ITEM, paying attention to
              ;; counters.
              (let* ((struct (org-element-property :structure item))
@@ -1305,7 +1478,7 @@ contextual information."
                                       (org-list-prevs-alist struct)
                                       (org-list-parents-alist struct)))))))
                (replace-regexp-in-string "[0-9]+" num bul)))
-            (t (let ((bul (org-element-property :bullet item)))
+            (_ (let ((bul (org-element-property :bullet item)))
                  ;; Change bullets into more visible form if UTF-8 is active.
                  (if (not utf8p) bul
                    (replace-regexp-in-string
@@ -1327,42 +1500,45 @@ contextual information."
 
 ;;;; Keyword
 
-(defun org-ascii-keyword (keyword contents info)
+(defun org-ascii-keyword (keyword _contents info)
   "Transcode a KEYWORD element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (let ((key (org-element-property :key keyword))
        (value (org-element-property :value keyword)))
     (cond
-     ((string= key "ASCII") value)
+     ((string= key "ASCII") (org-ascii--justify-element value keyword info))
      ((string= key "TOC")
-      (let ((value (downcase value)))
-       (cond
-        ((string-match "\\<headlines\\>" value)
-         (let ((depth (or (and (string-match "[0-9]+" value)
-                               (string-to-number (match-string 0 value)))
-                          (plist-get info :with-toc))))
-           (org-ascii--build-toc
-            info (and (wholenump depth) depth) keyword)))
-        ((string= "tables" value)
-         (org-ascii--list-tables keyword info))
-        ((string= "listings" value)
-         (org-ascii--list-listings keyword info))))))))
+      (org-ascii--justify-element
+       (let ((case-fold-search t))
+        (cond
+         ((string-match-p "\\<headlines\\>" value)
+          (let ((depth (and (string-match "\\<[0-9]+\\>" value)
+                            (string-to-number (match-string 0 value))))
+                (localp (string-match-p "\\<local\\>" value)))
+            (org-ascii--build-toc info depth keyword localp)))
+         ((string-match-p "\\<tables\\>" value)
+          (org-ascii--list-tables keyword info))
+         ((string-match-p "\\<listings\\>" value)
+          (org-ascii--list-listings keyword info))))
+       keyword info)))))
 
 
 ;;;; Latex Environment
 
-(defun org-ascii-latex-environment (latex-environment contents info)
+(defun org-ascii-latex-environment (latex-environment _contents info)
   "Transcode a LATEX-ENVIRONMENT element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (when (plist-get info :with-latex)
-    (org-remove-indentation (org-element-property :value latex-environment))))
+    (org-ascii--justify-element
+     (org-remove-indentation (org-element-property :value latex-environment))
+     latex-environment info)))
 
 
 ;;;; Latex Fragment
 
-(defun org-ascii-latex-fragment (latex-fragment contents info)
+(defun org-ascii-latex-fragment (latex-fragment _contents info)
   "Transcode a LATEX-FRAGMENT object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
@@ -1372,7 +1548,7 @@ information."
 
 ;;;; Line Break
 
-(defun org-ascii-line-break (line-break contents info)
+(defun org-ascii-line-break (_line-break _contents _info)
   "Transcode a LINE-BREAK object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual
   information."  hard-newline)
@@ -1385,9 +1561,9 @@ CONTENTS is nil.  INFO is a plist holding contextual
 
 DESC is the description part of the link, or the empty string.
 INFO is a plist holding contextual information."
-  (let ((raw-link (org-element-property :raw-link link))
-       (type (org-element-property :type link)))
+  (let ((type (org-element-property :type link)))
     (cond
+     ((org-export-custom-protocol-maybe link desc 'ascii))
      ((string= type "coderef")
       (let ((ref (org-element-property :path link)))
        (format (org-export-get-coderef-format ref desc)
@@ -1395,23 +1571,51 @@ INFO is a plist holding contextual information."
      ;; Do not apply a special syntax on radio links.  Though, use
      ;; transcoded target's contents as output.
      ((string= type "radio") desc)
-     ;; Do not apply a special syntax on fuzzy links pointing to
-     ;; targets.
-     ((string= type "fuzzy")
-      (let ((destination (org-export-resolve-fuzzy-link link info)))
-       (if (org-string-nw-p desc) desc
-         (when destination
-           (let ((number
-                  (org-export-get-ordinal
-                   destination info nil 'org-ascii--has-caption-p)))
-             (when number
-               (if (atom number) (number-to-string number)
-                 (mapconcat 'number-to-string number "."))))))))
+     ((member type '("custom-id" "fuzzy" "id"))
+      (let ((destination (if (string= type "fuzzy")
+                            (org-export-resolve-fuzzy-link link info)
+                          (org-export-resolve-id-link link info))))
+       (pcase (org-element-type destination)
+         ((guard desc)
+          (if (plist-get info :ascii-links-to-notes)
+              (format "[%s]" desc)
+            (concat desc
+                    (format " (%s)"
+                            (org-ascii--describe-datum destination info)))))
+         ;; External file.
+         (`plain-text destination)
+         (`headline
+          (if (org-export-numbered-headline-p destination info)
+              (mapconcat #'number-to-string
+                         (org-export-get-headline-number destination info)
+                         ".")
+            (org-export-data (org-element-property :title destination) info)))
+         ;; Handle enumerable elements and targets within them.
+         ((and (let number (org-export-get-ordinal
+                            destination info nil #'org-ascii--has-caption-p))
+               (guard number))
+          (if (atom number) (number-to-string number)
+            (mapconcat #'number-to-string number ".")))
+         ;; Don't know what to do.  Signal it.
+         (_ "???"))))
      (t
-      (if (not (org-string-nw-p desc)) (format "[%s]" raw-link)
-       (concat
-        (format "[%s]" desc)
-        (unless org-ascii-links-to-notes (format " (%s)" raw-link))))))))
+      (let ((raw-link (org-element-property :raw-link link)))
+       (if (not (org-string-nw-p desc)) (format "[%s]" raw-link)
+         (concat (format "[%s]" desc)
+                 (and (not (plist-get info :ascii-links-to-notes))
+                      (format " (%s)" raw-link)))))))))
+
+
+;;;; Node Properties
+
+(defun org-ascii-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to ASCII.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
 
 
 ;;;; Paragraph
@@ -1420,16 +1624,17 @@ INFO is a plist holding contextual information."
   "Transcode a PARAGRAPH element from Org to ASCII.
 CONTENTS is the contents of the paragraph, as a string.  INFO is
 the plist used as a communication channel."
-  (org-ascii--fill-string
-   (if (not (wholenump org-ascii-indented-line-width)) contents
-     (concat
-      ;; Do not indent first paragraph in a section.
-      (unless (and (not (org-export-get-previous-element paragraph info))
-                  (eq (org-element-type (org-export-get-parent paragraph))
-                      'section))
-       (make-string org-ascii-indented-line-width ?\s))
-      (replace-regexp-in-string "\\`[ \t]+" "" contents)))
-   (org-ascii--current-text-width paragraph info) info))
+  (org-ascii--justify-element
+   (let ((indented-line-width (plist-get info :ascii-indented-line-width)))
+     (if (not (wholenump indented-line-width)) contents
+       (concat
+       ;; Do not indent first paragraph in a section.
+       (unless (and (not (org-export-get-previous-element paragraph info))
+                    (eq (org-element-type (org-export-get-parent paragraph))
+                        'section))
+         (make-string indented-line-width ?\s))
+       (replace-regexp-in-string "\\`[ \t]+" "" contents))))
+   paragraph info))
 
 
 ;;;; Plain List
@@ -1438,7 +1643,11 @@ the plist used as a communication channel."
   "Transcode a PLAIN-LIST element from Org to ASCII.
 CONTENTS is the contents of the list.  INFO is a plist holding
 contextual information."
-  contents)
+  (let ((margin (plist-get info :ascii-list-margin)))
+    (if (or (< margin 1)
+           (eq (org-element-type (org-export-get-parent plain-list)) 'item))
+       contents
+      (org-ascii--indent-string contents margin))))
 
 
 ;;;; Plain Text
@@ -1462,62 +1671,52 @@ INFO is a plist used as a communication channel."
 
 ;;;; Planning
 
-(defun org-ascii-planning (planning contents info)
+(defun org-ascii-planning (planning _contents info)
   "Transcode a PLANNING element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (mapconcat
-   'identity
-   (delq nil
-        (list (let ((closed (org-element-property :closed planning)))
-                (when closed
-                  (concat org-closed-string " "
-                          (org-translate-time
-                           (org-element-property :raw-value closed)))))
-              (let ((deadline (org-element-property :deadline planning)))
-                (when deadline
-                  (concat org-deadline-string " "
-                          (org-translate-time
-                           (org-element-property :raw-value deadline)))))
-              (let ((scheduled (org-element-property :scheduled planning)))
-                (when scheduled
-                  (concat org-scheduled-string " "
-                          (org-translate-time
-                           (org-element-property :raw-value scheduled)))))))
-   " "))
+  (org-ascii--justify-element
+   (mapconcat
+    #'identity
+    (delq nil
+         (list (let ((closed (org-element-property :closed planning)))
+                 (when closed
+                   (concat org-closed-string " "
+                           (org-timestamp-translate closed))))
+               (let ((deadline (org-element-property :deadline planning)))
+                 (when deadline
+                   (concat org-deadline-string " "
+                           (org-timestamp-translate deadline))))
+               (let ((scheduled (org-element-property :scheduled planning)))
+                 (when scheduled
+                   (concat org-scheduled-string " "
+                           (org-timestamp-translate scheduled))))))
+    " ")
+   planning info))
+
+
+;;;; Property Drawer
+
+(defun org-ascii-property-drawer (property-drawer contents info)
+  "Transcode a PROPERTY-DRAWER element from Org to ASCII.
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (org-ascii--justify-element contents property-drawer info)))
 
 
 ;;;; Quote Block
 
-(defun org-ascii-quote-block (quote-block contents info)
+(defun org-ascii-quote-block (_quote-block contents info)
   "Transcode a QUOTE-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (org-ascii--indent-string contents org-ascii-quote-margin))
-
-
-;;;; Quote Section
-
-(defun org-ascii-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to ASCII.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((width (org-ascii--current-text-width quote-section info))
-       (value
-        (org-export-data
-         (org-remove-indentation (org-element-property :value quote-section))
-         info)))
-    (org-ascii--indent-string
-     value
-     (+ org-ascii-quote-margin
-       ;; Don't apply inner margin if parent headline is low level.
-       (let ((headline (org-export-get-parent-headline quote-section)))
-         (if (org-export-low-level-p headline info) 0
-           org-ascii-inner-margin))))))
+  (org-ascii--indent-string contents (plist-get info :ascii-quote-margin)))
 
 
 ;;;; Radio Target
 
-(defun org-ascii-radio-target (radio-target contents info)
+(defun org-ascii-radio-target (_radio-target contents _info)
   "Transcode a RADIO-TARGET object from Org to ASCII.
 CONTENTS is the contents of the target.  INFO is a plist holding
 contextual information."
@@ -1530,50 +1729,56 @@ contextual information."
   "Transcode a SECTION element from Org to ASCII.
 CONTENTS is the contents of the section.  INFO is a plist holding
 contextual information."
-  (org-ascii--indent-string
-   (concat
-    contents
-    (when org-ascii-links-to-notes
-      ;; Add list of links at the end of SECTION.
-      (let ((links (org-ascii--describe-links
-                   (org-ascii--unique-links section info)
-                   (org-ascii--current-text-width section info) info)))
-       ;; Separate list of links and section contents.
-       (when (org-string-nw-p links) (concat "\n\n" links)))))
-   ;; Do not apply inner margin if parent headline is low level.
-   (let ((headline (org-export-get-parent-headline section)))
-     (if (or (not headline) (org-export-low-level-p headline info)) 0
-       org-ascii-inner-margin))))
+  (let ((links
+        (and (plist-get info :ascii-links-to-notes)
+             ;; Take care of links in first section of the document.
+             (not (org-element-lineage section '(headline)))
+             (org-ascii--describe-links
+              (org-ascii--unique-links section info)
+              (org-ascii--current-text-width section info)
+              info))))
+    (org-ascii--indent-string
+     (if (not (org-string-nw-p links)) contents
+       (concat (org-element-normalize-string contents) "\n\n" links))
+     ;; Do not apply inner margin if parent headline is low level.
+     (let ((headline (org-export-get-parent-headline section)))
+       (if (or (not headline) (org-export-low-level-p headline info)) 0
+        (plist-get info :ascii-inner-margin))))))
 
 
 ;;;; Special Block
 
-(defun org-ascii-special-block (special-block contents info)
+(defun org-ascii-special-block (_special-block contents _info)
   "Transcode a SPECIAL-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
+  ;; "JUSTIFYLEFT" and "JUSTFYRIGHT" have already been taken care of
+  ;; at a lower level.  There is no other special block type to
+  ;; handle.
   contents)
 
 
 ;;;; Src Block
 
-(defun org-ascii-src-block (src-block contents info)
+(defun org-ascii-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to ASCII.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (let ((caption (org-ascii--build-caption src-block info))
+       (caption-above-p (plist-get info :ascii-caption-above))
        (code (org-export-format-code-default src-block info)))
     (if (equal code "") ""
-      (concat
-       (when (and caption org-ascii-caption-above) (concat caption "\n"))
-       (org-ascii--box-string code info)
-       (when (and caption (not org-ascii-caption-above))
-        (concat "\n" caption))))))
+      (org-ascii--justify-element
+       (concat
+       (and caption caption-above-p (concat caption "\n"))
+       (org-ascii--box-string code info)
+       (and caption (not caption-above-p) (concat "\n" caption)))
+       src-block info))))
 
 
 ;;;; Statistics Cookie
 
-(defun org-ascii-statistics-cookie (statistics-cookie contents info)
+(defun org-ascii-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-element-property :value statistics-cookie))
@@ -1581,7 +1786,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Subscript
 
-(defun org-ascii-subscript (subscript contents info)
+(defun org-ascii-subscript (subscript contents _info)
   "Transcode a SUBSCRIPT object from Org to ASCII.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -1592,7 +1797,7 @@ contextual information."
 
 ;;;; Superscript
 
-(defun org-ascii-superscript (superscript contents info)
+(defun org-ascii-superscript (superscript contents _info)
   "Transcode a SUPERSCRIPT object from Org to ASCII.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -1603,7 +1808,7 @@ contextual information."
 
 ;;;; Strike-through
 
-(defun org-ascii-strike-through (strike-through contents info)
+(defun org-ascii-strike-through (_strike-through contents _info)
   "Transcode STRIKE-THROUGH from Org to ASCII.
 CONTENTS is text with strike-through markup.  INFO is a plist
 holding contextual information."
@@ -1616,26 +1821,29 @@ holding contextual information."
   "Transcode a TABLE element from Org to ASCII.
 CONTENTS is the contents of the table.  INFO is a plist holding
 contextual information."
-  (let ((caption (org-ascii--build-caption table info)))
-    (concat
-     ;; Possibly add a caption string above.
-     (when (and caption org-ascii-caption-above) (concat caption "\n"))
-     ;; Insert table.  Note: "table.el" tables are left unmodified.
-     (cond ((eq (org-element-property :type table) 'org) contents)
-          ((and org-ascii-table-use-ascii-art
-                (eq (plist-get info :ascii-charset) 'utf-8)
-                (require 'ascii-art-to-unicode nil t))
-           (with-temp-buffer
-             (insert (org-remove-indentation
-                      (org-element-property :value table)))
-             (goto-char (point-min))
-             (aa2u)
-             (goto-char (point-max))
-             (skip-chars-backward " \r\t\n")
-             (buffer-substring (point-min) (point))))
-          (t (org-remove-indentation (org-element-property :value table))))
-     ;; Possible add a caption string below.
-     (and (not org-ascii-caption-above) caption))))
+  (let ((caption (org-ascii--build-caption table info))
+       (caption-above-p (plist-get info :ascii-caption-above)))
+    (org-ascii--justify-element
+     (concat
+      ;; Possibly add a caption string above.
+      (and caption caption-above-p (concat caption "\n"))
+      ;; Insert table.  Note: "table.el" tables are left unmodified.
+      (cond ((eq (org-element-property :type table) 'org) contents)
+           ((and (plist-get info :ascii-table-use-ascii-art)
+                 (eq (plist-get info :ascii-charset) 'utf-8)
+                 (require 'ascii-art-to-unicode nil t))
+            (with-temp-buffer
+              (insert (org-remove-indentation
+                       (org-element-property :value table)))
+              (goto-char (point-min))
+              (aa2u)
+              (goto-char (point-max))
+              (skip-chars-backward " \r\t\n")
+              (buffer-substring (point-min) (point))))
+           (t (org-remove-indentation (org-element-property :value table))))
+      ;; Possible add a caption string below.
+      (and (not caption-above-p) caption))
+     table info)))
 
 
 ;;;; Table Cell
@@ -1661,12 +1869,13 @@ are ignored."
                               (plist-put info :ascii-table-cell-width-cache
                                          (make-hash-table :test 'equal)))
                         :ascii-table-cell-width-cache)))
-        (key (cons table col)))
+        (key (cons table col))
+        (widenp (plist-get info :ascii-table-widen-columns)))
     (or (gethash key cache)
        (puthash
         key
         (let ((cookie-width (org-export-table-cell-width table-cell info)))
-          (or (and (not org-ascii-table-widen-columns) cookie-width)
+          (or (and (not widenp) cookie-width)
               (let ((contents-width
                      (let ((max-width 0))
                        (org-element-map table 'table-row
@@ -1681,8 +1890,7 @@ are ignored."
                          info)
                        max-width)))
                 (cond ((not cookie-width) contents-width)
-                      (org-ascii-table-widen-columns
-                       (max cookie-width contents-width))
+                      (widenp (max cookie-width contents-width))
                       (t cookie-width)))))
         cache))))
 
@@ -1696,14 +1904,14 @@ a communication channel."
   ;; each cell in the column.
   (let ((width (org-ascii--table-cell-width table-cell info)))
     ;; When contents are too large, truncate them.
-    (unless (or org-ascii-table-widen-columns
+    (unless (or (plist-get info :ascii-table-widen-columns)
                (<= (string-width (or contents "")) width))
       (setq contents (concat (substring contents 0 (- width 2)) "=>")))
     ;; Align contents correctly within the cell.
     (let* ((indent-tabs-mode nil)
           (data
            (when contents
-             (org-ascii--justify-string
+             (org-ascii--justify-lines
               contents width
               (org-export-table-cell-alignment table-cell info)))))
       (setq contents
@@ -1770,7 +1978,7 @@ a communication channel."
 
 ;;;; Timestamp
 
-(defun org-ascii-timestamp (timestamp contents info)
+(defun org-ascii-timestamp (timestamp _contents info)
   "Transcode a TIMESTAMP object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-ascii-plain-text (org-timestamp-translate timestamp) info))
@@ -1778,7 +1986,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Underline
 
-(defun org-ascii-underline (underline contents info)
+(defun org-ascii-underline (_underline contents _info)
   "Transcode UNDERLINE from Org to ASCII.
 CONTENTS is the text with underline markup.  INFO is a plist
 holding contextual information."
@@ -1787,10 +1995,10 @@ holding contextual information."
 
 ;;;; Verbatim
 
-(defun org-ascii-verbatim (verbatim contents info)
+(defun org-ascii-verbatim (verbatim _contents info)
   "Return a VERBATIM object from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (format org-ascii-verbatim-format
+  (format (plist-get info :ascii-verbatim-format)
          (org-element-property :value verbatim)))
 
 
@@ -1800,48 +2008,48 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
   "Transcode a VERSE-BLOCK element from Org to ASCII.
 CONTENTS is verse block contents.  INFO is a plist holding
 contextual information."
-  (let ((verse-width (org-ascii--current-text-width verse-block info)))
-    (org-ascii--indent-string
-     (org-ascii--justify-string contents verse-width 'left)
-     org-ascii-quote-margin)))
+  (org-ascii--indent-string
+   (org-ascii--justify-element contents verse-block info)
+   (plist-get info :ascii-quote-margin)))
 
 
 
 ;;; Filters
 
-(defun org-ascii-filter-headline-blank-lines (headline back-end info)
+(defun org-ascii-filter-headline-blank-lines (headline _backend info)
   "Filter controlling number of blank lines after a headline.
 
-HEADLINE is a string representing a transcoded headline.
-BACK-END is symbol specifying back-end used for export.  INFO is
-plist containing the communication channel.
+HEADLINE is a string representing a transcoded headline.  BACKEND
+is symbol specifying back-end used for export.  INFO is plist
+containing the communication channel.
 
 This function only applies to `ascii' back-end.  See
 `org-ascii-headline-spacing' for information."
-  (if (not org-ascii-headline-spacing) headline
-    (let ((blanks (make-string (1+ (cdr org-ascii-headline-spacing)) ?\n)))
-      (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline))))
+  (let ((headline-spacing (plist-get info :ascii-headline-spacing)))
+    (if (not headline-spacing) headline
+      (let ((blanks (make-string (1+ (cdr headline-spacing)) ?\n)))
+       (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline)))))
 
-(defun org-ascii-filter-paragraph-spacing (tree back-end info)
+(defun org-ascii-filter-paragraph-spacing (tree _backend info)
   "Filter controlling number of blank lines between paragraphs.
 
-TREE is the parse tree.  BACK-END is the symbol specifying
+TREE is the parse tree.  BACKEND is the symbol specifying
 back-end used for export.  INFO is a plist used as
 a communication channel.
 
 See `org-ascii-paragraph-spacing' for information."
-  (when (wholenump org-ascii-paragraph-spacing)
-    (org-element-map tree 'paragraph
-      (lambda (p)
-       (when (eq (org-element-type (org-export-get-next-element p info))
-                 'paragraph)
-         (org-element-put-property
-          p :post-blank org-ascii-paragraph-spacing)))))
+  (let ((paragraph-spacing (plist-get info :ascii-paragraph-spacing)))
+    (when (wholenump paragraph-spacing)
+      (org-element-map tree 'paragraph
+       (lambda (p)
+         (when (eq (org-element-type (org-export-get-next-element p info))
+                   'paragraph)
+           (org-element-put-property p :post-blank paragraph-spacing))))))
   tree)
 
-(defun org-ascii-filter-comment-spacing (tree backend info)
+(defun org-ascii-filter-comment-spacing (tree _backend info)
   "Filter removing blank lines between comments.
-TREE is the parse tree.  BACK-END is the symbol specifying
+TREE is the parse tree.  BACKEND is the symbol specifying
 back-end used for export.  INFO is a plist used as
 a communication channel."
   (org-element-map tree '(comment comment-block)
diff --git a/lisp/org/ox-beamer.el b/lisp/org/ox-beamer.el
index a8d48b6..82651d3 100644
--- a/lisp/org/ox-beamer.el
+++ b/lisp/org/ox-beamer.el
@@ -1,4 +1,4 @@
-;;; ox-beamer.el --- Beamer Back-End for Org Export Engine
+;;; ox-beamer.el --- Beamer Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
 
@@ -29,7 +29,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'ox-latex)
 
 ;; Install a default set-up for Beamer export.
@@ -105,7 +105,9 @@ key     Selection key for `org-beamer-select-environment'
 open    The opening template for the environment, with the following escapes
         %a   the action/overlay specification
         %A   the default action/overlay specification
-        %o   the options argument of the template
+        %R   the raw BEAMER_act value
+        %o   the options argument, with square brackets
+        %O   the raw BEAMER_opt value
         %h   the headline text
         %r   the raw headline text (i.e. without any processing)
         %H   if there is headline text, that raw text in {} braces
@@ -133,6 +135,15 @@ You might want to put e.g. \"allowframebreaks=0.9\" here."
   :type '(string :tag "Outline frame options"))
 
 
+(defcustom org-beamer-subtitle-format "\\subtitle{%s}"
+  "Format string used for transcoded subtitle.
+The format string should have at most one \"%s\"-expression,
+which is replaced with the subtitle."
+  :group 'org-export-beamer
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(string :tag "Format string"))
+
 
 ;;; Internal Variables
 
@@ -191,19 +202,14 @@ TYPE is a symbol among the following:
 `defaction' Return ARGUMENT within both square and angular brackets.
 `option'    Return ARGUMENT within square brackets."
   (if (not (string-match "\\S-" argument)) ""
-    (case type
-      (action (if (string-match "\\`<.*>\\'" argument) argument
-               (format "<%s>" argument)))
-      (defaction (cond
-                 ((string-match "\\`\\[<.*>\\]\\'" argument) argument)
-                 ((string-match "\\`<.*>\\'" argument)
-                  (format "[%s]" argument))
-                 ((string-match "\\`\\[\\(.*\\)\\]\\'" argument)
-                  (format "[<%s>]" (match-string 1 argument)))
-                 (t (format "[<%s>]" argument))))
-      (option (if (string-match "\\`\\[.*\\]\\'" argument) argument
-               (format "[%s]" argument)))
-      (otherwise argument))))
+    (cl-case type
+      (action (format "<%s>" (org-unbracket-string "<" ">" argument)))
+      (defaction
+       (format "[<%s>]"
+               (org-unbracket-string "<" ">" (org-unbracket-string "[" "]" 
argument))))
+      (option (format "[%s]" (org-unbracket-string "[" "]" argument)))
+      (otherwise (error "Invalid `type' argument to 
`org-beamer--normalize-argument': %s"
+                       type)))))
 
 (defun org-beamer--element-has-overlay-p (element)
   "Non-nil when ELEMENT has an overlay specified.
@@ -213,14 +219,14 @@ Return overlay specification, as a string, or nil."
   (let ((first-object (car (org-element-contents element))))
     (when (eq (org-element-type first-object) 'export-snippet)
       (let ((value (org-element-property :value first-object)))
-       (and (string-match "\\`<.*>\\'" value) value)))))
+       (and (string-prefix-p "<" value) (string-suffix-p ">" value)
+            value)))))
 
 
 
 ;;; Define Back-End
 
 (org-export-define-derived-backend 'beamer 'latex
-  :export-block "BEAMER"
   :menu-entry
   '(?l 1
        ((?B "As LaTeX buffer (Beamer)" org-beamer-export-as-latex)
@@ -231,15 +237,20 @@ Return overlay specification, as a string, or nil."
              (if a (org-beamer-export-to-pdf t s v b)
                (org-open-file (org-beamer-export-to-pdf nil s v b)))))))
   :options-alist
-  '((:beamer-theme "BEAMER_THEME" nil org-beamer-theme)
+  '((:headline-levels nil "H" org-beamer-frame-level)
+    (:latex-class "LATEX_CLASS" nil "beamer" t)
+    (:beamer-subtitle-format nil nil org-beamer-subtitle-format)
+    (:beamer-column-view-format "COLUMNS" nil org-beamer-column-view-format)
+    (:beamer-theme "BEAMER_THEME" nil org-beamer-theme)
     (:beamer-color-theme "BEAMER_COLOR_THEME" nil nil t)
     (:beamer-font-theme "BEAMER_FONT_THEME" nil nil t)
     (:beamer-inner-theme "BEAMER_INNER_THEME" nil nil t)
     (:beamer-outer-theme "BEAMER_OUTER_THEME" nil nil t)
-    (:beamer-header-extra "BEAMER_HEADER" nil nil newline)
-    ;; Modify existing properties.
-    (:headline-levels nil "H" org-beamer-frame-level)
-    (:latex-class "LATEX_CLASS" nil "beamer" t))
+    (:beamer-header "BEAMER_HEADER" nil nil newline)
+    (:beamer-environments-extra nil nil org-beamer-environments-extra)
+    (:beamer-frame-default-options nil nil org-beamer-frame-default-options)
+    (:beamer-outline-frame-options nil nil org-beamer-outline-frame-options)
+    (:beamer-outline-frame-title nil nil org-beamer-outline-frame-title))
   :translate-alist '((bold . org-beamer-bold)
                     (export-block . org-beamer-export-block)
                     (export-snippet . org-beamer-export-snippet)
@@ -249,7 +260,6 @@ Return overlay specification, as a string, or nil."
                     (link . org-beamer-link)
                     (plain-list . org-beamer-plain-list)
                     (radio-target . org-beamer-radio-target)
-                    (target . org-beamer-target)
                     (template . org-beamer-template)))
 
 
@@ -258,7 +268,7 @@ Return overlay specification, as a string, or nil."
 
 ;;;; Bold
 
-(defun org-beamer-bold (bold contents info)
+(defun org-beamer-bold (bold contents _info)
   "Transcode BLOCK object into Beamer code.
 CONTENTS is the text being bold.  INFO is a plist used as
 a communication channel."
@@ -269,7 +279,7 @@ a communication channel."
 
 ;;;; Export Block
 
-(defun org-beamer-export-block (export-block contents info)
+(defun org-beamer-export-block (export-block _contents _info)
   "Transcode an EXPORT-BLOCK element into Beamer code.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -279,7 +289,7 @@ channel."
 
 ;;;; Export Snippet
 
-(defun org-beamer-export-snippet (export-snippet contents info)
+(defun org-beamer-export-snippet (export-snippet _contents info)
   "Transcode an EXPORT-SNIPPET object into Beamer code.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -315,16 +325,21 @@ channel."
 INFO is a plist used as a communication channel.
 
 The value is either the label specified in \"BEAMER_opt\"
-property, or a fallback value built from headline's number.  This
-function assumes HEADLINE will be treated as a frame."
-  (let ((opt (org-element-property :BEAMER_OPT headline)))
-    (if (and (org-string-nw-p opt)
-            (string-match "\\(?:^\\|,\\)label=\\(.*?\\)\\(?:$\\|,\\)" opt))
-       (match-string 1 opt)
-      (format "sec-%s"
-             (mapconcat 'number-to-string
-                        (org-export-get-headline-number headline info)
-                        "-")))))
+property, the custom ID, if there is one and
+`:latex-prefer-user-labels' property has a non nil value, or
+a unique internal label.  This function assumes HEADLINE will be
+treated as a frame."
+  (cond
+   ((let ((opt (org-element-property :BEAMER_OPT headline)))
+      (and (stringp opt)
+          (string-match "\\(?:^\\|,\\)label=\\(.*?\\)\\(?:$\\|,\\)" opt)
+          (let ((label (match-string 1 opt)))
+            (if (string-match-p "\\`{.*}\\'" label)
+                (substring label 1 -1)
+              label)))))
+   ((and (plist-get info :latex-prefer-user-labels)
+        (org-element-property :CUSTOM_ID headline)))
+   (t (format "sec:%s" (org-export-get-reference headline info)))))
 
 (defun org-beamer--frame-level (headline info)
   "Return frame level in subtree containing HEADLINE.
@@ -333,12 +348,10 @@ INFO is a plist used as a communication channel."
    ;; 1. Look for "frame" environment in parents, starting from the
    ;;    farthest.
    (catch 'exit
-     (mapc (lambda (parent)
-            (let ((env (org-element-property :BEAMER_ENV parent)))
-              (when (and env (member-ignore-case env '("frame" "fullframe")))
-                (throw 'exit (org-export-get-relative-level parent info)))))
-          (nreverse (org-export-get-genealogy headline)))
-     nil)
+     (dolist (parent (nreverse (org-element-lineage headline)))
+       (let ((env (org-element-property :BEAMER_ENV parent)))
+        (when (and env (member-ignore-case env '("frame" "fullframe")))
+          (throw 'exit (org-export-get-relative-level parent info))))))
    ;; 2. Look for "frame" environment in HEADLINE.
    (let ((env (org-element-property :BEAMER_ENV headline)))
      (and env (member-ignore-case env '("frame" "fullframe"))
@@ -413,7 +426,8 @@ used as a communication channel."
                    ;; Collect options from default value and headline's
                    ;; properties.  Also add a label for links.
                    (append
-                    (org-split-string org-beamer-frame-default-options ",")
+                    (org-split-string
+                     (plist-get info :beamer-frame-default-options) ",")
                     (and beamer-opt
                          (org-split-string
                           ;; Remove square brackets if user provided
@@ -422,12 +436,20 @@ used as a communication channel."
                                (match-string 1 beamer-opt))
                           ","))
                     ;; Provide an automatic label for the frame
-                    ;; unless the user specified one.
+                    ;; unless the user specified one.  Also refrain
+                    ;; from labeling `allowframebreaks' frames; this
+                    ;; is not allowed by beamer.
                     (unless (and beamer-opt
-                                 (string-match "\\(^\\|,\\)label=" beamer-opt))
+                                 (or (string-match "\\(^\\|,\\)label=" 
beamer-opt)
+                                     (string-match "allowframebreaks" 
beamer-opt)))
                       (list
-                       (format "label=%s"
-                               (org-beamer--get-label headline info)))))))
+                       (let ((label (org-beamer--get-label headline info)))
+                         ;; Labels containing colons need to be
+                         ;; wrapped within braces.
+                         (format (if (string-match-p ":" label)
+                                     "label={%s}"
+                                   "label=%s")
+                                 label)))))))
              ;; Change options list into a string.
              (org-beamer--normalize-argument
               (mapconcat
@@ -475,14 +497,15 @@ used as a communication channel."
         (env-format
          (cond ((member environment '("column" "columns")) nil)
                ((assoc environment
-                       (append org-beamer-environments-extra
+                       (append (plist-get info :beamer-environments-extra)
                                org-beamer-environments-default)))
                (t (user-error "Wrong block type at a headline named \"%s\""
                               raw-title))))
         (title (org-export-data (org-element-property :title headline) info))
-        (options (let ((options (org-element-property :BEAMER_OPT headline)))
-                   (if (not options) ""
-                     (org-beamer--normalize-argument options 'option))))
+        (raw-options (org-element-property :BEAMER_OPT headline))
+        (options (if raw-options
+                     (org-beamer--normalize-argument raw-options 'option)
+                   ""))
         ;; Start a "columns" environment when explicitly requested or
         ;; when there is no previous headline or the previous
         ;; headline do not have a BEAMER_column property.
@@ -521,7 +544,7 @@ used as a communication channel."
               ;; One can specify placement for column only when
               ;; HEADLINE stands for a column on its own.
               (if (equal environment "column") options "")
-              (format "%s\\textwidth" column-width)))
+              (format "%s\\columnwidth" column-width)))
      ;; Block's opening string.
      (when (nth 2 env-format)
        (concat
@@ -534,15 +557,19 @@ used as a communication channel."
          ;; overlay specification and the default one is nil.
          (let ((action (org-element-property :BEAMER_ACT headline)))
            (cond
-            ((not action) (list (cons "a" "") (cons "A" "")))
-            ((string-match "\\`\\[.*\\]\\'" action)
+            ((not action) (list (cons "a" "") (cons "A" "") (cons "R" "")))
+            ((and (string-prefix-p "[" action)
+                  (string-suffix-p "]" action))
              (list
               (cons "A" (org-beamer--normalize-argument action 'defaction))
-              (cons "a" "")))
+              (cons "a" "")
+              (cons "R" action)))
             (t
              (list (cons "a" (org-beamer--normalize-argument action 'action))
-                   (cons "A" "")))))
+                   (cons "A" "")
+                   (cons "R" action)))))
          (list (cons "o" options)
+               (cons "O" (or raw-options ""))
                (cons "h" title)
                (cons "r" raw-title)
                (cons "H" (if (equal raw-title "") ""
@@ -578,28 +605,27 @@ as a communication channel."
                      (when overlay
                        (org-beamer--normalize-argument
                         overlay
-                        (if (string-match "^\\[.*\\]$" overlay) 'defaction
+                        (if (string-match "\\`\\[.*\\]\\'" overlay) 'defaction
                           'action))))
                    ;; Options.
                    (let ((options (org-element-property :BEAMER_OPT headline)))
                      (when options
                        (org-beamer--normalize-argument options 'option)))
                    ;; Resolve reference provided by "BEAMER_ref"
-                   ;; property.  This is done by building a minimal fake
-                   ;; link and calling the appropriate resolve function,
-                   ;; depending on the reference syntax.
-                   (let* ((type
-                           (progn
-                             (string-match "^\\(id:\\|#\\|\\*\\)?\\(.*\\)" ref)
-                             (cond
-                              ((or (not (match-string 1 ref))
-                                   (equal (match-string 1 ref) "*")) 'fuzzy)
-                              ((equal (match-string 1 ref) "id:") 'id)
-                              (t 'custom-id))))
-                          (link (list 'link (list :path (match-string 2 ref))))
-                          (target (if (eq type 'fuzzy)
-                                      (org-export-resolve-fuzzy-link link info)
-                                    (org-export-resolve-id-link link info))))
+                   ;; property.  This is done by building a minimal
+                   ;; fake link and calling the appropriate resolve
+                   ;; function, depending on the reference syntax.
+                   (let ((target
+                          (if (string-match "\\`\\(id:\\|#\\)" ref)
+                              (org-export-resolve-id-link
+                               `(link (:path ,(substring ref (match-end 0))))
+                               info)
+                            (org-export-resolve-fuzzy-link
+                             `(link (:path
+                                     ;; Look for headlines only.
+                                     ,(if (eq (string-to-char ref) ?*) ref
+                                        (concat "*" ref))))
+                             info))))
                      ;; Now use user-defined label provided in TARGET
                      ;; headline, or fallback to standard one.
                      (format "{%s}" (org-beamer--get-label target info)))))))
@@ -640,15 +666,27 @@ as a communication channel."
   "Transcode an ITEM element into Beamer code.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let ((action (let ((first-element (car (org-element-contents item))))
-                 (and (eq (org-element-type first-element) 'paragraph)
-                      (org-beamer--element-has-overlay-p first-element))))
-       (output (org-export-with-backend 'latex item contents info)))
-    (if (or (not action) (not (string-match "\\\\item" output))) output
-      ;; If the item starts with a paragraph and that paragraph starts
-      ;; with an export snippet specifying an overlay, insert it after
-      ;; \item command.
-      (replace-match (concat "\\\\item" action) nil nil output))))
+  (org-export-with-backend
+   ;; Delegate item export to `latex'.  However, we use `beamer'
+   ;; transcoders for objects in the description tag.
+   (org-export-create-backend
+    :parent 'beamer
+    :transcoders
+    (list
+     (cons
+      'item
+      (lambda (item _c _i)
+       (let ((action
+              (let ((first (car (org-element-contents item))))
+                (and (eq (org-element-type first) 'paragraph)
+                     (org-beamer--element-has-overlay-p first))))
+             (output (org-latex-item item contents info)))
+         (if (not (and action (string-match "\\\\item" output))) output
+           ;; If the item starts with a paragraph and that paragraph
+           ;; starts with an export snippet specifying an overlay,
+           ;; append it to the \item command.
+           (replace-match (concat "\\\\item" action) nil nil output)))))))
+   item contents info))
 
 
 ;;;; Keyword
@@ -681,46 +719,16 @@ channel."
   "Transcode a LINK object into Beamer code.
 CONTENTS is the description part of the link.  INFO is a plist
 used as a communication channel."
-  (let ((type (org-element-property :type link))
-       (path (org-element-property :path link)))
-    ;; Use \hyperlink command for all internal links.
-    (cond
-     ((equal type "radio")
-      (let ((destination (org-export-resolve-radio-link link info)))
-       (if (not destination) contents
-         (format "\\hyperlink%s{%s}{%s}"
-                 (or (org-beamer--element-has-overlay-p link) "")
-                 (org-export-solidify-link-text
-                  (org-element-property :value destination))
-                 contents))))
-     ((and (member type '("custom-id" "fuzzy" "id"))
-          (let ((destination (if (string= type "fuzzy")
-                                 (org-export-resolve-fuzzy-link link info)
-                               (org-export-resolve-id-link link info))))
-            (case (org-element-type destination)
-              (headline
-               (let ((label
-                      (format "sec-%s"
-                              (mapconcat
-                               'number-to-string
-                               (org-export-get-headline-number
-                                destination info)
-                               "-"))))
-                 (if (and (plist-get info :section-numbers) (not contents))
-                     (format "\\ref{%s}" label)
-                   (format "\\hyperlink%s{%s}{%s}"
-                           (or (org-beamer--element-has-overlay-p link) "")
-                           label
-                           contents))))
-              (target
-               (let ((path (org-export-solidify-link-text path)))
-                 (if (not contents) (format "\\ref{%s}" path)
-                   (format "\\hyperlink%s{%s}{%s}"
-                           (or (org-beamer--element-has-overlay-p link) "")
-                           path
-                           contents))))))))
-     ;; Otherwise, use `latex' back-end.
-     (t (org-export-with-backend 'latex link contents info)))))
+  (or (org-export-custom-protocol-maybe link contents 'beamer)
+      ;; Fall-back to LaTeX export.  However, prefer "\hyperlink" over
+      ;; "\hyperref" since the former handles overlay specifications.
+      (let ((latex-link (org-export-with-backend 'latex link contents info)))
+       (if (string-match "\\`\\\\hyperref\\[\\(.*?\\)\\]" latex-link)
+           (replace-match
+            (format "\\\\hyperlink%s{\\1}"
+                    (or (org-beamer--element-has-overlay-p link) ""))
+            nil nil latex-link)
+         latex-link))))
 
 
 ;;;; Plain List
@@ -755,7 +763,8 @@ contextual information."
              'option)
             ;; Eventually insert contents and close environment.
             contents
-            latex-type))))
+            latex-type)
+     info)))
 
 
 ;;;; Radio Target
@@ -766,21 +775,10 @@ TEXT is the text of the target.  INFO is a plist holding
 contextual information."
   (format "\\hypertarget%s{%s}{%s}"
          (or (org-beamer--element-has-overlay-p radio-target) "")
-         (org-export-solidify-link-text
-          (org-element-property :value radio-target))
+         (org-export-get-reference radio-target info)
          text))
 
 
-;;;; Target
-
-(defun org-beamer-target (target contents info)
-  "Transcode a TARGET object into Beamer code.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (format "\\hypertarget{%s}{}"
-         (org-export-solidify-link-text (org-element-property :value target))))
-
-
 ;;;; Template
 ;;
 ;; Template used is similar to the one used in `latex' back-end,
@@ -790,37 +788,17 @@ information."
   "Return complete document string after Beamer conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
-  (let ((title (org-export-data (plist-get info :title) info)))
+  (let ((title (org-export-data (plist-get info :title) info))
+       (subtitle (org-export-data (plist-get info :subtitle) info)))
     (concat
-     ;; 1. Time-stamp.
+     ;; Time-stamp.
      (and (plist-get info :time-stamp-file)
          (format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
-     ;; 2. Document class and packages.
-     (let* ((class (plist-get info :latex-class))
-           (class-options (plist-get info :latex-class-options))
-           (header (nth 1 (assoc class org-latex-classes)))
-           (document-class-string
-            (and (stringp header)
-                 (if (not class-options) header
-                   (replace-regexp-in-string
-                    "^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)"
-                    class-options header t nil 1)))))
-       (if (not document-class-string)
-          (user-error "Unknown LaTeX class `%s'" class)
-        (org-latex-guess-babel-language
-         (org-latex-guess-inputenc
-          (org-element-normalize-string
-           (org-splice-latex-header
-            document-class-string
-            org-latex-default-packages-alist
-            org-latex-packages-alist nil
-            (concat (org-element-normalize-string
-                     (plist-get info :latex-header))
-                    (org-element-normalize-string
-                     (plist-get info :latex-header-extra))
-                    (plist-get info :beamer-header-extra)))))
-         info)))
-     ;; 3. Insert themes.
+     ;; LaTeX compiler
+     (org-latex--insert-compiler info)
+     ;; Document class and packages.
+     (org-latex-make-preamble info)
+     ;; Insert themes.
      (let ((format-theme
            (function
             (lambda (prop command)
@@ -840,11 +818,11 @@ holding export options."
                    (:beamer-inner-theme "\\useinnertheme")
                    (:beamer-outer-theme "\\useoutertheme"))
                  ""))
-     ;; 4. Possibly limit depth for headline numbering.
+     ;; Possibly limit depth for headline numbering.
      (let ((sec-num (plist-get info :section-numbers)))
        (when (integerp sec-num)
         (format "\\setcounter{secnumdepth}{%d}\n" sec-num)))
-     ;; 5. Author.
+     ;; Author.
      (let ((author (and (plist-get info :with-author)
                        (let ((auth (plist-get info :author)))
                          (and auth (org-export-data auth info)))))
@@ -852,52 +830,52 @@ holding export options."
                       (org-export-data (plist-get info :email) info))))
        (cond ((and author email (not (string= "" email)))
              (format "\\author{%s\\thanks{%s}}\n" author email))
-            (author (format "\\author{%s}\n" author))
-            (t "\\author{}\n")))
-     ;; 6. Date.
+            ((or author email) (format "\\author{%s}\n" (or author email)))))
+     ;; Date.
      (let ((date (and (plist-get info :with-date) (org-export-get-date info))))
        (format "\\date{%s}\n" (org-export-data date info)))
-     ;; 7. Title
+     ;; Title
      (format "\\title{%s}\n" title)
-     ;; 8. Hyperref options.
-     (when (plist-get info :latex-hyperref-p)
-       (format "\\hypersetup{\n  pdfkeywords={%s},\n  pdfsubject={%s},\n  
pdfcreator={%s}}\n"
-              (or (plist-get info :keywords) "")
-              (or (plist-get info :description) "")
-              (if (not (plist-get info :with-creator)) ""
-                (plist-get info :creator))))
-     ;; 9. Document start.
+     (when (org-string-nw-p subtitle)
+       (concat (format (plist-get info :beamer-subtitle-format) subtitle) 
"\n"))
+     ;; Beamer-header
+     (let ((beamer-header (plist-get info :beamer-header)))
+       (when beamer-header
+        (format "%s\n" (plist-get info :beamer-header))))
+     ;; 9. Hyperref options.
+     (let ((template (plist-get info :latex-hyperref-template)))
+       (and (stringp template)
+           (format-spec template (org-latex--format-spec info))))
+     ;; Document start.
      "\\begin{document}\n\n"
-     ;; 10. Title command.
+     ;; Title command.
      (org-element-normalize-string
-      (cond ((string= "" title) nil)
+      (cond ((not (plist-get info :with-title)) nil)
+           ((string= "" title) nil)
            ((not (stringp org-latex-title-command)) nil)
            ((string-match "\\(?:[^%]\\|^\\)%s"
                           org-latex-title-command)
             (format org-latex-title-command title))
            (t org-latex-title-command)))
-     ;; 11. Table of contents.
+     ;; Table of contents.
      (let ((depth (plist-get info :with-toc)))
        (when depth
         (concat
          (format "\\begin{frame}%s{%s}\n"
                  (org-beamer--normalize-argument
-                  org-beamer-outline-frame-options 'option)
-                 org-beamer-outline-frame-title)
+                  (plist-get info :beamer-outline-frame-options) 'option)
+                 (plist-get info :beamer-outline-frame-title))
          (when (wholenump depth)
            (format "\\setcounter{tocdepth}{%d}\n" depth))
          "\\tableofcontents\n"
          "\\end{frame}\n\n")))
-     ;; 12. Document's body.
+     ;; Document's body.
      contents
-     ;; 13. Creator.
-     (let ((creator-info (plist-get info :with-creator)))
-       (cond
-       ((not creator-info) "")
-       ((eq creator-info 'comment)
-        (format "%% %s\n" (plist-get info :creator)))
-       (t (concat (plist-get info :creator) "\n"))))
-     ;; 14. Document end.
+     ;; Creator.
+     (if (plist-get info :with-creator)
+        (concat (plist-get info :creator) "\n")
+       "")
+     ;; Document end.
      "\\end{document}")))
 
 
@@ -933,7 +911,7 @@ value."
     (save-excursion
       (org-back-to-heading t)
       ;; Filter out Beamer-related tags and install environment tag.
-      (let ((tags (org-remove-if (lambda (x) (string-match "^B_" x))
+      (let ((tags (cl-remove-if (lambda (x) (string-match "^B_" x))
                                 (org-get-tags)))
            (env-tag (and (org-string-nw-p value) (concat "B_" value))))
        (org-set-tags-to (if env-tag (cons env-tag tags) tags))
@@ -1085,7 +1063,7 @@ aid, but the tag does not have any semantic meaning."
   (let* ((envs (append org-beamer-environments-special
                       org-beamer-environments-extra
                       org-beamer-environments-default))
-        (org-tag-alist
+        (org-current-tag-alist
          (append '((:startgroup))
                  (mapcar (lambda (e) (cons (concat "B_" (car e))
                                       (string-to-char (nth 1 e))))
@@ -1121,30 +1099,6 @@ aid, but the tag does not have any semantic meaning."
        (t (org-entry-delete nil "BEAMER_env"))))))
 
 ;;;###autoload
-(defun org-beamer-insert-options-template (&optional kind)
-  "Insert a settings template, to make sure users do this right."
-  (interactive (progn
-                (message "Current [s]ubtree or [g]lobal?")
-                (if (eq (read-char-exclusive) ?g) (list 'global)
-                  (list 'subtree))))
-  (if (eq kind 'subtree)
-      (progn
-       (org-back-to-heading t)
-       (org-reveal)
-       (org-entry-put nil "EXPORT_LaTeX_CLASS" "beamer")
-       (org-entry-put nil "EXPORT_LaTeX_CLASS_OPTIONS" "[presentation]")
-       (org-entry-put nil "EXPORT_FILE_NAME" "presentation.pdf")
-       (when org-beamer-column-view-format
-         (org-entry-put nil "COLUMNS" org-beamer-column-view-format))
-       (org-entry-put nil "BEAMER_col_ALL" org-beamer-column-widths))
-    (insert "#+LaTeX_CLASS: beamer\n")
-    (insert "#+LaTeX_CLASS_OPTIONS: [presentation]\n")
-    (when org-beamer-theme (insert "#+BEAMER_THEME: " org-beamer-theme "\n"))
-    (when org-beamer-column-view-format
-      (insert "#+COLUMNS: " org-beamer-column-view-format "\n"))
-    (insert "#+PROPERTY: BEAMER_col_ALL " org-beamer-column-widths "\n")))
-
-;;;###autoload
 (defun org-beamer-publish-to-latex (plist filename pub-dir)
   "Publish an Org file to a Beamer presentation (LaTeX).
 
@@ -1168,9 +1122,13 @@ Return output file name."
   ;; working directory and then moved to publishing directory.
   (org-publish-attachment
    plist
-   (org-latex-compile
-    (org-publish-org-to
-     'beamer filename ".tex" plist (file-name-directory filename)))
+   ;; Default directory could be anywhere when this function is
+   ;; called.  We ensure it is set to source file directory during
+   ;; compilation so as to not break links to external documents.
+   (let ((default-directory (file-name-directory filename)))
+     (org-latex-compile
+      (org-publish-org-to
+       'beamer filename ".tex" plist (file-name-directory filename))))
    pub-dir))
 
 
diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el
index 86ca3a6..9c0ba65 100644
--- a/lisp/org/ox-html.el
+++ b/lisp/org/ox-html.el
@@ -1,4 +1,4 @@
-;;; ox-html.el --- HTML Back-End for Org Export Engine
+;;; ox-html.el --- HTML Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -30,20 +30,24 @@
 
 ;;; Dependencies
 
+(require 'cl-lib)
+(require 'format-spec)
 (require 'ox)
 (require 'ox-publish)
-(require 'format-spec)
-(eval-when-compile (require 'cl) (require 'table nil 'noerror))
+(require 'table)
 
 
 ;;; Function Declarations
 
 (declare-function org-id-find-id-file "org-id" (id))
 (declare-function htmlize-region "ext:htmlize" (beg end))
-(declare-function org-pop-to-buffer-same-window
-                 "org-compat" (&optional buffer-or-name norecord label))
 (declare-function mm-url-decode-entities "mm-url" ())
 
+(defvar htmlize-css-name-prefix)
+(defvar htmlize-output-type)
+(defvar htmlize-output-type)
+(defvar htmlize-css-name-prefix)
+
 ;;; Define Back-End
 
 (org-export-define-backend 'html
@@ -72,13 +76,13 @@
     (latex-fragment . org-html-latex-fragment)
     (line-break . org-html-line-break)
     (link . org-html-link)
+    (node-property . org-html-node-property)
     (paragraph . org-html-paragraph)
     (plain-list . org-html-plain-list)
     (plain-text . org-html-plain-text)
     (planning . org-html-planning)
     (property-drawer . org-html-property-drawer)
     (quote-block . org-html-quote-block)
-    (quote-section . org-html-quote-section)
     (radio-target . org-html-radio-target)
     (section . org-html-section)
     (special-block . org-html-special-block)
@@ -96,7 +100,6 @@
     (underline . org-html-underline)
     (verbatim . org-html-verbatim)
     (verse-block . org-html-verse-block))
-  :export-block "HTML"
   :filters-alist '((:filter-options . org-html-infojs-install-script)
                   (:filter-final-output . org-html-final-function))
   :menu-entry
@@ -108,10 +111,10 @@
              (if a (org-html-export-to-html t s v b)
                (org-open-file (org-html-export-to-html nil s v b)))))))
   :options-alist
-  '((:html-extension nil nil org-html-extension)
-    (:html-link-org-as-html nil nil org-html-link-org-files-as-html)
-    (:html-doctype "HTML_DOCTYPE" nil org-html-doctype)
+  '((:html-doctype "HTML_DOCTYPE" nil org-html-doctype)
     (:html-container "HTML_CONTAINER" nil org-html-container-element)
+    (:description "DESCRIPTION" nil nil newline)
+    (:keywords "KEYWORDS" nil nil space)
     (:html-html5-fancy nil "html5-fancy" org-html-html5-fancy)
     (:html-link-use-abs-url nil "html-link-use-abs-url" 
org-html-link-use-abs-url)
     (:html-link-home "HTML_LINK_HOME" nil org-html-link-home)
@@ -121,12 +124,52 @@
     (:html-preamble nil "html-preamble" org-html-preamble)
     (:html-head "HTML_HEAD" nil org-html-head newline)
     (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline)
-    (:html-head-include-default-style nil "html-style" 
org-html-head-include-default-style)
+    (:subtitle "SUBTITLE" nil nil parse)
+    (:html-head-include-default-style
+     nil "html-style" org-html-head-include-default-style)
     (:html-head-include-scripts nil "html-scripts" 
org-html-head-include-scripts)
+    (:html-allow-name-attribute-in-anchors
+     nil nil org-html-allow-name-attribute-in-anchors)
+    (:html-divs nil nil org-html-divs)
+    (:html-checkbox-type nil nil org-html-checkbox-type)
+    (:html-extension nil nil org-html-extension)
+    (:html-footnote-format nil nil org-html-footnote-format)
+    (:html-footnote-separator nil nil org-html-footnote-separator)
+    (:html-footnotes-section nil nil org-html-footnotes-section)
+    (:html-format-drawer-function nil nil org-html-format-drawer-function)
+    (:html-format-headline-function nil nil org-html-format-headline-function)
+    (:html-format-inlinetask-function
+     nil nil org-html-format-inlinetask-function)
+    (:html-home/up-format nil nil org-html-home/up-format)
+    (:html-indent nil nil org-html-indent)
+    (:html-infojs-options nil nil org-html-infojs-options)
+    (:html-infojs-template nil nil org-html-infojs-template)
+    (:html-inline-image-rules nil nil org-html-inline-image-rules)
+    (:html-link-org-files-as-html nil nil org-html-link-org-files-as-html)
+    (:html-mathjax-options nil nil org-html-mathjax-options)
+    (:html-mathjax-template nil nil org-html-mathjax-template)
+    (:html-metadata-timestamp-format nil nil 
org-html-metadata-timestamp-format)
+    (:html-postamble-format nil nil org-html-postamble-format)
+    (:html-preamble-format nil nil org-html-preamble-format)
+    (:html-table-align-individual-fields
+     nil nil org-html-table-align-individual-fields)
+    (:html-table-caption-above nil nil org-html-table-caption-above)
+    (:html-table-data-tags nil nil org-html-table-data-tags)
+    (:html-table-header-tags nil nil org-html-table-header-tags)
+    (:html-table-use-header-tags-for-first-column
+     nil nil org-html-table-use-header-tags-for-first-column)
+    (:html-tag-class-prefix nil nil org-html-tag-class-prefix)
+    (:html-text-markup-alist nil nil org-html-text-markup-alist)
+    (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix)
+    (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel)
+    (:html-use-infojs nil nil org-html-use-infojs)
+    (:html-validation-link nil nil org-html-validation-link)
+    (:html-viewport nil nil org-html-viewport)
+    (:html-inline-images nil nil org-html-inline-images)
     (:html-table-attributes nil nil org-html-table-default-attributes)
-    (:html-table-row-tags nil nil org-html-table-row-tags)
+    (:html-table-row-open-tag nil nil org-html-table-row-open-tag)
+    (:html-table-row-close-tag nil nil org-html-table-row-close-tag)
     (:html-xml-declaration nil nil org-html-xml-declaration)
-    (:html-inline-images nil nil org-html-inline-images)
     (:infojs-opt "INFOJS_OPT" nil nil)
     ;; Redefine regular options.
     (:creator "CREATOR" nil org-html-creator-string)
@@ -186,7 +229,7 @@ property on the headline itself.")
 @licstart  The following is the entire license notice for the
 JavaScript code in this tag.
 
-Copyright (C) 2012-2013 Free Software Foundation, Inc.
+Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
 The JavaScript code in this tag is free software: you can
 redistribute it and/or modify it under the terms of the GNU
@@ -232,16 +275,22 @@ for the JavaScript code in this tag.
 (defconst org-html-style-default
   "<style type=\"text/css\">
  <!--/*--><![CDATA[/*><!--*/
-  .title  { text-align: center; }
+  .title  { text-align: center;
+             margin-bottom: .2em; }
+  .subtitle { text-align: center;
+              font-size: medium;
+              font-weight: bold;
+              margin-top:0; }
   .todo   { font-family: monospace; color: red; }
-  .done   { color: green; }
+  .done   { font-family: monospace; color: green; }
+  .priority { font-family: monospace; color: orange; }
   .tag    { background-color: #eee; font-family: monospace;
             padding: 2px; font-size: 80%; font-weight: normal; }
   .timestamp { color: #bebebe; }
   .timestamp-kwd { color: #5f9ea0; }
-  .right  { margin-left: auto; margin-right: 0px;  text-align: right; }
-  .left   { margin-left: 0px;  margin-right: auto; text-align: left; }
-  .center { margin-left: auto; margin-right: auto; text-align: center; }
+  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
+  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
+  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
   .underline { text-decoration: underline; }
   #postamble p, #preamble p { font-size: 90%; margin: .2em; }
   p.verse { margin-left: 3%; }
@@ -268,27 +317,110 @@ for the JavaScript code in this tag.
     border: 1px solid black;
   }
   pre.src:hover:before { display: inline;}
-  pre.src-sh:before    { content: 'sh'; }
-  pre.src-bash:before  { content: 'sh'; }
+  /* Languages per Org manual */
+  pre.src-asymptote:before { content: 'Asymptote'; }
+  pre.src-awk:before { content: 'Awk'; }
+  pre.src-C:before { content: 'C'; }
+  /* pre.src-C++ doesn't work in CSS */
+  pre.src-clojure:before { content: 'Clojure'; }
+  pre.src-css:before { content: 'CSS'; }
+  pre.src-D:before { content: 'D'; }
+  pre.src-ditaa:before { content: 'ditaa'; }
+  pre.src-dot:before { content: 'Graphviz'; }
+  pre.src-calc:before { content: 'Emacs Calc'; }
   pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
-  pre.src-R:before     { content: 'R'; }
-  pre.src-perl:before  { content: 'Perl'; }
-  pre.src-java:before  { content: 'Java'; }
-  pre.src-sql:before   { content: 'SQL'; }
+  pre.src-fortran:before { content: 'Fortran'; }
+  pre.src-gnuplot:before { content: 'gnuplot'; }
+  pre.src-haskell:before { content: 'Haskell'; }
+  pre.src-java:before { content: 'Java'; }
+  pre.src-js:before { content: 'Javascript'; }
+  pre.src-latex:before { content: 'LaTeX'; }
+  pre.src-ledger:before { content: 'Ledger'; }
+  pre.src-lisp:before { content: 'Lisp'; }
+  pre.src-lilypond:before { content: 'Lilypond'; }
+  pre.src-lua:before { content: 'Lua'; }
+  pre.src-matlab:before { content: 'MATLAB'; }
+  pre.src-mscgen:before { content: 'Mscgen'; }
+  pre.src-ocaml:before { content: 'Objective Caml'; }
+  pre.src-octave:before { content: 'Octave'; }
+  pre.src-org:before { content: 'Org mode'; }
+  pre.src-oz:before { content: 'OZ'; }
+  pre.src-plantuml:before { content: 'Plantuml'; }
+  pre.src-processing:before { content: 'Processing.js'; }
+  pre.src-python:before { content: 'Python'; }
+  pre.src-R:before { content: 'R'; }
+  pre.src-ruby:before { content: 'Ruby'; }
+  pre.src-sass:before { content: 'Sass'; }
+  pre.src-scheme:before { content: 'Scheme'; }
+  pre.src-screen:before { content: 'Gnu Screen'; }
+  pre.src-sed:before { content: 'Sed'; }
+  pre.src-sh:before { content: 'shell'; }
+  pre.src-sql:before { content: 'SQL'; }
+  pre.src-sqlite:before { content: 'SQLite'; }
+  /* additional languages in org.el's org-babel-load-languages alist */
+  pre.src-forth:before { content: 'Forth'; }
+  pre.src-io:before { content: 'IO'; }
+  pre.src-J:before { content: 'J'; }
+  pre.src-makefile:before { content: 'Makefile'; }
+  pre.src-maxima:before { content: 'Maxima'; }
+  pre.src-perl:before { content: 'Perl'; }
+  pre.src-picolisp:before { content: 'Pico Lisp'; }
+  pre.src-scala:before { content: 'Scala'; }
+  pre.src-shell:before { content: 'Shell Script'; }
+  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
+  /* additional language identifiers per \"defun org-babel-execute\"
+       in ob-*.el */
+  pre.src-cpp:before  { content: 'C++'; }
+  pre.src-abc:before  { content: 'ABC'; }
+  pre.src-coq:before  { content: 'Coq'; }
+  pre.src-groovy:before  { content: 'Groovy'; }
+  /* additional language identifiers from org-babel-shell-names in
+     ob-shell.el: ob-shell is the only babel language using a lambda to put
+     the execution function name together. */
+  pre.src-bash:before  { content: 'bash'; }
+  pre.src-csh:before  { content: 'csh'; }
+  pre.src-ash:before  { content: 'ash'; }
+  pre.src-dash:before  { content: 'dash'; }
+  pre.src-ksh:before  { content: 'ksh'; }
+  pre.src-mksh:before  { content: 'mksh'; }
+  pre.src-posh:before  { content: 'posh'; }
+  /* Additional Emacs modes also supported by the LaTeX listings package */
+  pre.src-ada:before { content: 'Ada'; }
+  pre.src-asm:before { content: 'Assembler'; }
+  pre.src-caml:before { content: 'Caml'; }
+  pre.src-delphi:before { content: 'Delphi'; }
+  pre.src-html:before { content: 'HTML'; }
+  pre.src-idl:before { content: 'IDL'; }
+  pre.src-mercury:before { content: 'Mercury'; }
+  pre.src-metapost:before { content: 'MetaPost'; }
+  pre.src-modula-2:before { content: 'Modula-2'; }
+  pre.src-pascal:before { content: 'Pascal'; }
+  pre.src-ps:before { content: 'PostScript'; }
+  pre.src-prolog:before { content: 'Prolog'; }
+  pre.src-simula:before { content: 'Simula'; }
+  pre.src-tcl:before { content: 'tcl'; }
+  pre.src-tex:before { content: 'TeX'; }
+  pre.src-plain-tex:before { content: 'Plain TeX'; }
+  pre.src-verilog:before { content: 'Verilog'; }
+  pre.src-vhdl:before { content: 'VHDL'; }
+  pre.src-xml:before { content: 'XML'; }
+  pre.src-nxml:before { content: 'XML'; }
+  /* add a generic configuration mode; LaTeX export needs an additional
+     (add-to-list 'org-latex-listings-langs '(conf \" \")) in .emacs */
+  pre.src-conf:before { content: 'Configuration File'; }
 
   table { border-collapse:collapse; }
   caption.t-above { caption-side: top; }
   caption.t-bottom { caption-side: bottom; }
   td, th { vertical-align:top;  }
-  th.right  { text-align: center;  }
-  th.left   { text-align: center;   }
-  th.center { text-align: center; }
-  td.right  { text-align: right;  }
-  td.left   { text-align: left;   }
-  td.center { text-align: center; }
+  th.org-right  { text-align: center;  }
+  th.org-left   { text-align: center;   }
+  th.org-center { text-align: center; }
+  td.org-right  { text-align: right;  }
+  td.org-left   { text-align: left;   }
+  td.org-center { text-align: center; }
   dt { font-weight: bold; }
-  .footpara:nth-child(2) { display: inline; }
-  .footpara { display: block; }
+  .footpara { display: inline; }
   .footdef  { margin-bottom: 1em; }
   .figure { padding: 1em; }
   .figure p { text-align: center; }
@@ -308,6 +440,7 @@ for the JavaScript code in this tag.
     { font-size: 10px; font-weight: bold; white-space: nowrap; }
   .org-info-js_search-highlight
     { background-color: #ffff00; color: #000000; font-weight: bold; }
+  .org-svg { width: 90%; }
   /*]]>*/-->
 </style>"
   "The default style specification for exported HTML files.
@@ -447,23 +580,24 @@ Option settings will replace the %MANAGER-OPTIONS cookie."
   :package-version '(Org . "8.0")
   :type 'string)
 
-(defun org-html-infojs-install-script (exp-plist backend)
+(defun org-html-infojs-install-script (exp-plist _backend)
   "Install script in export options when appropriate.
 EXP-PLIST is a plist containing export options.  BACKEND is the
 export back-end currently used."
   (unless (or (memq 'body-only (plist-get exp-plist :export-options))
-             (not org-html-use-infojs)
-             (and (eq org-html-use-infojs 'when-configured)
-                  (or (not (plist-get exp-plist :infojs-opt))
-                      (string= "" (plist-get exp-plist :infojs-opt))
-                      (string-match "\\<view:nil\\>"
-                                    (plist-get exp-plist :infojs-opt)))))
-    (let* ((template org-html-infojs-template)
+             (not (plist-get exp-plist :html-use-infojs))
+             (and (eq (plist-get exp-plist :html-use-infojs) 'when-configured)
+                  (let ((opt (plist-get exp-plist :infojs-opt)))
+                    (or (not opt)
+                        (string= "" opt)
+                        (string-match "\\<view:nil\\>" opt)))))
+    (let* ((template (plist-get exp-plist :html-infojs-template))
           (ptoc (plist-get exp-plist :with-toc))
           (hlevels (plist-get exp-plist :headline-levels))
           (sdepth hlevels)
           (tdepth (if (integerp ptoc) (min ptoc hlevels) hlevels))
           (options (plist-get exp-plist :infojs-opt))
+          (infojs-opt (plist-get exp-plist :html-infojs-options))
           (table org-html-infojs-opts-table)
           style)
       (dolist (entry table)
@@ -472,7 +606,7 @@ export back-end currently used."
               ;; Compute default values for script option OPT from
               ;; `org-html-infojs-options' variable.
               (default
-                (let ((default (cdr (assq opt org-html-infojs-options))))
+                (let ((default (cdr (assq opt infojs-opt))))
                   (if (and (symbolp default) (not (memq default '(t nil))))
                       (plist-get exp-plist default)
                     default)))
@@ -483,21 +617,21 @@ export back-end currently used."
                                           options))
                        (match-string 1 options)
                      default)))
-         (case opt
-           (path (setq template
-                       (replace-regexp-in-string
-                        "%SCRIPT_PATH" val template t t)))
-           (sdepth (when (integerp (read val))
-                     (setq sdepth (min (read val) sdepth))))
-           (tdepth (when (integerp (read val))
-                     (setq tdepth (min (read val) tdepth))))
-           (otherwise (setq val
-                            (cond
-                             ((or (eq val t) (equal val "t")) "1")
-                             ((or (eq val nil) (equal val "nil")) "0")
-                             ((stringp val) val)
-                             (t (format "%s" val))))
-                      (push (cons var val) style)))))
+         (pcase opt
+           (`path (setq template
+                        (replace-regexp-in-string
+                         "%SCRIPT_PATH" val template t t)))
+           (`sdepth (when (integerp (read val))
+                      (setq sdepth (min (read val) sdepth))))
+           (`tdepth (when (integerp (read val))
+                      (setq tdepth (min (read val) tdepth))))
+           (_ (setq val
+                    (cond
+                     ((or (eq val t) (equal val "t")) "1")
+                     ((or (eq val nil) (equal val "nil")) "0")
+                     ((stringp val) val)
+                     (t (format "%s" val))))
+              (push (cons var val) style)))))
       ;; Now we set the depth of the *generated* TOC to SDEPTH,
       ;; because the toc will actually determine the splitting.  How
       ;; much of the toc will actually be displayed is governed by the
@@ -509,9 +643,9 @@ export back-end currently used."
       (push (cons "TOC_DEPTH" tdepth) style)
       ;; Build style string.
       (setq style (mapconcat
-                  (lambda (x) (format "org_html_manager.set(\"%s\", \"%s\");"
-                                 (car x)
-                                 (cdr x)))
+                  (lambda (x)
+                    (format "org_html_manager.set(\"%s\", \"%s\");"
+                            (car x) (cdr x)))
                   style "\n"))
       (when (and style (> (length style) 0))
        (and (string-match "%MANAGER_OPTIONS" template)
@@ -561,17 +695,9 @@ Warning: non-nil may break indentation of source code 
blocks."
   :package-version '(Org . "8.0")
   :type 'boolean)
 
-(defcustom org-html-use-unicode-chars nil
-  "Non-nil means to use unicode characters instead of HTML entities."
-  :group 'org-export-html
-  :version "24.4"
-  :package-version '(Org . "8.0")
-  :type 'boolean)
-
 ;;;; Drawers
 
-(defcustom org-html-format-drawer-function
-  (lambda (name contents) contents)
+(defcustom org-html-format-drawer-function (lambda (_name contents) contents)
   "Function called to format a drawer in HTML code.
 
 The function must accept two parameters:
@@ -628,28 +754,30 @@ document title."
   :group 'org-export-html
   :type 'integer)
 
-(defcustom org-html-format-headline-function 'ignore
+(defcustom org-html-format-headline-function
+  'org-html-format-headline-default-function
   "Function to format headline text.
 
-This function will be called with 5 arguments:
+This function will be called with six arguments:
 TODO      the todo keyword (string or nil).
 TODO-TYPE the type of todo (symbol: `todo', `done', nil)
 PRIORITY  the priority of the headline (integer or nil)
 TEXT      the main headline text (string).
 TAGS      the tags (string or nil).
+INFO      the export options (plist).
 
 The function result will be used in the section format string."
   :group 'org-export-html
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type 'function)
 
 ;;;; HTML-specific
 
-(defcustom org-html-allow-name-attribute-in-anchors t
+(defcustom org-html-allow-name-attribute-in-anchors nil
   "When nil, do not set \"name\" attribute in anchors.
-By default, anchors are formatted with both \"id\" and \"name\"
-attributes, when appropriate."
+By default, when appropriate, anchors are formatted with \"id\"
+but without \"name\" attribute."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -657,21 +785,23 @@ attributes, when appropriate."
 
 ;;;; Inlinetasks
 
-(defcustom org-html-format-inlinetask-function 'ignore
+(defcustom org-html-format-inlinetask-function
+  'org-html-format-inlinetask-default-function
   "Function called to format an inlinetask in HTML code.
 
-The function must accept six parameters:
+The function must accept seven parameters:
   TODO      the todo keyword, as a string
   TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
   PRIORITY  the inlinetask priority, as a string
   NAME      the inlinetask name, as a string.
   TAGS      the inlinetask tags, as a list of strings.
   CONTENTS  the contents of the inlinetask, as a string.
+  INFO      the export options, as a plist
 
 The function should return the string to be exported."
   :group 'org-export-html
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type 'function)
 
 ;;;; LaTeX
@@ -685,24 +815,20 @@ fragments.
 This option can also be set with the +OPTIONS line,
 e.g. \"tex:mathjax\".  Allowed values are:
 
-nil            Ignore math snippets.
-`verbatim'     Keep everything in verbatim
-`dvipng'       Process the LaTeX fragments to images.  This will also
-               include processing of non-math environments.
-`imagemagick'  Convert the LaTeX fragments to pdf files and use
-               imagemagick to convert pdf files to png files.
-`mathjax'      Do MathJax preprocessing and arrange for MathJax.js to
-               be loaded.
-t              Synonym for `mathjax'."
+  nil           Ignore math snippets.
+  `verbatim'    Keep everything in verbatim
+  `mathjax', t  Do MathJax preprocessing and arrange for MathJax.js to
+                be loaded.
+  SYMBOL        Any symbol defined in `org-preview-latex-process-alist',
+                e.g., `dvipng'."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
   :type '(choice
          (const :tag "Do not process math in any way" nil)
-         (const :tag "Use dvipng to make images" dvipng)
-         (const :tag "Use imagemagick to make images" imagemagick)
+         (const :tag "Leave math verbatim" verbatim)
          (const :tag "Use MathJax to display math" mathjax)
-         (const :tag "Leave math verbatim" verbatim)))
+         (symbol :tag "Convert to image to display math" :value dvipng)))
 
 ;;;; Links :: Generic
 
@@ -710,11 +836,11 @@ t              Synonym for `mathjax'."
   "Non-nil means make file links to `file.org' point to `file.html'.
 When `org-mode' is exporting an `org-mode' file to HTML, links to
 non-html files are directly put into a href tag in HTML.
-However, links to other Org-mode files (recognized by the
-extension `.org') should become links to the corresponding html
+However, links to other Org files (recognized by the extension
+\".org\") should become links to the corresponding HTML
 file, assuming that the linked `org-mode' file will also be
 converted to HTML.
-When nil, the links still point to the plain `.org' file."
+When nil, the links still point to the plain \".org\" file."
   :group 'org-export-html
   :type 'boolean)
 
@@ -745,22 +871,20 @@ link's path."
 
 ;;;; Plain Text
 
-(defcustom org-html-protect-char-alist
+(defvar org-html-protect-char-alist
   '(("&" . "&amp;")
     ("<" . "&lt;")
     (">" . "&gt;"))
-  "Alist of characters to be converted by `org-html-protect'."
-  :group 'org-export-html
-  :type '(repeat (cons (string :tag "Character")
-                      (string :tag "HTML equivalent"))))
+  "Alist of characters to be converted by `org-html-encode-plain-text'.")
 
 ;;;; Src Block
 
 (defcustom org-html-htmlize-output-type 'inline-css
   "Output type to be used by htmlize when formatting code snippets.
-Choices are `css', to export the CSS selectors only, or `inline-css', to
-export the CSS attribute values inline in the HTML.  We use as default
-`inline-css', in order to make the resulting HTML self-containing.
+Choices are `css' to export the CSS selectors only,`inline-css'
+to export the CSS attribute values inline in the HTML or `nil' to
+export plain text.  We use as default `inline-css', in order to
+make the resulting HTML self-containing.
 
 However, this will fail when using Emacs in batch mode for export, because
 then no rich font definitions are in place.  It will also not be good if
@@ -771,9 +895,9 @@ a style file to define the look of these classes.
 To get a start for your css file, start Emacs session and make sure that
 all the faces you are interested in are defined, for example by loading files
 in all modes you want.  Then, use the command
-\\[org-html-htmlize-generate-css] to extract class definitions."
+`\\[org-html-htmlize-generate-css]' to extract class definitions."
   :group 'org-export-html
-  :type '(choice (const css) (const inline-css)))
+  :type '(choice (const css) (const inline-css) (const nil)))
 
 (defcustom org-html-htmlize-font-prefix "org-"
   "The prefix for CSS class names for htmlize font specifications."
@@ -796,7 +920,7 @@ When exporting to HTML5, these values will be disregarded."
                :value-type (string :tag "Value")))
 
 (defcustom org-html-table-header-tags '("<th scope=\"%s\"%s>" . "</th>")
-  "The opening tag for table header fields.
+  "The opening and ending tags for table header fields.
 This is customizable so that alignment options can be specified.
 The first %s will be filled with the scope of the field, either row or col.
 The second %s will be replaced by a style entry to align the field.
@@ -806,7 +930,7 @@ See also the variable 
`org-html-table-align-individual-fields'."
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
 
 (defcustom org-html-table-data-tags '("<td%s>" . "</td>")
-  "The opening tag for table data fields.
+  "The opening and ending tags for table data fields.
 This is customizable so that alignment options can be specified.
 The first %s will be filled with the scope of the field, either row or col.
 The second %s will be replaced by a style entry to align the field.
@@ -814,43 +938,50 @@ See also the variable 
`org-html-table-align-individual-fields'."
   :group 'org-export-html
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
 
-(defcustom org-html-table-row-tags '("<tr>" . "</tr>")
-  "The opening and ending tags for table rows.
+(defcustom org-html-table-row-open-tag "<tr>"
+  "The opening tag for table rows.
 This is customizable so that alignment options can be specified.
-Instead of strings, these can be Lisp forms that will be
+Instead of strings, these can be a Lisp function that will be
 evaluated for each row in order to construct the table row tags.
 
-During evaluation, these variables will be dynamically bound so that
-you can reuse them:
+The function will be called with these arguments:
 
-       `row-number': row number (0 is the first row)
-  `rowgroup-number': group number of current row
- `start-rowgroup-p': non-nil means the row starts a group
-   `end-rowgroup-p': non-nil means the row ends a group
-        `top-row-p': non-nil means this is the top row
-     `bottom-row-p': non-nil means this is the bottom row
+         `number': row number (0 is the first row)
+   `group-number': group number of current row
+   `start-group?': non-nil means the row starts a group
+     `end-group?': non-nil means the row ends a group
+           `top?': non-nil means this is the top row
+        `bottom?': non-nil means this is the bottom row
 
 For example:
 
-\(setq org-html-table-row-tags
-      (cons \\='(cond (top-row-p \"<tr class=\\\"tr-top\\\">\")
-                   (bottom-row-p \"<tr class=\\\"tr-bottom\\\">\")
-                   (t (if (= (mod row-number 2) 1)
-                         \"<tr class=\\\"tr-odd\\\">\"
-                       \"<tr class=\\\"tr-even\\\">\")))
-           \"</tr>\"))
+  (setq org-html-table-row-open-tag
+        (lambda (number group-number start-group? end-group-p top? bottom?)
+           (cond (top? \"<tr class=\\\"tr-top\\\">\")
+                 (bottom? \"<tr class=\\\"tr-bottom\\\">\")
+                 (t (if (= (mod number 2) 1)
+                        \"<tr class=\\\"tr-odd\\\">\"
+                      \"<tr class=\\\"tr-even\\\">\")))))
 
 will use the \"tr-top\" and \"tr-bottom\" classes for the top row
 and the bottom row, and otherwise alternate between \"tr-odd\" and
 \"tr-even\" for odd and even rows."
   :group 'org-export-html
-  :type '(cons
-         (choice :tag "Opening tag"
-                 (string :tag "Specify")
-                 (sexp))
-         (choice :tag "Closing tag"
-                 (string :tag "Specify")
-                 (sexp))))
+  :type '(choice :tag "Opening tag"
+                (string :tag "Specify")
+                (function)))
+
+(defcustom org-html-table-row-close-tag "</tr>"
+  "The closing tag for table rows.
+This is customizable so that alignment options can be specified.
+Instead of strings, this can be a Lisp function that will be
+evaluated for each row in order to construct the table row tags.
+
+See documentation of `org-html-table-row-open-tag'."
+  :group 'org-export-html
+  :type '(choice :tag "Closing tag"
+                (string :tag "Specify")
+                (function)))
 
 (defcustom org-html-table-align-individual-fields t
   "Non-nil means attach style attributes for alignment to each table field.
@@ -921,7 +1052,10 @@ publishing, with :html-doctype."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'string)
+  :type (append
+        '(choice)
+        (mapcar (lambda (x) `(const ,(car x))) org-html-doctype-alist)
+        '((string :tag "Custom doctype" ))))
 
 (defcustom org-html-html5-fancy nil
   "Non-nil means using new HTML5 elements.
@@ -954,7 +1088,7 @@ org-info.js for your website."
     (content   "div" "content")
     (postamble "div" "postamble"))
   "Alist of the three section elements for HTML export.
-The car of each entry is one of 'preamble, 'content or 'postamble.
+The car of each entry is one of `preamble', `content' or `postamble'.
 The cdrs of each entry are the ELEMENT_TYPE and ID for each
 section of the exported document.
 
@@ -973,6 +1107,41 @@ org-info.js for your website."
               (list :tag "Postamble" (const :format "" postamble)
                     (string :tag "     id") (string :tag "element"))))
 
+(defconst org-html-checkbox-types
+  '((unicode .
+     ((on . "&#x2611;") (off . "&#x2610;") (trans . "&#x2610;")))
+    (ascii .
+     ((on . "<code>[X]</code>")
+      (off . "<code>[&#xa0;]</code>")
+      (trans . "<code>[-]</code>")))
+    (html .
+         ((on . "<input type='checkbox' checked='checked' />")
+         (off . "<input type='checkbox' />")
+         (trans . "<input type='checkbox' />"))))
+  "Alist of checkbox types.
+The cdr of each entry is an alist list three checkbox types for
+HTML export: `on', `off' and `trans'.
+
+The choices are:
+  `unicode' Unicode characters (HTML entities)
+  `ascii'   ASCII characters
+  `html'    HTML checkboxes
+
+Note that only the ascii characters implement tri-state
+checkboxes. The other two use the `off' checkbox for `trans'.")
+
+(defcustom org-html-checkbox-type 'ascii
+  "The type of checkboxes to use for HTML export.
+See `org-html-checkbox-types' for for the values used for each
+option."
+  :group 'org-export-html
+  :version "24.4"
+  :package-version '(Org . "8.0")
+  :type '(choice
+         (const :tag "ASCII characters" ascii)
+         (const :tag "Unicode characters" unicode)
+         (const :tag "HTML checkboxes" html)))
+
 (defcustom org-html-metadata-timestamp-format "%Y-%m-%d %a %H:%M"
   "Format used for timestamps in preamble, postamble and metadata.
 See `format-time-string' for more information on its components."
@@ -984,82 +1153,107 @@ See `format-time-string' for more information on its 
components."
 ;;;; Template :: Mathjax
 
 (defcustom org-html-mathjax-options
-  '((path  "http://orgmode.org/mathjax/MathJax.js";)
+  '((path 
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML";
 )
     (scale "100")
     (align "center")
-    (indent "2em")
-    (mathml nil))
+    (font "TeX")
+    (linebreaks "false")
+    (autonumber "AMS")
+    (indent "0em")
+    (multlinewidth "85%")
+    (tagindent ".8em")
+    (tagside "right"))
   "Options for MathJax setup.
 
-path        The path where to find MathJax
-scale       Scaling for the HTML-CSS backend, usually between 100 and 133
-align       How to align display math: left, center, or right
-indent      If align is not center, how far from the left/right side?
-mathml      Should a MathML player be used if available?
-            This is faster and reduces bandwidth use, but currently
-            sometimes has lower spacing quality.  Therefore, the default is
-            nil.  When browsers get better, this switch can be flipped.
+Alist of the following elements.  All values are strings.
+
+path          The path to MathJax.
+scale         Scaling with HTML-CSS, MathML and SVG output engines.
+align         How to align display math: left, center, or right.
+font          The font to use with HTML-CSS and SVG output.  As of MathJax 2.5
+              the following values are understood: \"TeX\", \"STIX-Web\",
+              \"Asana-Math\", \"Neo-Euler\", \"Gyre-Pagella\",
+              \"Gyre-Termes\", and \"Latin-Modern\".
+linebreaks    Let MathJax perform automatic linebreaks.  Valid values
+              are \"true\" and \"false\".
+indent        If align is not center, how far from the left/right side?
+              Valid values are \"left\" and \"right\"
+multlinewidth The width of the multline environment.
+autonumber    How to number equations.  Valid values are \"None\",
+              \"all\" and \"AMS Math\".
+tagindent     The amount tags are indented.
+tagside       Which side to show tags/labels on.  Valid values are
+              \"left\" and \"right\"
 
 You can also customize this for each buffer, using something like
 
-#+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\""
+#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
+
+For further information about MathJax options, see the MathJax documentation:
+
+  http://docs.mathjax.org/";
   :group 'org-export-html
+  :package-version '(Org . "8.3")
   :type '(list :greedy t
-             (list :tag "path   (the path from where to load MathJax.js)"
-                   (const :format "       " path) (string))
-             (list :tag "scale  (scaling for the displayed math)"
-                   (const :format "       " scale) (string))
-             (list :tag "align  (alignment of displayed equations)"
-                   (const :format "       " align) (string))
-             (list :tag "indent (indentation with left or right alignment)"
-                   (const :format "       " indent) (string))
-             (list :tag "mathml (should MathML display be used is possible)"
-                   (const :format "       " mathml) (boolean))))
+              (list :tag "path   (the path from where to load MathJax.js)"
+                    (const :format "       " path) (string))
+              (list :tag "scale  (scaling for the displayed math)"
+                    (const :format "       " scale) (string))
+              (list :tag "align  (alignment of displayed equations)"
+                    (const :format "       " align) (string))
+              (list :tag "font (used to display math)"
+                    (const :format "            " font)
+                    (choice (const "TeX")
+                            (const "STIX-Web")
+                            (const "Asana-Math")
+                            (const "Neo-Euler")
+                            (const "Gyre-Pagella")
+                            (const "Gyre-Termes")
+                            (const "Latin-Modern")))
+              (list :tag "linebreaks (automatic line-breaking)"
+                    (const :format "      " linebreaks)
+                    (choice (const "true")
+                            (const "false")))
+              (list :tag "autonumber (when should equations be numbered)"
+                    (const :format "      " autonumber)
+                    (choice (const "AMS")
+                            (const "None")
+                            (const "All")))
+              (list :tag "indent (indentation with left or right alignment)"
+                    (const :format "       " indent) (string))
+              (list :tag "multlinewidth (width to use for the multline 
environment)"
+                    (const :format "       " multlinewidth) (string))
+              (list :tag "tagindent (the indentation of tags from left or 
right)"
+                    (const :format "     " tagindent) (string))
+              (list :tag "tagside (location of tags)"
+                    (const :format "      " tagside)
+                    (choice (const "left")
+                            (const "right")))))
 
 (defcustom org-html-mathjax-template
-  "<script type=\"text/javascript\" src=\"%PATH\"></script>
-<script type=\"text/javascript\">
-<!--/*--><![CDATA[/*><!--*/
+  "<script type=\"text/x-mathjax-config\">
     MathJax.Hub.Config({
-        // Only one of the two following lines, depending on user settings
-        // First allows browser-native MathML display, second forces HTML/CSS
-        :MMLYES: config: [\"MMLorHTML.js\"], jax: [\"input/TeX\"],
-        :MMLNO: jax: [\"input/TeX\", \"output/HTML-CSS\"],
-        extensions: [\"tex2jax.js\",\"TeX/AMSmath.js\",\"TeX/AMSsymbols.js\",
-                     \"TeX/noUndefined.js\"],
-        tex2jax: {
-            inlineMath: [ [\"\\\\(\",\"\\\\)\"] ],
-            displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"], 
[\"\\\\begin{displaymath}\",\"\\\\end{displaymath}\"] ],
-            skipTags: 
[\"script\",\"noscript\",\"style\",\"textarea\",\"pre\",\"code\"],
-            ignoreClass: \"tex2jax_ignore\",
-            processEscapes: false,
-            processEnvironments: true,
-            preview: \"TeX\"
-        },
-        showProcessingMessages: true,
         displayAlign: \"%ALIGN\",
         displayIndent: \"%INDENT\",
 
-        \"HTML-CSS\": {
-             scale: %SCALE,
-             availableFonts: [\"STIX\",\"TeX\"],
-             preferredFont: \"TeX\",
-             webFont: \"TeX\",
-             imageFont: \"TeX\",
-             showMathMenu: true,
-        },
-        MMLorHTML: {
-             prefer: {
-                 MSIE:    \"MML\",
-                 Firefox: \"MML\",
-                 Opera:   \"HTML\",
-                 other:   \"HTML\"
+        \"HTML-CSS\": { scale: %SCALE,
+                        linebreaks: { automatic: \"%LINEBREAKS\" },
+                        webFont: \"%FONT\"
+                       },
+        SVG: {scale: %SCALE,
+              linebreaks: { automatic: \"%LINEBREAKS\" },
+              font: \"%FONT\"},
+        NativeMML: {scale: %SCALE},
+        TeX: { equationNumbers: {autoNumber: \"%AUTONUMBER\"},
+               MultLineWidth: \"%MULTLINEWIDTH\",
+               TagSide: \"%TAGSIDE\",
+               TagIndent: \"%TAGINDENT\"
              }
-        }
-    });
-/*]]>*///-->
-</script>"
-  "The MathJax setup for XHTML files."
+});
+</script>
+<script type=\"text/javascript\"
+        src=\"%PATH\"></script>"
+  "The MathJax template.  See also `org-html-mathjax-options'."
   :group 'org-export-html
   :type 'string)
 
@@ -1068,7 +1262,7 @@ You can also customize this for each buffer, using 
something like
 (defcustom org-html-postamble 'auto
   "Non-nil means insert a postamble in HTML export.
 
-When set to 'auto, check against the
+When set to `auto', check against the
 `org-export-with-author/email/creator/date' variables to set the
 content of the postamble.  When set to a string, use this string
 as the postamble.  When t, insert a string as defined by the
@@ -1101,6 +1295,7 @@ The second element of each list is a format string to 
format the
 postamble itself.  This format string can contain these elements:
 
   %t stands for the title.
+  %s stands for the subtitle.
   %a stands for the author's name.
   %e stands for the author's email.
   %d stands for the date.
@@ -1165,6 +1360,7 @@ The second element of each list is a format string to 
format the
 preamble itself.  This format string can contain these elements:
 
   %t stands for the title.
+  %s stands for the subtitle.
   %a stands for the author's name.
   %e stands for the author's email.
   %d stands for the date.
@@ -1216,8 +1412,6 @@ ignored."
 
 ;;;; Template :: Scripts
 
-(define-obsolete-variable-alias
-  'org-html-style-include-scripts 'org-html-head-include-scripts "24.4")
 (defcustom org-html-head-include-scripts t
   "Non-nil means include the JavaScript snippets in exported HTML files.
 The actual script is defined in `org-html-scripts' and should
@@ -1229,8 +1423,6 @@ not be modified."
 
 ;;;; Template :: Styles
 
-(define-obsolete-variable-alias
-  'org-html-style-include-default 'org-html-head-include-default-style "24.4")
 (defcustom org-html-head-include-default-style t
   "Non-nil means include the default style in exported HTML files.
 The actual style is defined in `org-html-style-default' and
@@ -1243,7 +1435,6 @@ style information."
 ;;;###autoload
 (put 'org-html-head-include-default-style 'safe-local-variable 'booleanp)
 
-(define-obsolete-variable-alias 'org-html-style 'org-html-head "24.4")
 (defcustom org-html-head ""
   "Org-wide head definitions for exported HTML files.
 
@@ -1293,6 +1484,54 @@ or for publication projects using the :html-head-extra 
property."
 ;;;###autoload
 (put 'org-html-head-extra 'safe-local-variable 'stringp)
 
+;;;; Template :: Viewport
+
+(defcustom org-html-viewport '((width "device-width")
+                              (initial-scale "1")
+                              (minimum-scale "")
+                              (maximum-scale "")
+                              (user-scalable ""))
+  "Viewport options for mobile-optimized sites.
+
+The following values are recognized
+
+width          Size of the viewport.
+initial-scale  Zoom level when the page is first loaded.
+minimum-scale  Minimum allowed zoom level.
+maximum-scale  Maximum allowed zoom level.
+user-scalable  Whether zoom can be changed.
+
+The viewport meta tag is inserted if this variable is non-nil.
+
+See the following site for a reference:
+https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag";
+  :group 'org-export-html
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice (const :tag "Disable" nil)
+                (list :tag "Enable"
+                      (list :tag "Width of viewport"
+                            (const :format "             " width)
+                            (choice (const :tag "unset" "")
+                                    (string)))
+                      (list :tag "Initial scale"
+                            (const :format "             " initial-scale)
+                            (choice (const :tag "unset" "")
+                                    (string)))
+                      (list :tag "Minimum scale/zoom"
+                            (const :format "             " minimum-scale)
+                            (choice (const :tag "unset" "")
+                                    (string)))
+                      (list :tag "Maximum scale/zoom"
+                            (const :format "             " maximum-scale)
+                            (choice (const :tag "unset" "")
+                                    (string)))
+                      (list :tag "User scalable/zoomable"
+                            (const :format "             " user-scalable)
+                            (choice (const :tag "unset" "")
+                                    (const "true")
+                                    (const "false"))))))
+
 ;;;; Todos
 
 (defcustom org-html-todo-kwd-class-prefix ""
@@ -1315,22 +1554,33 @@ CSS classes, then this prefix can be very useful."
   (let ((dt (downcase (plist-get info :html-doctype))))
        (member dt '("html5" "xhtml5" "<!doctype html>"))))
 
+(defun org-html--html5-fancy-p (info)
+  "Non-nil when exporting to HTML5 with fancy elements.
+INFO is the current state of the export process, as a plist."
+  (and (plist-get info :html-html5-fancy)
+       (org-html-html5-p info)))
+
 (defun org-html-close-tag (tag attr info)
-  (concat "<" tag " " attr
+  "Return close-tag for string TAG.
+ATTR specifies additional attributes.  INFO is a property list
+containing current export state."
+  (concat "<" tag
+         (org-string-nw-p (concat " " attr))
          (if (org-html-xhtml-p info) " />" ">")))
 
 (defun org-html-doctype (info)
-  "Return correct html doctype tag from `org-html-doctype-alist',
-or the literal value of :html-doctype from INFO if :html-doctype
-is not found in the alist.
-INFO is a plist used as a communication channel."
+  "Return correct HTML doctype tag.
+INFO is a plist used as a communication channel.  Doctype tag is
+extracted from `org-html-doctype-alist', or the literal value
+of :html-doctype from INFO if :html-doctype is not found in the
+alist."
   (let ((dt (plist-get info :html-doctype)))
     (or (cdr (assoc dt org-html-doctype-alist)) dt)))
 
 (defun org-html--make-attribute-string (attributes)
   "Return a list of attributes, as a string.
-ATTRIBUTES is a plist where values are either strings or nil. An
-attributes with a nil value will be omitted from the result."
+ATTRIBUTES is a plist where values are either strings or nil.  An
+attribute with a nil value will be omitted from the result."
   (let (output)
     (dolist (item attributes (mapconcat 'identity (nreverse output) " "))
       (cond ((null item) (pop output))
@@ -1345,15 +1595,13 @@ attributes with a nil value will be omitted from the 
result."
 INFO is a plist used as a communication channel.  When optional
 arguments CAPTION and LABEL are given, use them for caption and
 \"id\" attribute."
-  (let ((html5-fancy (and (org-html-html5-p info)
-                         (plist-get info :html-html5-fancy))))
-    (format (if html5-fancy "\n<figure%s>%s%s\n</figure>"
-             "\n<div%s class=\"figure\">%s%s\n</div>")
+  (let ((html5-fancy (org-html--html5-fancy-p info)))
+    (format (if html5-fancy "\n<figure%s>\n%s%s\n</figure>"
+             "\n<div%s class=\"figure\">\n%s%s\n</div>")
            ;; ID.
-           (if (not (org-string-nw-p label)) ""
-             (format " id=\"%s\"" (org-export-solidify-link-text label)))
+           (if (org-string-nw-p label) (format " id=\"%s\"" label) "")
            ;; Contents.
-           (format "\n<p>%s</p>" contents)
+           (if html5-fancy contents (format "<p>%s</p>" contents))
            ;; Caption.
            (if (not (org-string-nw-p caption)) ""
              (format (if html5-fancy "\n<figcaption>%s</figcaption>"
@@ -1366,17 +1614,42 @@ SOURCE is a string specifying the location of the image.
 ATTRIBUTES is a plist, as returned by
 `org-export-read-attribute'.  INFO is a plist used as
 a communication channel."
-  (org-html-close-tag
-   "img"
-   (org-html--make-attribute-string
-    (org-combine-plists
-     (list :src source
-          :alt (if (string-match-p "^ltxpng/" source)
-                   (org-html-encode-plain-text
-                    (org-find-text-property-in-string 'org-latex-src source))
-                 (file-name-nondirectory source)))
-     attributes))
-   info))
+  (if (string= "svg" (file-name-extension source))
+      (org-html--svg-image source attributes info)
+    (org-html-close-tag
+     "img"
+     (org-html--make-attribute-string
+      (org-combine-plists
+       (list :src source
+            :alt (if (string-match-p "^ltxpng/" source)
+                     (org-html-encode-plain-text
+                      (org-find-text-property-in-string 'org-latex-src source))
+                   (file-name-nondirectory source)))
+       attributes))
+     info)))
+
+(defun org-html--svg-image (source attributes info)
+  "Return \"object\" embedding svg file SOURCE with given ATTRIBUTES.
+INFO is a plist used as a communication channel.
+
+The special attribute \"fallback\" can be used to specify a
+fallback image file to use if the object embedding is not
+supported.  CSS class \"org-svg\" is assigned as the class of the
+object unless a different class is specified with an attribute."
+  (let ((fallback (plist-get attributes :fallback))
+       (attrs (org-html--make-attribute-string
+               (org-combine-plists
+                 ;; Remove fallback attribute, which is not meant to
+                 ;; appear directly in the attributes string, and
+                 ;; provide a default class if none is set.
+                 '(:class "org-svg") attributes '(:fallback nil)))))
+    (format "<object type=\"image/svg+xml\" data=\"%s\" %s>\n%s</object>"
+           source
+           attrs
+           (if fallback
+               (org-html-close-tag
+                "img" (format "src=\"%s\" %s" fallback attrs) info)
+             "Sorry, your browser does not support SVG."))))
 
 (defun org-html--textarea-block (element)
   "Transcode ELEMENT into a textarea block.
@@ -1388,7 +1661,7 @@ ELEMENT is either a src block or an example block."
            (or (plist-get attr :height) (org-count-lines code))
            code)))
 
-(defun org-html--has-caption-p (element &optional info)
+(defun org-html--has-caption-p (element &optional _info)
   "Non-nil when ELEMENT has a caption affiliated keyword.
 INFO is a plist used as a communication channel.  This function
 is meant to be used as a predicate for `org-export-get-ordinal' or
@@ -1435,7 +1708,7 @@ produce code that uses these same face definitions."
        (when (and (symbolp f) (or (not i) (not (listp i))))
          (insert (org-add-props (copy-sequence "1") nil 'face f))))
       (htmlize-region (point-min) (point-max))))
-  (org-pop-to-buffer-same-window "*html*")
+  (pop-to-buffer-same-window "*html*")
   (goto-char (point-min))
   (if (re-search-forward "<style" nil t)
       (delete-region (point-min) (match-beginning 0)))
@@ -1447,59 +1720,44 @@ produce code that uses these same face definitions."
 
 (defun org-html--make-string (n string)
   "Build a string by concatenating N times STRING."
-  (let (out) (dotimes (i n out) (setq out (concat string out)))))
+  (let (out) (dotimes (_ n out) (setq out (concat string out)))))
 
 (defun org-html-fix-class-name (kwd)   ; audit callers of this function
   "Turn todo keyword KWD into a valid class name.
 Replaces invalid characters with \"_\"."
-  (save-match-data
-    (while (string-match "[^a-zA-Z0-9_]" kwd)
-      (setq kwd (replace-match "_" t t kwd))))
-  kwd)
-
-(defun org-html-format-footnote-reference (n def refcnt)
-  "Format footnote reference N with definition DEF into HTML."
-  (let ((extra (if (= refcnt 1) "" (format ".%d"  refcnt))))
-    (format org-html-footnote-format
-           (let* ((id (format "fnr.%s%s" n extra))
-                  (href (format " href=\"#fn.%s\"" n))
-                  (attributes (concat " class=\"footref\"" href)))
-             (org-html--anchor id n attributes)))))
-
-(defun org-html-format-footnotes-section (section-name definitions)
-  "Format footnotes section SECTION-NAME."
-  (if (not definitions) ""
-    (format org-html-footnotes-section section-name definitions)))
-
-(defun org-html-format-footnote-definition (fn)
-  "Format the footnote definition FN."
-  (let ((n (car fn)) (def (cdr fn)))
-    (format
-     "<div class=\"footdef\">%s %s</div>\n"
-     (format org-html-footnote-format
-            (let* ((id (format "fn.%s" n))
-                   (href (format " href=\"#fnr.%s\"" n))
-                   (attributes (concat " class=\"footnum\"" href)))
-              (org-html--anchor id n attributes)))
-     def)))
+  (replace-regexp-in-string "[^a-zA-Z0-9_]" "_" kwd nil t))
 
 (defun org-html-footnote-section (info)
   "Format the footnote section.
 INFO is a plist used as a communication channel."
-  (let* ((fn-alist (org-export-collect-footnote-definitions
-                   (plist-get info :parse-tree) info))
+  (let* ((fn-alist (org-export-collect-footnote-definitions info))
         (fn-alist
-         (loop for (n type raw) in fn-alist collect
-               (cons n (if (eq (org-element-type raw) 'org-data)
-                           (org-trim (org-export-data raw info))
-                         (format "<p>%s</p>"
-                                 (org-trim (org-export-data raw info))))))))
+         (cl-loop for (n _type raw) in fn-alist collect
+                  (cons n (if (eq (org-element-type raw) 'org-data)
+                              (org-trim (org-export-data raw info))
+                            (format "<div class=\"footpara\">%s</div>"
+                                    (org-trim (org-export-data raw info))))))))
     (when fn-alist
-      (org-html-format-footnotes-section
+      (format
+       (plist-get info :html-footnotes-section)
        (org-html--translate "Footnotes" info)
        (format
        "\n%s\n"
-       (mapconcat 'org-html-format-footnote-definition fn-alist "\n"))))))
+       (mapconcat
+        (lambda (fn)
+          (let ((n (car fn)) (def (cdr fn)))
+            (format
+             "<div class=\"footdef\">%s %s</div>\n"
+             (format
+              (plist-get info :html-footnote-format)
+              (org-html--anchor
+               (format "fn.%d" n)
+               n
+               (format " class=\"footnum\" href=\"#fnr.%d\"" n)
+               info))
+             def)))
+        fn-alist
+        "\n"))))))
 
 
 ;;; Template
@@ -1529,37 +1787,52 @@ INFO is a plist used as a communication channel."
                                             'mime-charset))
                     "iso-8859-1")))
     (concat
-     (format "<title>%s</title>\n" title)
      (when (plist-get info :time-stamp-file)
        (format-time-string
-        (concat "<!-- " org-html-metadata-timestamp-format " -->\n")))
+       (concat "<!-- "
+               (plist-get info :html-metadata-timestamp-format)
+               " -->\n")))
      (format
       (if (org-html-html5-p info)
-         (org-html-close-tag "meta" " charset=\"%s\"" info)
+         (org-html-close-tag "meta" "charset=\"%s\"" info)
        (org-html-close-tag
-        "meta" " http-equiv=\"Content-Type\" content=\"text/html;charset=%s\""
+        "meta" "http-equiv=\"Content-Type\" content=\"text/html;charset=%s\""
         info))
       charset) "\n"
-     (org-html-close-tag "meta" " name=\"generator\" content=\"Org-mode\"" 
info)
+     (let ((viewport-options
+           (cl-remove-if-not (lambda (cell) (org-string-nw-p (cadr cell)))
+                              (plist-get info :html-viewport))))
+       (and viewport-options
+           (concat
+            (org-html-close-tag
+             "meta"
+             (format "name=\"viewport\" content=\"%s\""
+                     (mapconcat
+                      (lambda (elm) (format "%s=%s" (car elm) (cadr elm)))
+                      viewport-options ", "))
+             info)
+            "\n")))
+     (format "<title>%s</title>\n" title)
+     (org-html-close-tag "meta" "name=\"generator\" content=\"Org mode\"" info)
      "\n"
      (and (org-string-nw-p author)
          (concat
           (org-html-close-tag "meta"
-                              (format " name=\"author\" content=\"%s\""
+                              (format "name=\"author\" content=\"%s\""
                                       (funcall protect-string author))
                               info)
           "\n"))
      (and (org-string-nw-p description)
          (concat
           (org-html-close-tag "meta"
-                              (format " name=\"description\" content=\"%s\"\n"
+                              (format "name=\"description\" content=\"%s\"\n"
                                       (funcall protect-string description))
                               info)
           "\n"))
      (and (org-string-nw-p keywords)
          (concat
           (org-html-close-tag "meta"
-                              (format " name=\"keywords\" content=\"%s\""
+                              (format "name=\"keywords\" content=\"%s\""
                                       (funcall protect-string keywords))
                               info)
           "\n")))))
@@ -1576,7 +1849,7 @@ INFO is a plist used as a communication channel."
     (when (and (plist-get info :html-htmlized-css-url)
               (eq org-html-htmlize-output-type 'css))
       (org-html-close-tag "link"
-                         (format " rel=\"stylesheet\" href=\"%s\" 
type=\"text/css\""
+                         (format "rel=\"stylesheet\" href=\"%s\" 
type=\"text/css\""
                                  (plist-get info :html-htmlized-css-url))
                          info))
     (when (plist-get info :html-head-include-scripts) org-html-scripts))))
@@ -1587,55 +1860,43 @@ INFO is a plist used as a communication channel."
   (when (and (memq (plist-get info :with-latex) '(mathjax t))
             (org-element-map (plist-get info :parse-tree)
                 '(latex-fragment latex-environment) 'identity info t))
-    (let ((template org-html-mathjax-template)
-         (options org-html-mathjax-options)
-         (in-buffer (or (plist-get info :html-mathjax) ""))
-         name val (yes "   ") (no "// ") x)
-      (mapc
-       (lambda (e)
-        (setq name (car e) val (nth 1 e))
-        (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer)
-            (setq val (car (read-from-string
-                            (substring in-buffer (match-end 0))))))
-        (if (not (stringp val)) (setq val (format "%s" val)))
-        (if (string-match (concat "%" (upcase (symbol-name name))) template)
-            (setq template (replace-match val t t template))))
-       options)
-      (setq val (nth 1 (assq 'mathml options)))
-      (if (string-match (concat "\\<mathml:") in-buffer)
-         (setq val (car (read-from-string
-                         (substring in-buffer (match-end 0))))))
-      ;; Exchange prefixes depending on mathml setting.
-      (if (not val) (setq x yes yes no no x))
-      ;; Replace cookies to turn on or off the config/jax lines.
-      (if (string-match ":MMLYES:" template)
-         (setq template (replace-match yes t t template)))
-      (if (string-match ":MMLNO:" template)
-         (setq template (replace-match no t t template)))
-      ;; Return the modified template.
-      (org-element-normalize-string template))))
+    (let ((template (plist-get info :html-mathjax-template))
+         (options (plist-get info :html-mathjax-options))
+         (in-buffer (or (plist-get info :html-mathjax) "")))
+      (dolist (e options (org-element-normalize-string template))
+       (let ((name (car e))
+             (val (nth 1 e)))
+         (when (string-match (concat "\\<" (symbol-name name) ":") in-buffer)
+           (setq val
+                 (car (read-from-string (substring in-buffer (match-end 0))))))
+         (unless (stringp val) (setq val (format "%s" val)))
+         (while (string-match (concat "%" (upcase (symbol-name name)))
+                              template)
+           (setq template (replace-match val t t template))))))))
 
 (defun org-html-format-spec (info)
-  "Return format specification for elements that can be
-used in the preamble or postamble."
-  `((?t . ,(org-export-data (plist-get info :title) info))
-    (?d . ,(org-export-data (org-export-get-date info) info))
-    (?T . ,(format-time-string org-html-metadata-timestamp-format))
-    (?a . ,(org-export-data (plist-get info :author) info))
-    (?e . ,(mapconcat
-           (lambda (e)
-             (format "<a href=\"mailto:%s\";>%s</a>" e e))
-           (split-string (plist-get info :email)  ",+ *")
-           ", "))
-    (?c . ,(plist-get info :creator))
-    (?C . ,(let ((file (plist-get info :input-file)))
-            (format-time-string org-html-metadata-timestamp-format
-                                (if file (nth 5 (file-attributes file))))))
-    (?v . ,(or org-html-validation-link ""))))
+  "Return format specification for preamble and postamble.
+INFO is a plist used as a communication channel."
+  (let ((timestamp-format (plist-get info :html-metadata-timestamp-format)))
+    `((?t . ,(org-export-data (plist-get info :title) info))
+      (?s . ,(org-export-data (plist-get info :subtitle) info))
+      (?d . ,(org-export-data (org-export-get-date info timestamp-format)
+                             info))
+      (?T . ,(format-time-string timestamp-format))
+      (?a . ,(org-export-data (plist-get info :author) info))
+      (?e . ,(mapconcat
+             (lambda (e) (format "<a href=\"mailto:%s\";>%s</a>" e e))
+             (split-string (plist-get info :email)  ",+ *")
+             ", "))
+      (?c . ,(plist-get info :creator))
+      (?C . ,(let ((file (plist-get info :input-file)))
+              (format-time-string timestamp-format
+                                  (and file (nth 5 (file-attributes file))))))
+      (?v . ,(or (plist-get info :html-validation-link) "")))))
 
 (defun org-html--build-pre/postamble (type info)
   "Return document preamble or postamble as a string, or nil.
-TYPE is either 'preamble or 'postamble, INFO is a plist used as a
+TYPE is either `preamble' or `postamble', INFO is a plist used as a
 communication channel."
   (let ((section (plist-get info (intern (format ":html-%s" type))))
        (spec (org-html-format-spec info)))
@@ -1649,7 +1910,6 @@ communication channel."
                       (author (cdr (assq ?a spec)))
                       (email (cdr (assq ?e spec)))
                       (creator (cdr (assq ?c spec)))
-                      (timestamp (cdr (assq ?T spec)))
                       (validation-link (cdr (assq ?v spec))))
                   (concat
                    (when (and (plist-get info :with-date)
@@ -1671,30 +1931,34 @@ communication channel."
                      (format
                       "<p class=\"date\">%s: %s</p>\n"
                       (org-html--translate "Created" info)
-                      (format-time-string org-html-metadata-timestamp-format)))
+                      (format-time-string
+                       (plist-get info :html-metadata-timestamp-format))))
                    (when (plist-get info :with-creator)
                      (format "<p class=\"creator\">%s</p>\n" creator))
                    (format "<p class=\"validation\">%s</p>\n"
                            validation-link))))
                (t (format-spec
-                   (or (cadr (assoc
+                   (or (cadr (assoc-string
                               (plist-get info :language)
                               (eval (intern
-                                     (format "org-html-%s-format" type)))))
+                                     (format "org-html-%s-format" type)))
+                              t))
                        (cadr
-                        (assoc
+                        (assoc-string
                          "en"
                          (eval
-                          (intern (format "org-html-%s-format" type))))))
+                          (intern (format "org-html-%s-format" type)))
+                         t)))
                    spec))))))
-       (when (org-string-nw-p section-contents)
-         (concat
-          (format "<%s id=\"%s\" class=\"%s\">\n"
-                  (nth 1 (assq type org-html-divs))
-                  (nth 2 (assq type org-html-divs))
-                  org-html--pre/postamble-class)
-          (org-element-normalize-string section-contents)
-          (format "</%s>\n" (nth 1 (assq type org-html-divs)))))))))
+       (let ((div (assq type (plist-get info :html-divs))))
+         (when (org-string-nw-p section-contents)
+           (concat
+            (format "<%s id=\"%s\" class=\"%s\">\n"
+                    (nth 1 div)
+                    (nth 2 div)
+                    org-html--pre/postamble-class)
+            (org-element-normalize-string section-contents)
+            (format "</%s>\n" (nth 1 div)))))))))
 
 (defun org-html-inner-template (contents info)
   "Return body of document string after HTML conversion.
@@ -1715,27 +1979,28 @@ CONTENTS is the transcoded contents string.  INFO is a 
plist
 holding export options."
   (concat
    (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info))
-     (let ((decl (or (and (stringp org-html-xml-declaration)
-                             org-html-xml-declaration)
-                        (cdr (assoc (plist-get info :html-extension)
-                                    org-html-xml-declaration))
-                        (cdr (assoc "html" org-html-xml-declaration))
-
-                        "")))
-       (when (not (or (eq nil decl) (string= "" decl)))
+     (let* ((xml-declaration (plist-get info :html-xml-declaration))
+           (decl (or (and (stringp xml-declaration) xml-declaration)
+                     (cdr (assoc (plist-get info :html-extension)
+                                 xml-declaration))
+                     (cdr (assoc "html" xml-declaration))
+                     "")))
+       (when (not (or (not decl) (string= "" decl)))
         (format "%s\n"
                 (format decl
-                 (or (and org-html-coding-system
-                          (fboundp 'coding-system-get)
-                          (coding-system-get org-html-coding-system 
'mime-charset))
-                     "iso-8859-1"))))))
+                        (or (and org-html-coding-system
+                                 (fboundp 'coding-system-get)
+                                 (coding-system-get org-html-coding-system 
'mime-charset))
+                            "iso-8859-1"))))))
    (org-html-doctype info)
    "\n"
    (concat "<html"
-          (when (org-html-xhtml-p info)
-            (format
-             " xmlns=\"http://www.w3.org/1999/xhtml\"; lang=\"%s\" 
xml:lang=\"%s\""
-             (plist-get info :language) (plist-get info :language)))
+          (cond ((org-html-xhtml-p info)
+                 (format
+                  " xmlns=\"http://www.w3.org/1999/xhtml\"; lang=\"%s\" 
xml:lang=\"%s\""
+                  (plist-get info :language) (plist-get info :language)))
+                ((org-html-html5-p info)
+                 (format " lang=\"%s\"" (plist-get info :language))))
           ">\n")
    "<head>\n"
    (org-html--build-meta-info info)
@@ -1746,21 +2011,34 @@ holding export options."
    (let ((link-up (org-trim (plist-get info :html-link-up)))
         (link-home (org-trim (plist-get info :html-link-home))))
      (unless (and (string= link-up "") (string= link-home ""))
-       (format org-html-home/up-format
+       (format (plist-get info :html-home/up-format)
               (or link-up link-home)
               (or link-home link-up))))
    ;; Preamble.
    (org-html--build-pre/postamble 'preamble info)
    ;; Document contents.
-   (format "<%s id=\"%s\">\n"
-          (nth 1 (assq 'content org-html-divs))
-          (nth 2 (assq 'content org-html-divs)))
+   (let ((div (assq 'content (plist-get info :html-divs))))
+     (format "<%s id=\"%s\">\n" (nth 1 div) (nth 2 div)))
    ;; Document title.
-   (let ((title (plist-get info :title)))
-     (format "<h1 class=\"title\">%s</h1>\n" (org-export-data (or title "") 
info)))
+   (when (plist-get info :with-title)
+     (let ((title (plist-get info :title))
+          (subtitle (plist-get info :subtitle))
+          (html5-fancy (org-html--html5-fancy-p info)))
+       (when title
+        (format
+         (if html5-fancy
+             "<header>\n<h1 class=\"title\">%s</h1>\n%s</header>"
+           "<h1 class=\"title\">%s%s</h1>\n")
+         (org-export-data title info)
+         (if subtitle
+             (format
+              (if html5-fancy
+                  "<p class=\"subtitle\">%s</p>\n"
+                "\n<br>\n<span class=\"subtitle\">%s</span>\n")
+              (org-export-data subtitle info))
+           "")))))
    contents
-   (format "</%s>\n"
-          (nth 1 (assq 'content org-html-divs)))
+   (format "</%s>\n" (nth 1 (assq 'content (plist-get info :html-divs))))
    ;; Postamble.
    (org-html--build-pre/postamble 'postamble info)
    ;; Closing document.
@@ -1773,9 +2051,9 @@ INFO is a plist used as a communication channel."
 
 ;;;; Anchor
 
-(defun org-html--anchor (&optional id desc attributes)
+(defun org-html--anchor (id desc attributes info)
   "Format a HTML anchor."
-  (let* ((name (and org-html-allow-name-attribute-in-anchors id))
+  (let* ((name (and (plist-get info :html-allow-name-attribute-in-anchors) id))
         (attributes (concat (and id (format " id=\"%s\"" id))
                             (and name (format " name=\"%s\"" name))
                             attributes)))
@@ -1783,43 +2061,38 @@ INFO is a plist used as a communication channel."
 
 ;;;; Todo
 
-(defun org-html--todo (todo)
+(defun org-html--todo (todo info)
   "Format TODO keywords into HTML."
   (when todo
     (format "<span class=\"%s %s%s\">%s</span>"
            (if (member todo org-done-keywords) "done" "todo")
-           org-html-todo-kwd-class-prefix (org-html-fix-class-name todo)
+           (or (plist-get info :html-todo-kwd-class-prefix) "")
+           (org-html-fix-class-name todo)
            todo)))
 
+;;;; Priority
+
+(defun org-html--priority (priority _info)
+  "Format a priority into HTML.
+PRIORITY is the character code of the priority or nil.  INFO is
+a plist containing export options."
+  (and priority (format "<span class=\"priority\">[%c]</span>" priority)))
+
 ;;;; Tags
 
-(defun org-html--tags (tags)
-  "Format TAGS into HTML."
+(defun org-html--tags (tags info)
+  "Format TAGS into HTML.
+INFO is a plist containing export options."
   (when tags
     (format "<span class=\"tag\">%s</span>"
            (mapconcat
             (lambda (tag)
               (format "<span class=\"%s\">%s</span>"
-                      (concat org-html-tag-class-prefix
+                      (concat (plist-get info :html-tag-class-prefix)
                               (org-html-fix-class-name tag))
                       tag))
             tags "&#xa0;"))))
 
-;;;; Headline
-
-(defun* org-html-format-headline
-  (todo todo-type priority text tags
-       &key level section-number headline-label &allow-other-keys)
-  "Format a headline in HTML."
-  (let ((section-number
-        (when section-number
-          (format "<span class=\"section-number-%d\">%s</span> "
-                  level section-number)))
-       (todo (org-html--todo todo))
-       (tags (org-html--tags tags)))
-    (concat section-number todo (and todo " ") text
-           (and tags "&#xa0;&#xa0;&#xa0;") tags)))
-
 ;;;; Src Code
 
 (defun org-html-fontify-code (code lang)
@@ -1838,6 +2111,10 @@ is the language used for CODE, as a string, or nil."
       (message "Cannot fontify src block (htmlize.el >= 1.34 required)")
       ;; Simple transcoding.
       (org-html-encode-plain-text code))
+     ;; Case 3: plain text explicitly set
+     ((not org-html-htmlize-output-type)
+      ;; Simple transcoding.
+      (org-html-encode-plain-text code))
      (t
       ;; Map language
       (setq lang (or (assoc-default lang org-src-lang-modes) lang))
@@ -1850,25 +2127,30 @@ is the language used for CODE, as a string, or nil."
         ;; Case 2: Default.  Fontify code.
         (t
          ;; htmlize
-         (setq code (with-temp-buffer
-                      ;; Switch to language-specific mode.
-                      (funcall lang-mode)
-                      (insert code)
-                      ;; Fontify buffer.
-                      (org-font-lock-ensure)
-                      ;; Remove formatting on newline characters.
-                      (save-excursion
-                        (let ((beg (point-min))
-                              (end (point-max)))
-                          (goto-char beg)
-                          (while (progn (end-of-line) (< (point) end))
-                            (put-text-property (point) (1+ (point)) 'face nil)
-                            (forward-char 1))))
-                      (org-src-mode)
-                      (set-buffer-modified-p nil)
-                      ;; Htmlize region.
-                      (org-html-htmlize-region-for-paste
-                       (point-min) (point-max))))
+         (setq code
+               (let ((output-type org-html-htmlize-output-type)
+                     (font-prefix org-html-htmlize-font-prefix))
+                 (with-temp-buffer
+                   ;; Switch to language-specific mode.
+                   (funcall lang-mode)
+                   (insert code)
+                   ;; Fontify buffer.
+                   (org-font-lock-ensure)
+                   ;; Remove formatting on newline characters.
+                   (save-excursion
+                     (let ((beg (point-min))
+                           (end (point-max)))
+                       (goto-char beg)
+                       (while (progn (end-of-line) (< (point) end))
+                         (put-text-property (point) (1+ (point)) 'face nil)
+                         (forward-char 1))))
+                   (org-src-mode)
+                   (set-buffer-modified-p nil)
+                   ;; Htmlize region.
+                   (let ((org-html-htmlize-output-type output-type)
+                         (org-html-htmlize-font-prefix font-prefix))
+                     (org-html-htmlize-region-for-paste
+                      (point-min) (point-max))))))
          ;; Strip any enclosing <pre></pre> tags.
          (let* ((beg (and (string-match "\\`<pre[^>]*>\n*" code) (match-end 
0)))
                 (end (and beg (string-match "</pre>\\'" code))))
@@ -1921,38 +2203,39 @@ a plist used as a communication channel."
         ;; Does the src block contain labels?
         (retain-labels (org-element-property :retain-labels element))
         ;; Does it have line numbers?
-        (num-start (case (org-element-property :number-lines element)
-                     (continued (org-export-get-loc element info))
-                     (new 0))))
+        (num-start (org-export-get-loc element info)))
     (org-html-do-format-code code lang refs retain-labels num-start)))
 
 
 ;;; Tables of Contents
 
-(defun org-html-toc (depth info)
+(defun org-html-toc (depth info &optional scope)
   "Build a table of contents.
-DEPTH is an integer specifying the depth of the table.  INFO is a
-plist used as a communication channel.  Return the table of
-contents as a string, or nil if it is empty."
+DEPTH is an integer specifying the depth of the table.  INFO is
+a plist used as a communication channel.  Optional argument SCOPE
+is an element defining the scope of the table.  Return the table
+of contents as a string, or nil if it is empty."
   (let ((toc-entries
         (mapcar (lambda (headline)
                   (cons (org-html--format-toc-headline headline info)
                         (org-export-get-relative-level headline info)))
-                (org-export-collect-headlines info depth)))
-       (outer-tag (if (and (org-html-html5-p info)
-                           (plist-get info :html-html5-fancy))
-                      "nav"
-                    "div")))
+                (org-export-collect-headlines info depth scope))))
     (when toc-entries
-      (concat (format "<%s id=\"table-of-contents\">\n" outer-tag)
-             (format "<h%d>%s</h%d>\n"
-                     org-html-toplevel-hlevel
-                     (org-html--translate "Table of Contents" info)
-                     org-html-toplevel-hlevel)
-             "<div id=\"text-table-of-contents\">"
-             (org-html--toc-text toc-entries)
-             "</div>\n"
-             (format "</%s>\n" outer-tag)))))
+      (let ((toc (concat "<div id=\"text-table-of-contents\">"
+                        (org-html--toc-text toc-entries)
+                        "</div>\n")))
+       (if scope toc
+         (let ((outer-tag (if (org-html--html5-fancy-p info)
+                              "nav"
+                            "div")))
+           (concat (format "<%s id=\"table-of-contents\">\n" outer-tag)
+                   (let ((top-level (plist-get info :html-toplevel-hlevel)))
+                     (format "<h%d>%s</h%d>\n"
+                             top-level
+                             (org-html--translate "Table of Contents" info)
+                             top-level))
+                   toc
+                   (format "</%s>\n" outer-tag))))))))
 
 (defun org-html--toc-text (toc-entries)
   "Return innards of a table of contents, as a string.
@@ -1967,8 +2250,7 @@ and value is its relative level, as an integer."
              (level (cdr entry)))
          (concat
           (let* ((cnt (- level prev-level))
-                 (times (if (> cnt 0) (1- cnt) (- cnt)))
-                 rtn)
+                 (times (if (> cnt 0) (1- cnt) (- cnt))))
             (setq prev-level level)
             (concat
              (org-html--make-string
@@ -2005,21 +2287,15 @@ INFO is a plist used as a communication channel."
                    (org-export-get-tags headline info))))
     (format "<a href=\"#%s\">%s</a>"
            ;; Label.
-           (org-export-solidify-link-text
-            (or (org-element-property :CUSTOM_ID headline)
-                (concat "sec-"
-                        (mapconcat #'number-to-string headline-number "-"))))
+           (or (org-element-property :CUSTOM_ID headline)
+               (org-export-get-reference headline info))
            ;; Body.
            (concat
             (and (not (org-export-low-level-p headline info))
                  (org-export-numbered-headline-p headline info)
                  (concat (mapconcat #'number-to-string headline-number ".")
                          ". "))
-            (apply (if (not (eq org-html-format-headline-function 'ignore))
-                       (lambda (todo todo-type priority text tags &rest ignore)
-                         (funcall org-html-format-headline-function
-                                  todo todo-type priority text tags))
-                     #'org-html-format-headline)
+            (apply (plist-get info :html-format-headline-function)
                    todo todo-type priority text tags :section-number nil)))))
 
 (defun org-html-list-of-listings (info)
@@ -2029,17 +2305,19 @@ of listings as a string, or nil if it is empty."
   (let ((lol-entries (org-export-collect-listings info)))
     (when lol-entries
       (concat "<div id=\"list-of-listings\">\n"
-             (format "<h%d>%s</h%d>\n"
-                     org-html-toplevel-hlevel
-                     (org-html--translate "List of Listings" info)
-                     org-html-toplevel-hlevel)
+             (let ((top-level (plist-get info :html-toplevel-hlevel)))
+               (format "<h%d>%s</h%d>\n"
+                       top-level
+                       (org-html--translate "List of Listings" info)
+                       top-level))
              "<div id=\"text-list-of-listings\">\n<ul>\n"
              (let ((count 0)
                    (initial-fmt (format "<span 
class=\"listing-number\">%s</span>"
                                         (org-html--translate "Listing %d:" 
info))))
                (mapconcat
                 (lambda (entry)
-                  (let ((label (org-element-property :name entry))
+                  (let ((label (and (org-element-property :name entry)
+                                    (org-export-get-reference entry info)))
                         (title (org-trim
                                 (org-export-data
                                  (or (org-export-get-caption entry t)
@@ -2048,10 +2326,12 @@ of listings as a string, or nil if it is empty."
                     (concat
                      "<li>"
                      (if (not label)
-                         (concat (format initial-fmt (incf count)) " " title)
+                         (concat (format initial-fmt (cl-incf count))
+                                 " "
+                                 title)
                        (format "<a href=\"#%s\">%s %s</a>"
-                               (org-export-solidify-link-text label)
-                               (format initial-fmt (incf count))
+                               label
+                               (format initial-fmt (cl-incf count))
                                title))
                      "</li>")))
                 lol-entries "\n"))
@@ -2064,17 +2344,19 @@ of tables as a string, or nil if it is empty."
   (let ((lol-entries (org-export-collect-tables info)))
     (when lol-entries
       (concat "<div id=\"list-of-tables\">\n"
-             (format "<h%d>%s</h%d>\n"
-                     org-html-toplevel-hlevel
-                     (org-html--translate "List of Tables" info)
-                     org-html-toplevel-hlevel)
+             (let ((top-level (plist-get info :html-toplevel-hlevel)))
+               (format "<h%d>%s</h%d>\n"
+                       top-level
+                       (org-html--translate "List of Tables" info)
+                       top-level))
              "<div id=\"text-list-of-tables\">\n<ul>\n"
              (let ((count 0)
                    (initial-fmt (format "<span 
class=\"table-number\">%s</span>"
                                         (org-html--translate "Table %d:" 
info))))
                (mapconcat
                 (lambda (entry)
-                  (let ((label (org-element-property :name entry))
+                  (let ((label (and (org-element-property :name entry)
+                                    (org-export-get-reference entry info)))
                         (title (org-trim
                                 (org-export-data
                                  (or (org-export-get-caption entry t)
@@ -2083,10 +2365,12 @@ of tables as a string, or nil if it is empty."
                     (concat
                      "<li>"
                      (if (not label)
-                         (concat (format initial-fmt (incf count)) " " title)
+                         (concat (format initial-fmt (cl-incf count))
+                                 " "
+                                 title)
                        (format "<a href=\"#%s\">%s %s</a>"
-                               (org-export-solidify-link-text label)
-                               (format initial-fmt (incf count))
+                               label
+                               (format initial-fmt (cl-incf count))
                                title))
                      "</li>")))
                 lol-entries "\n"))
@@ -2097,24 +2381,24 @@ of tables as a string, or nil if it is empty."
 
 ;;;; Bold
 
-(defun org-html-bold (bold contents info)
+(defun org-html-bold (_bold contents info)
   "Transcode BOLD from Org to HTML.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
-  (format (or (cdr (assq 'bold org-html-text-markup-alist)) "%s")
+  (format (or (cdr (assq 'bold (plist-get info :html-text-markup-alist))) "%s")
          contents))
 
 ;;;; Center Block
 
-(defun org-html-center-block (center-block contents info)
+(defun org-html-center-block (_center-block contents _info)
   "Transcode a CENTER-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (format "<div class=\"center\">\n%s</div>" contents))
+  (format "<div class=\"org-center\">\n%s</div>" contents))
 
 ;;;; Clock
 
-(defun org-html-clock (clock contents info)
+(defun org-html-clock (clock _contents _info)
   "Transcode a CLOCK element from Org to HTML.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -2124,19 +2408,17 @@ channel."
 </span>
 </p>"
          org-clock-string
-         (org-translate-time
-          (org-element-property :raw-value
-                                (org-element-property :value clock)))
+         (org-timestamp-translate (org-element-property :value clock))
          (let ((time (org-element-property :duration clock)))
            (and time (format " <span class=\"timestamp\">(%s)</span>" time)))))
 
 ;;;; Code
 
-(defun org-html-code (code contents info)
+(defun org-html-code (code _contents info)
   "Transcode CODE from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format (or (cdr (assq 'code org-html-text-markup-alist)) "%s")
+  (format (or (cdr (assq 'code (plist-get info :html-text-markup-alist))) "%s")
          (org-html-encode-plain-text (org-element-property :value code))))
 
 ;;;; Drawer
@@ -2145,17 +2427,13 @@ information."
   "Transcode a DRAWER element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (if (functionp org-html-format-drawer-function)
-      (funcall org-html-format-drawer-function
-              (org-element-property :drawer-name drawer)
-              contents)
-    ;; If there's no user defined function: simply
-    ;; display contents of the drawer.
-    contents))
+  (funcall (plist-get info :html-format-drawer-function)
+          (org-element-property :drawer-name drawer)
+          contents))
 
 ;;;; Dynamic Block
 
-(defun org-html-dynamic-block (dynamic-block contents info)
+(defun org-html-dynamic-block (_dynamic-block contents _info)
   "Transcode a DYNAMIC-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information.  See `org-export-data'."
@@ -2163,7 +2441,7 @@ holding contextual information.  See `org-export-data'."
 
 ;;;; Entity
 
-(defun org-html-entity (entity contents info)
+(defun org-html-entity (entity _contents _info)
   "Transcode an ENTITY object from Org to HTML.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
@@ -2171,18 +2449,25 @@ contextual information."
 
 ;;;; Example Block
 
-(defun org-html-example-block (example-block contents info)
+(defun org-html-example-block (example-block _contents info)
   "Transcode a EXAMPLE-BLOCK element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (if (org-export-read-attribute :attr_html example-block :textarea)
-      (org-html--textarea-block example-block)
-    (format "<pre class=\"example\">\n%s</pre>"
-           (org-html-format-code example-block info))))
+  (let ((attributes (org-export-read-attribute :attr_html example-block)))
+    (if (plist-get attributes :textarea)
+       (org-html--textarea-block example-block)
+      (format "<pre class=\"example\"%s>\n%s</pre>"
+             (let* ((name (org-element-property :name example-block))
+                    (a (org-html--make-attribute-string
+                        (if (or (not name) (plist-member attributes :id))
+                            attributes
+                          (plist-put attributes :id name)))))
+               (if (org-string-nw-p a) (concat " " a) ""))
+             (org-html-format-code example-block info)))))
 
 ;;;; Export Snippet
 
-(defun org-html-export-snippet (export-snippet contents info)
+(defun org-html-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
@@ -2191,7 +2476,7 @@ information."
 
 ;;;; Export Block
 
-(defun org-html-export-block (export-block contents info)
+(defun org-html-export-block (export-block _contents _info)
   "Transcode a EXPORT-BLOCK element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (string= (org-element-property :type export-block) "HTML")
@@ -2199,7 +2484,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Fixed Width
 
-(defun org-html-fixed-width (fixed-width contents info)
+(defun org-html-fixed-width (fixed-width _contents _info)
   "Transcode a FIXED-WIDTH element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (format "<pre class=\"example\">\n%s</pre>"
@@ -2209,135 +2494,116 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Footnote Reference
 
-(defun org-html-footnote-reference (footnote-reference contents info)
+(defun org-html-footnote-reference (footnote-reference _contents info)
   "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (concat
    ;; Insert separator between two footnotes in a row.
    (let ((prev (org-export-get-previous-element footnote-reference info)))
      (when (eq (org-element-type prev) 'footnote-reference)
-       org-html-footnote-separator))
-   (cond
-    ((not (org-export-footnote-first-reference-p footnote-reference info))
-     (org-html-format-footnote-reference
-      (org-export-get-footnote-number footnote-reference info)
-      "IGNORED" 100))
-    ;; Inline definitions are secondary strings.
-    ((eq (org-element-property :type footnote-reference) 'inline)
-     (org-html-format-footnote-reference
-      (org-export-get-footnote-number footnote-reference info)
-      "IGNORED" 1))
-    ;; Non-inline footnotes definitions are full Org data.
-    (t (org-html-format-footnote-reference
-       (org-export-get-footnote-number footnote-reference info)
-       "IGNORED" 1)))))
+       (plist-get info :html-footnote-separator)))
+   (let* ((n (org-export-get-footnote-number footnote-reference info))
+         (id (format "fnr.%d%s"
+                     n
+                     (if (org-export-footnote-first-reference-p
+                          footnote-reference info)
+                         ""
+                       ".100"))))
+     (format
+      (plist-get info :html-footnote-format)
+      (org-html--anchor
+       id n (format " class=\"footref\" href=\"#fn.%d\"" n) info)))))
 
 ;;;; Headline
 
-(defun org-html-format-headline--wrap
-  (headline info &optional format-function &rest extra-keys)
-  "Transcode a HEADLINE element from Org to HTML.
-CONTENTS holds the contents of the headline.  INFO is a plist
-holding contextual information."
-  (let* ((level (+ (org-export-get-relative-level headline info)
-                  (1- org-html-toplevel-hlevel)))
-        (headline-number (org-export-get-headline-number headline info))
-        (section-number (and (not (org-export-low-level-p headline info))
-                             (org-export-numbered-headline-p headline info)
-                             (mapconcat 'number-to-string
-                                        headline-number ".")))
-        (todo (and (plist-get info :with-todo-keywords)
-                   (let ((todo (org-element-property :todo-keyword headline)))
-                     (and todo (org-export-data todo info)))))
-        (todo-type (and todo (org-element-property :todo-type headline)))
-        (priority (and (plist-get info :with-priority)
-                       (org-element-property :priority headline)))
-        (text (org-export-data (org-element-property :title headline) info))
-        (tags (and (plist-get info :with-tags)
-                   (org-export-get-tags headline info)))
-        (headline-label (or (org-element-property :CUSTOM_ID headline)
-                            (concat "sec-" (mapconcat 'number-to-string
-                                                      headline-number "-"))))
-        (format-function
-         (cond ((functionp format-function) format-function)
-               ((not (eq org-html-format-headline-function 'ignore))
-                (lambda (todo todo-type priority text tags &rest ignore)
-                  (funcall org-html-format-headline-function
-                           todo todo-type priority text tags)))
-               (t 'org-html-format-headline))))
-    (apply format-function
-          todo todo-type  priority text tags
-          :headline-label headline-label :level level
-          :section-number section-number extra-keys)))
-
 (defun org-html-headline (headline contents info)
   "Transcode a HEADLINE element from Org to HTML.
 CONTENTS holds the contents of the headline.  INFO is a plist
 holding contextual information."
   (unless (org-element-property :footnote-section-p headline)
-    (let* ((contents (or contents ""))
-          (numberedp (org-export-numbered-headline-p headline info))
-          (level (org-export-get-relative-level headline info))
-          (text (org-export-data (org-element-property :title headline) info))
-          (todo (and (plist-get info :with-todo-keywords)
-                     (let ((todo (org-element-property :todo-keyword 
headline)))
-                       (and todo (org-export-data todo info)))))
-          (todo-type (and todo (org-element-property :todo-type headline)))
-          (tags (and (plist-get info :with-tags)
-                     (org-export-get-tags headline info)))
-          (priority (and (plist-get info :with-priority)
-                         (org-element-property :priority headline)))
-          (section-number (mapconcat #'number-to-string
-                                     (org-export-get-headline-number
-                                      headline info) "-"))
-          (ids (delq 'nil
-                     (list (org-element-property :CUSTOM_ID headline)
-                           (concat "sec-" section-number)
-                           (org-element-property :ID headline))))
-          (preferred-id (car ids))
-          (extra-ids (mapconcat
-                      (lambda (id)
-                        (org-html--anchor
-                         (org-export-solidify-link-text
-                          (if (org-uuidgen-p id) (concat "ID-" id) id))))
-                      (cdr ids) ""))
-          ;; Create the headline text.
-          (full-text (org-html-format-headline--wrap headline info)))
+    (let* ((numberedp (org-export-numbered-headline-p headline info))
+           (numbers (org-export-get-headline-number headline info))
+           (level (+ (org-export-get-relative-level headline info)
+                     (1- (plist-get info :html-toplevel-hlevel))))
+           (todo (and (plist-get info :with-todo-keywords)
+                      (let ((todo (org-element-property :todo-keyword 
headline)))
+                        (and todo (org-export-data todo info)))))
+           (todo-type (and todo (org-element-property :todo-type headline)))
+           (priority (and (plist-get info :with-priority)
+                          (org-element-property :priority headline)))
+           (text (org-export-data (org-element-property :title headline) info))
+           (tags (and (plist-get info :with-tags)
+                      (org-export-get-tags headline info)))
+           (full-text (funcall (plist-get info :html-format-headline-function)
+                               todo todo-type priority text tags info))
+           (contents (or contents ""))
+          (ids (delq nil
+                      (list (org-element-property :CUSTOM_ID headline)
+                            (org-export-get-reference headline info)
+                            (org-element-property :ID headline))))
+           (preferred-id (car ids))
+           (extra-ids
+           (mapconcat
+            (lambda (id)
+              (org-html--anchor
+               (if (org-uuidgen-p id) (concat "ID-" id) id)
+               nil nil info))
+            (cdr ids) "")))
       (if (org-export-low-level-p headline info)
-         ;; This is a deep sub-tree: export it as a list item.
-         (let* ((type (if numberedp 'ordered 'unordered))
-                (itemized-body
-                 (org-html-format-list-item
-                  contents type nil info nil
-                  (concat (org-html--anchor preferred-id) extra-ids
-                          full-text))))
-           (concat
-            (and (org-export-first-sibling-p headline info)
-                 (org-html-begin-plain-list type))
-            itemized-body
-            (and (org-export-last-sibling-p headline info)
-                 (org-html-end-plain-list type))))
-       ;; Standard headline.  Export it as a section.
-       (let ((extra-class (org-element-property :HTML_CONTAINER_CLASS 
headline))
-             (level1 (+ level (1- org-html-toplevel-hlevel)))
-             (first-content (car (org-element-contents headline))))
-         (format "<%s id=\"%s\" class=\"%s\">%s%s</%s>\n"
-                 (org-html--container headline info)
-                 (format "outline-container-%s"
-                         (or (org-element-property :CUSTOM_ID headline)
-                             (concat "sec-" section-number)))
-                 (concat (format "outline-%d" level1) (and extra-class " ")
-                         extra-class)
-                 (format "\n<h%d id=\"%s\">%s%s</h%d>\n"
-                         level1 preferred-id extra-ids full-text level1)
-                 ;; When there is no section, pretend there is an
-                 ;; empty one to get the correct <div class="outline-
-                 ;; ...> which is needed by `org-info.js'.
-                 (if (not (eq (org-element-type first-content) 'section))
-                     (concat (org-html-section first-content "" info)
-                             contents)
-                   contents)
-                 (org-html--container headline info)))))))
+          ;; This is a deep sub-tree: export it as a list item.
+          (let* ((type (if numberedp 'ordered 'unordered))
+                 (itemized-body
+                  (org-html-format-list-item
+                   contents type nil info nil
+                   (concat (org-html--anchor preferred-id nil nil info)
+                           extra-ids
+                           full-text))))
+            (concat (and (org-export-first-sibling-p headline info)
+                         (org-html-begin-plain-list type))
+                    itemized-body
+                    (and (org-export-last-sibling-p headline info)
+                         (org-html-end-plain-list type))))
+        (let ((extra-class (org-element-property :HTML_CONTAINER_CLASS 
headline))
+              (first-content (car (org-element-contents headline))))
+          ;; Standard headline.  Export it as a section.
+          (format "<%s id=\"%s\" class=\"%s\">%s%s</%s>\n"
+                  (org-html--container headline info)
+                  (concat "outline-container-"
+                         (org-export-get-reference headline info))
+                  (concat (format "outline-%d" level)
+                          (and extra-class " ")
+                          extra-class)
+                  (format "\n<h%d id=\"%s\">%s%s</h%d>\n"
+                          level
+                          preferred-id
+                          extra-ids
+                          (concat
+                           (and numberedp
+                                (format
+                                 "<span class=\"section-number-%d\">%s</span> "
+                                 level
+                                 (mapconcat #'number-to-string numbers ".")))
+                           full-text)
+                          level)
+                  ;; When there is no section, pretend there is an
+                  ;; empty one to get the correct <div
+                  ;; class="outline-...> which is needed by
+                  ;; `org-info.js'.
+                  (if (eq (org-element-type first-content) 'section) contents
+                    (concat (org-html-section first-content "" info) contents))
+                  (org-html--container headline info)))))))
+
+(defun org-html-format-headline-default-function
+    (todo _todo-type priority text tags info)
+  "Default format function for a headline.
+See `org-html-format-headline-function' for details."
+  (let ((todo (org-html--todo todo info))
+       (priority (org-html--priority priority info))
+       (tags (org-html--tags tags info)))
+    (concat todo (and todo " ")
+           priority (and priority " ")
+           text
+           (and tags "&#xa0;&#xa0;&#xa0;") tags)))
 
 (defun org-html--container (headline info)
   (or (org-element-property :HTML_CONTAINER headline)
@@ -2347,100 +2613,112 @@ holding contextual information."
 
 ;;;; Horizontal Rule
 
-(defun org-html-horizontal-rule (horizontal-rule contents info)
+(defun org-html-horizontal-rule (_horizontal-rule _contents info)
   "Transcode an HORIZONTAL-RULE  object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-html-close-tag "hr" nil info))
 
 ;;;; Inline Src Block
 
-(defun org-html-inline-src-block (inline-src-block contents info)
+(defun org-html-inline-src-block (inline-src-block _contents info)
   "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let* ((org-lang (org-element-property :language inline-src-block))
-        (code (org-element-property :value inline-src-block)))
-    (error "Cannot export inline src block")))
+  (let* ((lang (org-element-property :language inline-src-block))
+        (code (org-html-fontify-code
+               (org-element-property :value inline-src-block)
+               lang))
+        (label
+         (let ((lbl (and (org-element-property :name inline-src-block)
+                         (org-export-get-reference inline-src-block info))))
+           (if (not lbl) "" (format " id=\"%s\"" lbl)))))
+    (format "<code class=\"src src-%s\"%s>%s</code>" lang label code)))
 
 ;;;; Inlinetask
 
-(defun org-html-format-section (text class &optional id)
-  "Format a section with TEXT into a HTML div with CLASS and ID."
-  (let ((extra (concat (when id (format " id=\"%s\"" id)))))
-    (concat (format "<div class=\"%s\"%s>\n" class extra) text "</div>\n")))
-
 (defun org-html-inlinetask (inlinetask contents info)
   "Transcode an INLINETASK element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (cond
-   ;; If `org-html-format-inlinetask-function' is not 'ignore, call it
-   ;; with appropriate arguments.
-   ((not (eq org-html-format-inlinetask-function 'ignore))
-    (let ((format-function
-          (function*
-           (lambda (todo todo-type priority text tags
-                    &key contents &allow-other-keys)
-             (funcall org-html-format-inlinetask-function
-                      todo todo-type priority text tags contents)))))
-      (org-html-format-headline--wrap
-       inlinetask info format-function :contents contents)))
-   ;; Otherwise, use a default template.
-   (t (format "<div class=\"inlinetask\">\n<b>%s</b>%s\n%s</div>"
-             (org-html-format-headline--wrap inlinetask info)
-             (org-html-close-tag "br" nil info)
-             contents))))
+  (let* ((todo (and (plist-get info :with-todo-keywords)
+                   (let ((todo (org-element-property :todo-keyword 
inlinetask)))
+                     (and todo (org-export-data todo info)))))
+        (todo-type (and todo (org-element-property :todo-type inlinetask)))
+        (priority (and (plist-get info :with-priority)
+                       (org-element-property :priority inlinetask)))
+        (text (org-export-data (org-element-property :title inlinetask) info))
+        (tags (and (plist-get info :with-tags)
+                   (org-export-get-tags inlinetask info))))
+    (funcall (plist-get info :html-format-inlinetask-function)
+            todo todo-type priority text tags contents info)))
+
+(defun org-html-format-inlinetask-default-function
+  (todo todo-type priority text tags contents info)
+  "Default format function for a inlinetasks.
+See `org-html-format-inlinetask-function' for details."
+  (format "<div class=\"inlinetask\">\n<b>%s</b>%s\n%s</div>"
+         (org-html-format-headline-default-function
+          todo todo-type priority text tags info)
+         (org-html-close-tag "br" nil info)
+         contents))
 
 ;;;; Italic
 
-(defun org-html-italic (italic contents info)
+(defun org-html-italic (_italic contents info)
   "Transcode ITALIC from Org to HTML.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
-  (format (or (cdr (assq 'italic org-html-text-markup-alist)) "%s") contents))
+  (format
+   (or (cdr (assq 'italic (plist-get info :html-text-markup-alist))) "%s")
+   contents))
 
 ;;;; Item
 
-(defun org-html-checkbox (checkbox)
-  "Format CHECKBOX into HTML."
-  (case checkbox (on "<code>[X]</code>")
-       (off "<code>[&#xa0;]</code>")
-       (trans "<code>[-]</code>")
-       (t "")))
+(defun org-html-checkbox (checkbox info)
+  "Format CHECKBOX into HTML.
+INFO is a plist holding contextual information.  See
+`org-html-checkbox-type' for customization options."
+  (cdr (assq checkbox
+            (cdr (assq (plist-get info :html-checkbox-type)
+                       org-html-checkbox-types)))))
 
 (defun org-html-format-list-item (contents type checkbox info
-                                            &optional term-counter-id
-                                            headline)
+                                          &optional term-counter-id
+                                          headline)
   "Format a list item into HTML."
-  (let ((checkbox (concat (org-html-checkbox checkbox) (and checkbox " ")))
+  (let ((class (if checkbox
+                  (format " class=\"%s\""
+                          (symbol-name checkbox)) ""))
+       (checkbox (concat (org-html-checkbox checkbox info)
+                         (and checkbox " ")))
        (br (org-html-close-tag "br" nil info)))
     (concat
-     (case type
-       (ordered
+     (pcase type
+       (`ordered
        (let* ((counter term-counter-id)
               (extra (if counter (format " value=\"%s\"" counter) "")))
          (concat
-          (format "<li%s>" extra)
+          (format "<li%s%s>" class extra)
           (when headline (concat headline br)))))
-       (unordered
+       (`unordered
        (let* ((id term-counter-id)
               (extra (if id (format " id=\"%s\"" id) "")))
          (concat
-          (format "<li%s>" extra)
+          (format "<li%s%s>" class extra)
           (when headline (concat headline br)))))
-       (descriptive
+       (`descriptive
        (let* ((term term-counter-id))
          (setq term (or term "(no term)"))
          ;; Check-boxes in descriptive lists are associated to tag.
-         (concat (format "<dt> %s </dt>"
-                         (concat checkbox term))
+         (concat (format "<dt%s>%s</dt>"
+                         class (concat checkbox term))
                  "<dd>"))))
      (unless (eq type 'descriptive) checkbox)
-     contents
-     (case type
-       (ordered "</li>")
-       (unordered "</li>")
-       (descriptive "</dd>")))))
+     (and contents (org-trim contents))
+     (pcase type
+       (`ordered "</li>")
+       (`unordered "</li>")
+       (`descriptive "</dd>")))))
 
 (defun org-html-item (item contents info)
   "Transcode an ITEM element from Org to HTML.
@@ -2457,7 +2735,7 @@ contextual information."
 
 ;;;; Keyword
 
-(defun org-html-keyword (keyword contents info)
+(defun org-html-keyword (keyword _contents info)
   "Transcode a KEYWORD element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((key (org-element-property :key keyword))
@@ -2465,13 +2743,13 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
     (cond
      ((string= key "HTML") value)
      ((string= key "TOC")
-      (let ((value (downcase value)))
+      (let ((case-fold-search t))
        (cond
         ((string-match "\\<headlines\\>" value)
-         (let ((depth (or (and (string-match "[0-9]+" value)
-                               (string-to-number (match-string 0 value)))
-                          (plist-get info :with-toc))))
-           (org-html-toc depth info)))
+         (let ((depth (and (string-match "\\<[0-9]+\\>" value)
+                           (string-to-number (match-string 0 value))))
+               (localp (string-match-p "\\<local\\>" value)))
+           (org-html-toc depth info (and localp keyword))))
         ((string= "listings" value) (org-html-list-of-listings info))
         ((string= "tables" value) (org-html-list-of-tables info))))))))
 
@@ -2479,10 +2757,11 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 (defun org-html-format-latex (latex-frag processing-type info)
   "Format a LaTeX fragment LATEX-FRAG into HTML.
-PROCESSING-TYPE designates the tool used for conversion.  It is
-a symbol among `mathjax', `dvipng', `imagemagick', `verbatim' nil
-and t.  See `org-html-with-latex' for more information.  INFO is
-a plist containing export properties."
+PROCESSING-TYPE designates the tool used for conversion.  It can
+be `mathjax', `verbatim', nil, t or symbols in
+`org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or
+`imagemagick'.  See `org-html-with-latex' for more information.
+INFO is a plist containing export properties."
   (let ((cache-relpath "") (cache-dir ""))
     (unless (eq processing-type 'mathjax)
       (let ((bfn (or (buffer-file-name)
@@ -2497,7 +2776,7 @@ a plist containing export properties."
                             "\n")
                            "\n")))))
        (setq cache-relpath
-             (concat "ltxpng/"
+             (concat (file-name-as-directory org-preview-latex-image-directory)
                      (file-name-sans-extension
                       (file-name-nondirectory bfn)))
              cache-dir (file-name-directory bfn))
@@ -2507,51 +2786,51 @@ a plist containing export properties."
        (setq latex-frag (concat latex-header latex-frag))))
     (with-temp-buffer
       (insert latex-frag)
-      (org-format-latex cache-relpath cache-dir nil "Creating LaTeX Image..."
-                       nil nil processing-type)
+      (org-format-latex cache-relpath nil nil cache-dir nil
+                       "Creating LaTeX Image..." nil processing-type)
       (buffer-string))))
 
-(defun org-html-latex-environment (latex-environment contents info)
+(defun org-html-latex-environment (latex-environment _contents info)
   "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((processing-type (plist-get info :with-latex))
        (latex-frag (org-remove-indentation
                     (org-element-property :value latex-environment)))
        (attributes (org-export-read-attribute :attr_html latex-environment)))
-    (case processing-type
-      ((t mathjax)
-       (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
-       (let ((formula-link
-             (org-html-format-latex latex-frag processing-type info)))
-        (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
-          ;; Do not provide a caption or a name to be consistent with
-          ;; `mathjax' handling.
-          (org-html--wrap-image
-           (org-html--format-image
-            (match-string 1 formula-link) attributes info) info))))
-      (t latex-frag))))
+    (cond
+     ((memq processing-type '(t mathjax))
+      (org-html-format-latex latex-frag 'mathjax info))
+     ((assq processing-type org-preview-latex-process-alist)
+      (let ((formula-link
+            (org-html-format-latex latex-frag processing-type info)))
+       (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+         ;; Do not provide a caption or a name to be consistent with
+         ;; `mathjax' handling.
+         (org-html--wrap-image
+          (org-html--format-image
+           (match-string 1 formula-link) attributes info) info))))
+     (t latex-frag))))
 
 ;;;; Latex Fragment
 
-(defun org-html-latex-fragment (latex-fragment contents info)
+(defun org-html-latex-fragment (latex-fragment _contents info)
   "Transcode a LATEX-FRAGMENT object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((latex-frag (org-element-property :value latex-fragment))
        (processing-type (plist-get info :with-latex)))
-    (case processing-type
-      ((t mathjax)
-       (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
-       (let ((formula-link
-             (org-html-format-latex latex-frag processing-type info)))
-        (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
-          (org-html--format-image (match-string 1 formula-link) nil info))))
-      (t latex-frag))))
+    (cond
+     ((memq processing-type '(t mathjax))
+      (org-html-format-latex latex-frag 'mathjax info))
+     ((assq processing-type org-preview-latex-process-alist)
+      (let ((formula-link
+            (org-html-format-latex latex-frag processing-type info)))
+       (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+         (org-html--format-image (match-string 1 formula-link) nil info))))
+     (t latex-frag))))
 
 ;;;; Line Break
 
-(defun org-html-line-break (line-break contents info)
+(defun org-html-line-break (_line-break _contents info)
   "Transcode a LINE-BREAK object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (concat (org-html-close-tag "br" nil info) "\n"))
@@ -2565,19 +2844,20 @@ inline image when it has no description and targets an 
image
 file (see `org-html-inline-image-rules' for more information), or
 if its description is a single link targeting an image file."
   (if (not (org-element-contents link))
-      (org-export-inline-image-p link org-html-inline-image-rules)
+      (org-export-inline-image-p
+       link (plist-get info :html-inline-image-rules))
     (not
      (let ((link-count 0))
        (org-element-map (org-element-contents link)
           (cons 'plain-text org-element-all-objects)
         (lambda (obj)
-          (case (org-element-type obj)
-            (plain-text (org-string-nw-p obj))
-            (link (if (= link-count 1) t
-                    (incf link-count)
-                    (not (org-export-inline-image-p
-                          obj org-html-inline-image-rules))))
-            (otherwise t)))
+          (pcase (org-element-type obj)
+            (`plain-text (org-string-nw-p obj))
+            (`link (if (= link-count 1) t
+                     (cl-incf link-count)
+                     (not (org-export-inline-image-p
+                           obj (plist-get info :html-inline-image-rules)))))
+            (_ t)))
          info t)))))
 
 (defvar org-html-standalone-image-predicate)
@@ -2599,9 +2879,9 @@ further.  For example, to check for only captioned 
standalone
 images, set it to:
 
   (lambda (paragraph) (org-element-property :caption paragraph))"
-  (let ((paragraph (case (org-element-type element)
-                    (paragraph element)
-                    (link (org-export-get-parent element)))))
+  (let ((paragraph (pcase (org-element-type element)
+                    (`paragraph element)
+                    (`link (org-export-get-parent element)))))
     (and (eq (org-element-type paragraph) 'paragraph)
         (or (not (fboundp 'org-html-standalone-image-predicate))
             (funcall org-html-standalone-image-predicate paragraph))
@@ -2609,19 +2889,18 @@ images, set it to:
           (let ((link-count 0))
             (org-element-map (org-element-contents paragraph)
                 (cons 'plain-text org-element-all-objects)
-              #'(lambda (obj)
-                  (when (case (org-element-type obj)
-                          (plain-text (org-string-nw-p obj))
-                          (link (or (> (incf link-count) 1)
-                                    (not (org-html-inline-image-p obj info))))
-                          (otherwise t))
-                    (throw 'exit nil)))
+              (lambda (obj)
+                (when (pcase (org-element-type obj)
+                        (`plain-text (org-string-nw-p obj))
+                        (`link (or (> (cl-incf link-count) 1)
+                                   (not (org-html-inline-image-p obj info))))
+                        (_ t))
+                  (throw 'exit nil)))
               info nil 'link)
             (= link-count 1))))))
 
 (defun org-html-link (link desc info)
   "Transcode a LINK object from Org to HTML.
-
 DESC is the description part of the link, or the empty string.
 INFO is a plist holding contextual information.  See
 `org-export-data'."
@@ -2629,56 +2908,49 @@ INFO is a plist holding contextual information.  See
                 (org-trim (plist-get info :html-link-home))))
         (use-abs-url (plist-get info :html-link-use-abs-url))
         (link-org-files-as-html-maybe
-         (function
-          (lambda (raw-path info)
-            "Treat links to `file.org' as links to `file.html', if needed.
-           See `org-html-link-org-files-as-html'."
-            (cond
-             ((and org-html-link-org-files-as-html
-                   (string= ".org"
-                            (downcase (file-name-extension raw-path "."))))
-              (concat (file-name-sans-extension raw-path) "."
-                      (plist-get info :html-extension)))
-             (t raw-path)))))
+         (lambda (raw-path info)
+           ;; Treat links to `file.org' as links to `file.html', if
+           ;; needed.  See `org-html-link-org-files-as-html'.
+           (cond
+            ((and (plist-get info :html-link-org-files-as-html)
+                  (string= ".org"
+                           (downcase (file-name-extension raw-path "."))))
+             (concat (file-name-sans-extension raw-path) "."
+                     (plist-get info :html-extension)))
+            (t raw-path))))
         (type (org-element-property :type link))
         (raw-path (org-element-property :path link))
         ;; Ensure DESC really exists, or set it to nil.
         (desc (org-string-nw-p desc))
         (path
          (cond
-          ((member type '("http" "https" "ftp" "mailto"))
-           (org-link-escape
-            (org-link-unescape
-             (concat type ":" raw-path)) org-link-escape-chars-browser))
+          ((member type '("http" "https" "ftp" "mailto" "news"))
+           (url-encode-url (org-link-unescape (concat type ":" raw-path))))
           ((string= type "file")
            ;; Treat links to ".org" files as ".html", if needed.
            (setq raw-path
                  (funcall link-org-files-as-html-maybe raw-path info))
            ;; If file path is absolute, prepend it with protocol
-           ;; component - "file:".
+           ;; component - "file://".
            (cond
             ((file-name-absolute-p raw-path)
-             (setq raw-path (concat "file:" raw-path)))
+             (setq raw-path (org-export-file-uri raw-path)))
             ((and home use-abs-url)
              (setq raw-path (concat (file-name-as-directory home) raw-path))))
            ;; Add search option, if any.  A search option can be
-           ;; relative to a custom-id or a headline title.  Any other
-           ;; option is ignored.
+           ;; relative to a custom-id, a headline title, a name or
+           ;; a target.
            (let ((option (org-element-property :search-option link)))
              (cond ((not option) raw-path)
-                   ((eq (aref option 0) ?#) (concat raw-path option))
-                   ;; External fuzzy link: try to resolve it if path
-                   ;; belongs to current project, if any.
-                   ((eq (aref option 0) ?*)
-                    (concat
-                     raw-path
-                     (let ((numbers
-                            (org-publish-resolve-external-fuzzy-link
-                             (org-element-property :path link) option)))
-                       (and numbers (concat "#sec-"
-                                            (mapconcat 'number-to-string
-                                                       numbers "-"))))))
-                   (t raw-path))))
+                   ;; Since HTML back-end use custom-id value as-is,
+                   ;; resolving is them is trivial.
+                   ((eq (string-to-char option) ?#) (concat raw-path option))
+                   (t
+                    (concat raw-path
+                            "#"
+                            (org-publish-resolve-external-link
+                             option
+                             (org-element-property :path link)))))))
           (t raw-path)))
         ;; Extract attributes from parent's paragraph.  HACK: Only do
         ;; this for the first link in parent (inner image link for
@@ -2695,12 +2967,14 @@ INFO is a plist holding contextual information.  See
                 (org-export-read-attribute :attr_html parent))))
         (attributes
          (let ((attr (org-html--make-attribute-string attributes-plist)))
-           (if (org-string-nw-p attr) (concat " " attr) "")))
-        protocol)
+           (if (org-string-nw-p attr) (concat " " attr) ""))))
     (cond
+     ;; Link type is handled by a special function.
+     ((org-export-custom-protocol-maybe link desc 'html))
      ;; Image file.
-     ((and org-html-inline-images
-          (org-export-inline-image-p link org-html-inline-image-rules))
+     ((and (plist-get info :html-inline-images)
+          (org-export-inline-image-p
+           link (plist-get info :html-inline-image-rules)))
       (org-html--format-image path attributes-plist info))
      ;; Radio target: Transcode target's contents and use them as
      ;; link's description.
@@ -2708,18 +2982,18 @@ INFO is a plist holding contextual information.  See
       (let ((destination (org-export-resolve-radio-link link info)))
        (if (not destination) desc
          (format "<a href=\"#%s\"%s>%s</a>"
-                 (org-export-solidify-link-text
-                  (org-element-property :value destination))
-                 attributes desc))))
+                 (org-export-get-reference destination info)
+                 attributes
+                 desc))))
      ;; Links pointing to a headline: Find destination and build
      ;; appropriate referencing command.
      ((member type '("custom-id" "fuzzy" "id"))
       (let ((destination (if (string= type "fuzzy")
                             (org-export-resolve-fuzzy-link link info)
                           (org-export-resolve-id-link link info))))
-       (case (org-element-type destination)
+       (pcase (org-element-type destination)
          ;; ID link points to an external file.
-         (plain-text
+         (`plain-text
           (let ((fragment (concat "ID-" path))
                 ;; Treat links to ".org" files as ".html", if needed.
                 (path (funcall link-org-files-as-html-maybe
@@ -2727,86 +3001,87 @@ INFO is a plist holding contextual information.  See
             (format "<a href=\"%s#%s\"%s>%s</a>"
                     path fragment attributes (or desc destination))))
          ;; Fuzzy link points nowhere.
-         ((nil)
+         (`nil
           (format "<i>%s</i>"
                   (or desc
                       (org-export-data
                        (org-element-property :raw-link link) info))))
          ;; Link points to a headline.
-         (headline
-          (let ((href
-                 ;; What href to use?
-                 (cond
-                  ;; Case 1: Headline is linked via it's CUSTOM_ID
-                  ;; property.  Use CUSTOM_ID.
-                  ((string= type "custom-id")
-                   (org-element-property :CUSTOM_ID destination))
-                  ;; Case 2: Headline is linked via it's ID property
-                  ;; or through other means.  Use the default href.
-                  ((member type '("id" "fuzzy"))
-                   (format "sec-%s"
-                           (mapconcat 'number-to-string
-                                      (org-export-get-headline-number
-                                       destination info) "-")))
-                  (t (error "Shouldn't reach here"))))
+         (`headline
+          (let ((href (or (org-element-property :CUSTOM_ID destination)
+                          (org-export-get-reference destination info)))
                 ;; What description to use?
                 (desc
                  ;; Case 1: Headline is numbered and LINK has no
                  ;; description.  Display section number.
                  (if (and (org-export-numbered-headline-p destination info)
                           (not desc))
-                     (mapconcat 'number-to-string
+                     (mapconcat #'number-to-string
                                 (org-export-get-headline-number
                                  destination info) ".")
                    ;; Case 2: Either the headline is un-numbered or
                    ;; LINK has a custom description.  Display LINK's
                    ;; description or headline's title.
-                   (or desc (org-export-data (org-element-property
-                                              :title destination) info)))))
-            (format "<a href=\"#%s\"%s>%s</a>"
-                    (org-export-solidify-link-text href) attributes desc)))
+                   (or desc
+                       (org-export-data
+                        (org-element-property :title destination) info)))))
+            (format "<a href=\"#%s\"%s>%s</a>" href attributes desc)))
          ;; Fuzzy link points to a target or an element.
-         (t
-          (let* ((path (org-export-solidify-link-text path))
-                 (org-html-standalone-image-predicate 'org-html--has-caption-p)
+         (_
+          (let* ((ref (org-export-get-reference destination info))
+                 (org-html-standalone-image-predicate
+                  #'org-html--has-caption-p)
                  (number (cond
                           (desc nil)
                           ((org-html-standalone-image-p destination info)
                            (org-export-get-ordinal
                             (org-element-map destination 'link
-                              'identity info t)
+                              #'identity info t)
                             info 'link 'org-html-standalone-image-p))
                           (t (org-export-get-ordinal
                               destination info nil 'org-html--has-caption-p))))
                  (desc (cond (desc)
                              ((not number) "No description for this link")
                              ((numberp number) (number-to-string number))
-                             (t (mapconcat 'number-to-string number ".")))))
-            (format "<a href=\"#%s\"%s>%s</a>" path attributes desc))))))
+                             (t (mapconcat #'number-to-string number ".")))))
+            (format "<a href=\"#%s\"%s>%s</a>" ref attributes desc))))))
      ;; Coderef: replace link with the reference name or the
      ;; equivalent line number.
      ((string= type "coderef")
-      (let ((fragment (concat "coderef-" path)))
-       (format "<a href=\"#%s\"%s%s>%s</a>"
+      (let ((fragment (concat "coderef-" (org-html-encode-plain-text path))))
+       (format "<a href=\"#%s\" %s%s>%s</a>"
                fragment
-               (org-trim
-                (format (concat "class=\"coderef\""
-                                " onmouseover=\"CodeHighlightOn(this, '%s');\""
-                                " onmouseout=\"CodeHighlightOff(this, 
'%s');\"")
-                        fragment fragment))
+               (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \
+'%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
+                       fragment fragment)
                attributes
                (format (org-export-get-coderef-format path desc)
                        (org-export-resolve-coderef path info)))))
-     ;; Link type is handled by a special function.
-     ((functionp (setq protocol (nth 2 (assoc type org-link-protocols))))
-      (funcall protocol (org-link-unescape path) desc 'html))
      ;; External link with a description part.
-     ((and path desc) (format "<a href=\"%s\"%s>%s</a>" path attributes desc))
+     ((and path desc) (format "<a href=\"%s\"%s>%s</a>"
+                             (org-html-encode-plain-text path)
+                             attributes
+                             desc))
      ;; External link without a description part.
-     (path (format "<a href=\"%s\"%s>%s</a>" path attributes path))
+     (path (let ((path (org-html-encode-plain-text path)))
+            (format "<a href=\"%s\"%s>%s</a>"
+                    path
+                    attributes
+                    (org-link-unescape path))))
      ;; No path, only description.  Try to do something useful.
      (t (format "<i>%s</i>" desc)))))
 
+;;;; Node Property
+
+(defun org-html-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to HTML.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
+
 ;;;; Paragraph
 
 (defun org-html-paragraph (paragraph contents info)
@@ -2815,13 +3090,19 @@ CONTENTS is the contents of the paragraph, as a string. 
 INFO is
 the plist used as a communication channel."
   (let* ((parent (org-export-get-parent paragraph))
         (parent-type (org-element-type parent))
-        (style '((footnote-definition " class=\"footpara\"")))
-        (extra (or (cadr (assoc parent-type style)) "")))
+        (style '((footnote-definition " class=\"footpara\"")
+                 (org-data " class=\"footpara\"")))
+        (attributes (org-html--make-attribute-string
+                     (org-export-read-attribute :attr_html paragraph)))
+        (extra (or (cadr (assq parent-type style)) "")))
     (cond
-     ((and (eq (org-element-type parent) 'item)
-          (= (org-element-property :begin paragraph)
-             (org-element-property :contents-begin parent)))
-      ;; Leading paragraph in a list item have no tags.
+     ((and (eq parent-type 'item)
+          (not (org-export-get-previous-element paragraph info))
+          (let ((followers (org-export-get-next-element paragraph info 2)))
+            (and (not (cdr followers))
+                 (memq (org-element-type (car followers)) '(nil plain-list)))))
+      ;; First paragraph in an item has no tag if it is alone or
+      ;; followed, at most, by a sub-list.
       contents)
      ((org-html-standalone-image-p paragraph info)
       ;; Standalone image.
@@ -2829,20 +3110,24 @@ the plist used as a communication channel."
             (let ((raw (org-export-data
                         (org-export-get-caption paragraph) info))
                   (org-html-standalone-image-predicate
-                   'org-html--has-caption-p))
+                   #'org-html--has-caption-p))
               (if (not (org-string-nw-p raw)) raw
-                (concat
-                  "<span class=\"figure-number\">"
-                 (format (org-html--translate "Figure %d:" info)
-                         (org-export-get-ordinal
-                          (org-element-map paragraph 'link
-                            'identity info t)
-                          info nil 'org-html-standalone-image-p))
-                 "</span> " raw))))
-           (label (org-element-property :name paragraph)))
+                (concat "<span class=\"figure-number\">"
+                        (format (org-html--translate "Figure %d:" info)
+                                (org-export-get-ordinal
+                                 (org-element-map paragraph 'link
+                                   #'identity info t)
+                                 info nil #'org-html-standalone-image-p))
+                        " </span>"
+                        raw))))
+           (label (and (org-element-property :name paragraph)
+                       (org-export-get-reference paragraph info))))
        (org-html--wrap-image contents info caption label)))
      ;; Regular paragraph.
-     (t (format "<p%s>\n%s</p>" extra contents)))))
+     (t (format "<p%s%s>\n%s</p>"
+               (if (org-string-nw-p attributes)
+                   (concat " " attributes) "")
+               extra contents)))))
 
 ;;;; Plain List
 
@@ -2852,26 +3137,25 @@ the plist used as a communication channel."
   "Insert the beginning of the HTML list depending on TYPE.
 When ARG1 is a string, use it as the start parameter for ordered
 lists."
-  (case type
-    (ordered
+  (pcase type
+    (`ordered
      (format "<ol class=\"org-ol\"%s>"
             (if arg1 (format " start=\"%d\"" arg1) "")))
-    (unordered "<ul class=\"org-ul\">")
-    (descriptive "<dl class=\"org-dl\">")))
+    (`unordered "<ul class=\"org-ul\">")
+    (`descriptive "<dl class=\"org-dl\">")))
 
 (defun org-html-end-plain-list (type)
   "Insert the end of the HTML list depending on TYPE."
-  (case type
-    (ordered "</ol>")
-    (unordered "</ul>")
-    (descriptive "</dl>")))
+  (pcase type
+    (`ordered "</ol>")
+    (`unordered "</ul>")
+    (`descriptive "</dl>")))
 
-(defun org-html-plain-list (plain-list contents info)
+(defun org-html-plain-list (plain-list contents _info)
   "Transcode a PLAIN-LIST element from Org to HTML.
 CONTENTS is the contents of the list.  INFO is a plist holding
 contextual information."
-  (let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item
-        (type (org-element-property :type plain-list)))
+  (let ((type (org-element-property :type plain-list)))
     (format "%s\n%s%s"
            (org-html-begin-plain-list type)
            contents (org-html-end-plain-list type))))
@@ -2880,22 +3164,16 @@ contextual information."
 
 (defun org-html-convert-special-strings (string)
   "Convert special characters in STRING to HTML."
-  (let ((all org-html-special-string-regexps)
-       e a re rpl start)
-    (while (setq a (pop all))
-      (setq re (car a) rpl (cdr a) start 0)
-      (while (string-match re string start)
-       (setq string (replace-match rpl t nil string))))
-    string))
+  (dolist (a org-html-special-string-regexps string)
+    (let ((re (car a))
+         (rpl (cdr a)))
+      (setq string (replace-regexp-in-string re rpl string t)))))
 
 (defun org-html-encode-plain-text (text)
   "Convert plain text characters from TEXT to HTML equivalent.
 Possible conversions are set in `org-html-protect-char-alist'."
-  (mapc
-   (lambda (pair)
-     (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))
-   org-html-protect-char-alist)
-  text)
+  (dolist (pair org-html-protect-char-alist text)
+    (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t))))
 
 (defun org-html-plain-text (text info)
   "Transcode a TEXT string from Org to HTML.
@@ -2923,60 +3201,52 @@ contextual information."
 
 ;; Planning
 
-(defun org-html-planning (planning contents info)
+(defun org-html-planning (planning _contents info)
   "Transcode a PLANNING element from Org to HTML.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (let ((span-fmt "<span class=\"timestamp-kwd\">%s</span> <span 
class=\"timestamp\">%s</span>"))
-    (format
-     "<p><span class=\"timestamp-wrapper\">%s</span></p>"
-     (mapconcat
-      'identity
-      (delq nil
-           (list
-            (let ((closed (org-element-property :closed planning)))
-              (when closed
-                (format span-fmt org-closed-string
-                        (org-translate-time
-                         (org-element-property :raw-value closed)))))
-            (let ((deadline (org-element-property :deadline planning)))
-              (when deadline
-                (format span-fmt org-deadline-string
-                        (org-translate-time
-                         (org-element-property :raw-value deadline)))))
-            (let ((scheduled (org-element-property :scheduled planning)))
-              (when scheduled
-                (format span-fmt org-scheduled-string
-                        (org-translate-time
-                         (org-element-property :raw-value scheduled)))))))
-      " "))))
+  (format
+   "<p><span class=\"timestamp-wrapper\">%s</span></p>"
+   (org-trim
+    (mapconcat
+     (lambda (pair)
+       (let ((timestamp (cdr pair)))
+        (when timestamp
+          (let ((string (car pair)))
+            (format "<span class=\"timestamp-kwd\">%s</span> \
+<span class=\"timestamp\">%s</span> "
+                    string
+                    (org-html-plain-text (org-timestamp-translate timestamp)
+                                         info))))))
+     `((,org-closed-string . ,(org-element-property :closed planning))
+       (,org-deadline-string . ,(org-element-property :deadline planning))
+       (,org-scheduled-string . ,(org-element-property :scheduled planning)))
+     ""))))
 
 ;;;; Property Drawer
 
-(defun org-html-property-drawer (property-drawer contents info)
+(defun org-html-property-drawer (_property-drawer contents _info)
   "Transcode a PROPERTY-DRAWER element from Org to HTML.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  ;; The property drawer isn't exported but we want separating blank
-  ;; lines nonetheless.
-  "")
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (format "<pre class=\"example\">\n%s</pre>" contents)))
 
 ;;;; Quote Block
 
-(defun org-html-quote-block (quote-block contents info)
+(defun org-html-quote-block (quote-block contents _info)
   "Transcode a QUOTE-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (format "<blockquote>\n%s</blockquote>" contents))
-
-;;;; Quote Section
-
-(defun org-html-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to HTML.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((value (org-remove-indentation
-               (org-element-property :value quote-section))))
-    (when value (format "<pre>\n%s</pre>" value))))
+  (format "<blockquote%s>\n%s</blockquote>"
+         (let* ((name (org-element-property :name quote-block))
+                (attributes (org-export-read-attribute :attr_html quote-block))
+                (a (org-html--make-attribute-string
+                    (if (or (not name) (plist-member attributes :id))
+                        attributes
+                      (plist-put attributes :id name)))))
+           (if (org-string-nw-p a) (concat " " a) ""))
+         contents))
 
 ;;;; Section
 
@@ -2989,16 +3259,19 @@ holding contextual information."
     (if (not parent) contents
       ;; Get div's class and id references.
       (let* ((class-num (+ (org-export-get-relative-level parent info)
-                          (1- org-html-toplevel-hlevel)))
+                          (1- (plist-get info :html-toplevel-hlevel))))
             (section-number
-             (mapconcat
-              'number-to-string
-              (org-export-get-headline-number parent info) "-")))
+             (and (org-export-numbered-headline-p parent info)
+                  (mapconcat
+                   #'number-to-string
+                   (org-export-get-headline-number parent info) "-"))))
         ;; Build return value.
        (format "<div class=\"outline-text-%d\" id=\"text-%s\">\n%s</div>"
                class-num
-               (or (org-element-property :CUSTOM_ID parent) section-number)
-               contents)))))
+               (or (org-element-property :CUSTOM_ID parent)
+                   section-number
+                   (org-export-get-reference parent info))
+               (or contents ""))))))
 
 ;;;; Radio Target
 
@@ -3006,9 +3279,8 @@ holding contextual information."
   "Transcode a RADIO-TARGET object from Org to HTML.
 TEXT is the text of the target.  INFO is a plist holding
 contextual information."
-  (let ((id (org-export-solidify-link-text
-            (org-element-property :value radio-target))))
-    (org-html--anchor id text)))
+  (let ((ref (org-export-get-reference radio-target info)))
+    (org-html--anchor ref text nil info)))
 
 ;;;; Special Block
 
@@ -3016,52 +3288,61 @@ contextual information."
   "Transcode a SPECIAL-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (let* ((block-type (downcase
-                     (org-element-property :type special-block)))
-        (contents (or contents ""))
-        (html5-fancy (and (org-html-html5-p info)
-                          (plist-get info :html-html5-fancy)
-                          (member block-type org-html-html5-elements)))
-        (attributes (org-export-read-attribute :attr_html special-block)))
+  (let* ((block-type (org-element-property :type special-block))
+         (html5-fancy (and (org-html--html5-fancy-p info)
+                           (member block-type org-html-html5-elements)))
+         (attributes (org-export-read-attribute :attr_html special-block)))
     (unless html5-fancy
       (let ((class (plist-get attributes :class)))
-       (setq attributes (plist-put attributes :class
-                                   (if class (concat class " " block-type)
-                                     block-type)))))
-    (setq attributes (org-html--make-attribute-string attributes))
-    (when (not (equal attributes ""))
-      (setq attributes (concat " " attributes)))
-    (if html5-fancy
-       (format "<%s%s>\n%s</%s>" block-type attributes
-               contents block-type)
-      (format "<div%s>\n%s\n</div>" attributes contents))))
+        (setq attributes (plist-put attributes :class
+                                    (if class (concat class " " block-type)
+                                      block-type)))))
+    (let* ((contents (or contents ""))
+          (name (org-element-property :name special-block))
+          (a (org-html--make-attribute-string
+              (if (or (not name) (plist-member attributes :id))
+                  attributes
+                (plist-put attributes :id name))))
+          (str (if (org-string-nw-p a) (concat " " a) "")))
+      (if html5-fancy
+         (format "<%s%s>\n%s</%s>" block-type str contents block-type)
+       (format "<div%s>\n%s\n</div>" str contents)))))
 
 ;;;; Src Block
 
-(defun org-html-src-block (src-block contents info)
+(defun org-html-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to HTML.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (if (org-export-read-attribute :attr_html src-block :textarea)
       (org-html--textarea-block src-block)
     (let ((lang (org-element-property :language src-block))
-         (caption (org-export-get-caption src-block))
          (code (org-html-format-code src-block info))
-         (label (let ((lbl (org-element-property :name src-block)))
-                  (if (not lbl) ""
-                    (format " id=\"%s\""
-                            (org-export-solidify-link-text lbl))))))
+         (label (let ((lbl (and (org-element-property :name src-block)
+                                (org-export-get-reference src-block info))))
+                  (if lbl (format " id=\"%s\"" lbl) ""))))
       (if (not lang) (format "<pre class=\"example\"%s>\n%s</pre>" label code)
-       (format
-        "<div class=\"org-src-container\">\n%s%s\n</div>"
-        (if (not caption) ""
-          (format "<label class=\"org-src-name\">%s</label>"
-                  (org-export-data caption info)))
-        (format "\n<pre class=\"src src-%s\"%s>%s</pre>" lang label code))))))
+       (format "<div class=\"org-src-container\">\n%s%s\n</div>"
+               ;; Build caption.
+               (let ((caption (org-export-get-caption src-block)))
+                 (if (not caption) ""
+                   (let ((listing-number
+                          (format
+                           "<span class=\"listing-number\">%s </span>"
+                           (format
+                            (org-html--translate "Listing %d:" info)
+                            (org-export-get-ordinal
+                             src-block info nil #'org-html--has-caption-p)))))
+                     (format "<label class=\"org-src-name\">%s%s</label>"
+                             listing-number
+                             (org-trim (org-export-data caption info))))))
+               ;; Contents.
+               (format "<pre class=\"src src-%s\"%s>%s</pre>"
+                       lang label code))))))
 
 ;;;; Statistics Cookie
 
-(defun org-html-statistics-cookie (statistics-cookie contents info)
+(defun org-html-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((cookie-value (org-element-property :value statistics-cookie)))
@@ -3069,16 +3350,18 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Strike-Through
 
-(defun org-html-strike-through (strike-through contents info)
+(defun org-html-strike-through (_strike-through contents info)
   "Transcode STRIKE-THROUGH from Org to HTML.
 CONTENTS is the text with strike-through markup.  INFO is a plist
 holding contextual information."
-  (format (or (cdr (assq 'strike-through org-html-text-markup-alist)) "%s")
-         contents))
+  (format
+   (or (cdr (assq 'strike-through (plist-get info :html-text-markup-alist)))
+       "%s")
+   contents))
 
 ;;;; Subscript
 
-(defun org-html-subscript (subscript contents info)
+(defun org-html-subscript (_subscript contents _info)
   "Transcode a SUBSCRIPT object from Org to HTML.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -3086,7 +3369,7 @@ contextual information."
 
 ;;;; Superscript
 
-(defun org-html-superscript (superscript contents info)
+(defun org-html-superscript (_superscript contents _info)
   "Transcode a SUPERSCRIPT object from Org to HTML.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -3101,24 +3384,30 @@ channel."
   (let* ((table-row (org-export-get-parent table-cell))
         (table (org-export-get-parent-table table-cell))
         (cell-attrs
-         (if (not org-html-table-align-individual-fields) ""
+         (if (not (plist-get info :html-table-align-individual-fields)) ""
            (format (if (and (boundp 'org-html-format-table-no-css)
                             org-html-format-table-no-css)
-                       " align=\"%s\"" " class=\"%s\"")
+                       " align=\"%s\"" " class=\"org-%s\"")
                    (org-export-table-cell-alignment table-cell info)))))
     (when (or (not contents) (string= "" (org-trim contents)))
       (setq contents "&#xa0;"))
     (cond
      ((and (org-export-table-has-header-p table info)
           (= 1 (org-export-table-row-group table-row info)))
-      (concat "\n" (format (car org-html-table-header-tags) "col" cell-attrs)
-             contents (cdr org-html-table-header-tags)))
-     ((and org-html-table-use-header-tags-for-first-column
+      (let ((header-tags (plist-get info :html-table-header-tags)))
+       (concat "\n" (format (car header-tags) "col" cell-attrs)
+               contents
+               (cdr header-tags))))
+     ((and (plist-get info :html-table-use-header-tags-for-first-column)
           (zerop (cdr (org-export-table-cell-address table-cell info))))
-      (concat "\n" (format (car org-html-table-header-tags) "row" cell-attrs)
-             contents (cdr org-html-table-header-tags)))
-     (t (concat "\n" (format (car org-html-table-data-tags) cell-attrs)
-               contents (cdr org-html-table-data-tags))))))
+      (let ((header-tags (plist-get info :html-table-header-tags)))
+       (concat "\n" (format (car header-tags) "row" cell-attrs)
+               contents
+               (cdr header-tags))))
+     (t (let ((data-tags (plist-get info :html-table-data-tags)))
+         (concat "\n" (format (car data-tags) cell-attrs)
+                 contents
+                 (cdr data-tags)))))))
 
 ;;;; Table Row
 
@@ -3129,40 +3418,45 @@ communication channel."
   ;; Rules are ignored since table separators are deduced from
   ;; borders of the current row.
   (when (eq (org-element-property :type table-row) 'standard)
-    (let* ((rowgroup-number (org-export-table-row-group table-row info))
-          (row-number (org-export-table-row-number table-row info))
-          (start-rowgroup-p
+    (let* ((group (org-export-table-row-group table-row info))
+          (number (org-export-table-row-number table-row info))
+          (start-group-p
            (org-export-table-row-starts-rowgroup-p table-row info))
-          (end-rowgroup-p
+          (end-group-p
            (org-export-table-row-ends-rowgroup-p table-row info))
-          ;; `top-row-p' and `end-rowgroup-p' are not used directly
-          ;; but should be set so that `org-html-table-row-tags' can
-          ;; use them (see the docstring of this variable.)
-          (top-row-p (and (equal start-rowgroup-p '(top))
-                          (equal end-rowgroup-p '(below top))))
-          (bottom-row-p (and (equal start-rowgroup-p '(above))
-                             (equal end-rowgroup-p '(bottom above))))
-          (rowgroup-tags
+          (topp (and (equal start-group-p '(top))
+                     (equal end-group-p '(below top))))
+          (bottomp (and (equal start-group-p '(above))
+                        (equal end-group-p '(bottom above))))
+           (row-open-tag
+            (pcase (plist-get info :html-table-row-open-tag)
+              ((and accessor (pred functionp))
+               (funcall accessor
+                       number group start-group-p end-group-p topp bottomp))
+             (accessor accessor)))
+           (row-close-tag
+            (pcase (plist-get info :html-table-row-close-tag)
+              ((and accessor (pred functionp))
+               (funcall accessor
+                       number group start-group-p end-group-p topp bottomp))
+             (accessor accessor)))
+          (group-tags
            (cond
-            ;; Case 1: Row belongs to second or subsequent rowgroups.
-            ((not (= 1 rowgroup-number))
-             '("<tbody>" . "\n</tbody>"))
-            ;; Case 2: Row is from first rowgroup.  Table has >=1 rowgroups.
+            ;; Row belongs to second or subsequent groups.
+            ((not (= 1 group)) '("<tbody>" . "\n</tbody>"))
+            ;; Row is from first group.  Table has >=1 groups.
             ((org-export-table-has-header-p
               (org-export-get-parent-table table-row) info)
              '("<thead>" . "\n</thead>"))
-            ;; Case 2: Row is from first and only row group.
+            ;; Row is from first and only group.
             (t '("<tbody>" . "\n</tbody>")))))
-      (concat
-       ;; Begin a rowgroup?
-       (when start-rowgroup-p (car rowgroup-tags))
-       ;; Actual table row
-       (concat "\n" (eval (car org-html-table-row-tags))
-              contents
-              "\n"
-              (eval (cdr org-html-table-row-tags)))
-       ;; End a rowgroup?
-       (when end-rowgroup-p (cdr rowgroup-tags))))))
+      (concat (and start-group-p (car group-tags))
+             (concat "\n"
+                     row-open-tag
+                     contents
+                     "\n"
+                     row-close-tag)
+             (and end-group-p (cdr group-tags))))))
 
 ;;;; Table
 
@@ -3178,7 +3472,7 @@ INFO is a plist used as a communication channel."
     (if (not special-column-p) (org-element-contents table-row)
       (cdr (org-element-contents table-row)))))
 
-(defun org-html-table--table.el-table (table info)
+(defun org-html-table--table.el-table (table _info)
   "Format table.el tables into HTML.
 INFO is a plist used as a communication channel."
   (when (eq (org-element-property :type table) 'table.el)
@@ -3199,134 +3493,123 @@ INFO is a plist used as a communication channel."
   "Transcode a TABLE element from Org to HTML.
 CONTENTS is the contents of the table.  INFO is a plist holding
 contextual information."
-  (case (org-element-property :type table)
-    ;; Case 1: table.el table.  Convert it using appropriate tools.
-    (table.el (org-html-table--table.el-table table info))
-    ;; Case 2: Standard table.
-    (t
-     (let* ((label (org-element-property :name table))
-           (caption (org-export-get-caption table))
-           (number (org-export-get-ordinal
-                    table info nil 'org-html--has-caption-p))
-           (attributes
-            (org-html--make-attribute-string
-             (org-combine-plists
-              (and label (list :id (org-export-solidify-link-text label)))
-              (and (not (org-html-html5-p info))
-                   (plist-get info :html-table-attributes))
-              (org-export-read-attribute :attr_html table))))
-           (alignspec
-            (if (and (boundp 'org-html-format-table-no-css)
-                     org-html-format-table-no-css)
-                "align=\"%s\"" "class=\"%s\""))
-           (table-column-specs
-            (function
-             (lambda (table info)
-               (mapconcat
-                (lambda (table-cell)
-                  (let ((alignment (org-export-table-cell-alignment
-                                    table-cell info)))
-                    (concat
-                     ;; Begin a colgroup?
-                     (when (org-export-table-cell-starts-colgroup-p
-                            table-cell info)
-                       "\n<colgroup>")
-                     ;; Add a column.  Also specify it's alignment.
-                     (format "\n%s"
-                             (org-html-close-tag
-                              "col" (concat " " (format alignspec alignment)) 
info))
-                     ;; End a colgroup?
-                     (when (org-export-table-cell-ends-colgroup-p
-                            table-cell info)
-                       "\n</colgroup>"))))
-                (org-html-table-first-row-data-cells table info) "\n")))))
-       (format "<table%s>\n%s\n%s\n%s</table>"
-              (if (equal attributes "") "" (concat " " attributes))
-              (if (not caption) ""
-                (format (if org-html-table-caption-above
-                            "<caption class=\"t-above\">%s</caption>"
-                          "<caption class=\"t-bottom\">%s</caption>")
-                        (concat
-                         "<span class=\"table-number\">"
-                          (format (org-html--translate "Table %d:" info) 
number)
-                         "</span> " (org-export-data caption info))))
-              (funcall table-column-specs table info)
-              contents)))))
+  (if (eq (org-element-property :type table) 'table.el)
+      ;; "table.el" table.  Convert it using appropriate tools.
+      (org-html-table--table.el-table table info)
+    ;; Standard table.
+    (let* ((caption (org-export-get-caption table))
+          (number (org-export-get-ordinal
+                   table info nil #'org-html--has-caption-p))
+          (attributes
+           (org-html--make-attribute-string
+            (org-combine-plists
+             (and (org-element-property :name table)
+                  (list :id (org-export-get-reference table info)))
+             (and (not (org-html-html5-p info))
+                  (plist-get info :html-table-attributes))
+             (org-export-read-attribute :attr_html table))))
+          (alignspec
+           (if (bound-and-true-p org-html-format-table-no-css)
+               "align=\"%s\""
+             "class=\"org-%s\""))
+          (table-column-specs
+           (lambda (table info)
+             (mapconcat
+              (lambda (table-cell)
+                (let ((alignment (org-export-table-cell-alignment
+                                  table-cell info)))
+                  (concat
+                   ;; Begin a colgroup?
+                   (when (org-export-table-cell-starts-colgroup-p
+                          table-cell info)
+                     "\n<colgroup>")
+                   ;; Add a column.  Also specify its alignment.
+                   (format "\n%s"
+                           (org-html-close-tag
+                            "col" (concat " " (format alignspec alignment)) 
info))
+                   ;; End a colgroup?
+                   (when (org-export-table-cell-ends-colgroup-p
+                          table-cell info)
+                     "\n</colgroup>"))))
+              (org-html-table-first-row-data-cells table info) "\n"))))
+      (format "<table%s>\n%s\n%s\n%s</table>"
+             (if (equal attributes "") "" (concat " " attributes))
+             (if (not caption) ""
+               (format (if (plist-get info :html-table-caption-above)
+                           "<caption class=\"t-above\">%s</caption>"
+                         "<caption class=\"t-bottom\">%s</caption>")
+                       (concat
+                        "<span class=\"table-number\">"
+                        (format (org-html--translate "Table %d:" info) number)
+                        "</span> " (org-export-data caption info))))
+             (funcall table-column-specs table info)
+             contents))))
 
 ;;;; Target
 
-(defun org-html-target (target contents info)
+(defun org-html-target (target _contents info)
   "Transcode a TARGET object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (let ((id (org-export-solidify-link-text
-            (org-element-property :value target))))
-    (org-html--anchor id)))
+  (let ((ref (org-export-get-reference target info)))
+    (org-html--anchor ref nil nil info)))
 
 ;;;; Timestamp
 
-(defun org-html-timestamp (timestamp contents info)
+(defun org-html-timestamp (timestamp _contents info)
   "Transcode a TIMESTAMP object from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (let ((value (org-html-plain-text
-               (org-timestamp-translate timestamp) info)))
+  (let ((value (org-html-plain-text (org-timestamp-translate timestamp) info)))
     (format "<span class=\"timestamp-wrapper\"><span 
class=\"timestamp\">%s</span></span>"
            (replace-regexp-in-string "--" "&#x2013;" value))))
 
 ;;;; Underline
 
-(defun org-html-underline (underline contents info)
+(defun org-html-underline (_underline contents info)
   "Transcode UNDERLINE from Org to HTML.
 CONTENTS is the text with underline markup.  INFO is a plist
 holding contextual information."
-  (format (or (cdr (assq 'underline org-html-text-markup-alist)) "%s")
+  (format (or (cdr (assq 'underline (plist-get info :html-text-markup-alist)))
+             "%s")
          contents))
 
 ;;;; Verbatim
 
-(defun org-html-verbatim (verbatim contents info)
+(defun org-html-verbatim (verbatim _contents info)
   "Transcode VERBATIM from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format (or (cdr (assq 'verbatim org-html-text-markup-alist)) "%s")
+  (format (or (cdr (assq 'verbatim (plist-get info :html-text-markup-alist))) 
"%s")
          (org-html-encode-plain-text (org-element-property :value verbatim))))
 
 ;;;; Verse Block
 
-(defun org-html-verse-block (verse-block contents info)
+(defun org-html-verse-block (_verse-block contents info)
   "Transcode a VERSE-BLOCK element from Org to HTML.
 CONTENTS is verse block contents.  INFO is a plist holding
 contextual information."
-  ;; Replace each newline character with line break.  Also replace
-  ;; each blank line with a line break.
-  (setq contents (replace-regexp-in-string
-                 "^ *\\\\\\\\$" (format "%s\n" (org-html-close-tag "br" nil 
info))
-                 (replace-regexp-in-string
-                  "\\(\\\\\\\\\\)?[ \t]*\n"
-                  (format "%s\n" (org-html-close-tag "br" nil info)) 
contents)))
-  ;; Replace each white space at beginning of a line with a
-  ;; non-breaking space.
-  (while (string-match "^[ \t]+" contents)
-    (let* ((num-ws (length (match-string 0 contents)))
-          (ws (let (out) (dotimes (i num-ws out)
-                           (setq out (concat out "&#xa0;"))))))
-      (setq contents (replace-match ws nil t contents))))
-  (format "<p class=\"verse\">\n%s</p>" contents))
+  (format "<p class=\"verse\">\n%s</p>"
+         ;; Replace leading white spaces with non-breaking spaces.
+         (replace-regexp-in-string
+          "^[ \t]+" (lambda (m) (org-html--make-string (length m) "&#xa0;"))
+          ;; Replace each newline character with line break.  Also
+          ;; remove any trailing "br" close-tag so as to avoid
+          ;; duplicates.
+          (let* ((br (org-html-close-tag "br" nil info))
+                 (re (format "\\(?:%s\\)?[ \t]*\n" (regexp-quote br))))
+            (replace-regexp-in-string re (concat br "\n") contents)))))
 
 
 ;;; Filter Functions
 
-(defun org-html-final-function (contents backend info)
+(defun org-html-final-function (contents _backend info)
   "Filter to indent the HTML and convert HTML entities."
   (with-temp-buffer
     (insert contents)
     (set-auto-mode t)
-    (if org-html-indent
+    (if (plist-get info :html-indent)
        (indent-region (point-min) (point-max)))
-    (when org-html-use-unicode-chars
-      (require 'mm-url)
-      (mm-url-decode-entities))
     (buffer-substring-no-properties (point-min) (point-max))))
 
 
@@ -3370,10 +3653,10 @@ is non-nil."
 
 ;;;###autoload
 (defun org-html-convert-region-to-html ()
-  "Assume the current region has org-mode syntax, and convert it to HTML.
+  "Assume the current region has Org syntax, and convert it to HTML.
 This can be used in any buffer.  For example, you can write an
-itemized list in org-mode syntax in an HTML buffer and use this
-command to convert it."
+itemized list in Org syntax in an HTML buffer and use this command
+to convert it."
   (interactive)
   (org-export-replace-region-by 'html))
 
@@ -3407,7 +3690,9 @@ file-local settings.
 
 Return output file's name."
   (interactive)
-  (let* ((extension (concat "." org-html-extension))
+  (let* ((extension (concat "." (or (plist-get ext-plist :html-extension)
+                                   org-html-extension
+                                   "html")))
         (file (org-export-output-file-name extension subtreep))
         (org-export-coding-system org-html-coding-system))
     (org-export-to-file 'html file
@@ -3424,7 +3709,8 @@ publishing directory.
 Return output file name."
   (org-publish-org-to 'html filename
                      (concat "." (or (plist-get plist :html-extension)
-                                     org-html-extension "html"))
+                                     org-html-extension
+                                     "html"))
                      plist pub-dir))
 
 
diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el
index fe6d08a..9ccbb27 100644
--- a/lisp/org/ox-icalendar.el
+++ b/lisp/org/ox-icalendar.el
@@ -1,4 +1,4 @@
-;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine
+;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 
@@ -31,7 +31,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'ox-ascii)
 (declare-function org-bbdb-anniv-export-ical "org-bbdb" nil)
 
@@ -46,7 +46,7 @@
 
 (defcustom org-icalendar-combined-agenda-file "~/org.ics"
   "The file name for the iCalendar file covering all agenda files.
-This file is created with the command \\[org-icalendar-combine-agenda-files].
+This file is created with the command `\\[org-icalendar-combine-agenda-files]'.
 The file name should be absolute.  It will be overwritten without warning."
   :group 'org-export-icalendar
   :type 'file)
@@ -77,7 +77,7 @@ for timed events.  If non-zero, alarms are created.
 (defcustom org-icalendar-exclude-tags nil
   "Tags that exclude a tree from export.
 This variable allows specifying different exclude tags from other
-back-ends.  It can also be set with the ICAL_EXCLUDE_TAGS
+back-ends.  It can also be set with the ICALENDAR_EXCLUDE_TAGS
 keyword."
   :group 'org-export-icalendar
   :type '(repeat (string :tag "Tag")))
@@ -85,10 +85,11 @@ keyword."
 (defcustom org-icalendar-use-deadline '(event-if-not-todo todo-due)
   "Contexts where iCalendar export should use a deadline time stamp.
 
-This is a list with several symbols in it.  Valid symbol are:
+This is a list with possibly several symbols in it.  Valid symbols are:
+
 `event-if-todo'       Deadlines in TODO entries become calendar events.
 `event-if-not-todo'   Deadlines in non-TODO entries become calendar events.
-`todo-due'            Use deadlines in TODO entries as due-dates"
+`todo-due'            Use deadlines in TODO entries as due-dates."
   :group 'org-export-icalendar
   :type '(set :greedy t
              (const :tag "Deadlines in non-TODO entries become events"
@@ -101,7 +102,8 @@ This is a list with several symbols in it.  Valid symbol 
are:
 (defcustom org-icalendar-use-scheduled '(todo-start)
   "Contexts where iCalendar export should use a scheduling time stamp.
 
-This is a list with several symbols in it.  Valid symbol are:
+This is a list with possibly several symbols in it.  Valid symbols are:
+
 `event-if-todo'       Scheduling time stamps in TODO entries become an event.
 `event-if-not-todo'   Scheduling time stamps in non-TODO entries become an 
event.
 `todo-start'          Scheduling time stamps in TODO entries become start date.
@@ -256,11 +258,18 @@ re-read the iCalendar file.")
   '((:exclude-tags
      "ICALENDAR_EXCLUDE_TAGS" nil org-icalendar-exclude-tags split)
     (:with-timestamps nil "<" org-icalendar-with-timestamps)
-    (:with-vtodo nil nil org-icalendar-include-todo)
-    ;; The following property will be non-nil when export has been
-    ;; started from org-agenda-mode.  In this case, any entry without
-    ;; a non-nil "ICALENDAR_MARK" property will be ignored.
-    (:icalendar-agenda-view nil nil nil))
+    ;; Other variables.
+    (:icalendar-alarm-time nil nil org-icalendar-alarm-time)
+    (:icalendar-categories nil nil org-icalendar-categories)
+    (:icalendar-date-time-format nil nil org-icalendar-date-time-format)
+    (:icalendar-include-bbdb-anniversaries nil nil 
org-icalendar-include-bbdb-anniversaries)
+    (:icalendar-include-body nil nil org-icalendar-include-body)
+    (:icalendar-include-sexps nil nil org-icalendar-include-sexps)
+    (:icalendar-include-todo nil nil org-icalendar-include-todo)
+    (:icalendar-store-UID nil nil org-icalendar-store-UID)
+    (:icalendar-timezone nil nil org-icalendar-timezone)
+    (:icalendar-use-deadline nil nil org-icalendar-use-deadline)
+    (:icalendar-use-scheduled nil nil org-icalendar-use-scheduled))
   :filters-alist
   '((:filter-headline . org-icalendar-clear-blank-lines))
   :menu-entry
@@ -275,22 +284,18 @@ re-read the iCalendar file.")
 
 ;;; Internal Functions
 
-(defun org-icalendar-create-uid (file &optional bell h-markers)
+(defun org-icalendar-create-uid (file &optional bell)
   "Set ID property on headlines missing it in FILE.
 When optional argument BELL is non-nil, inform the user with
-a message if the file was modified.  With optional argument
-H-MARKERS non-nil, it is a list of markers for the headlines
-which will be updated."
-  (let ((pt (if h-markers (goto-char (car h-markers)) (point-min)))
-       modified-flag)
+a message if the file was modified."
+  (let (modified-flag)
     (org-map-entries
      (lambda ()
        (let ((entry (org-element-at-point)))
-        (unless (or (< (point) pt) (org-element-property :ID entry))
+        (unless (org-element-property :ID entry)
           (org-id-get-create)
           (setq modified-flag t)
-          (forward-line))
-        (when h-markers (setq org-map-continue-from (pop h-markers)))))
+          (forward-line))))
      nil nil 'comment)
     (when (and bell modified-flag)
       (message "ID properties created in file \"%s\"" file)
@@ -318,19 +323,17 @@ A headline is blocked when either
    ;; Check :ORDERED: node property.
    (catch 'blockedp
      (let ((current headline))
-       (mapc (lambda (parent)
-              (cond
-               ((not (org-element-property :todo-keyword parent))
-                (throw 'blockedp nil))
-               ((org-not-nil (org-element-property :ORDERED parent))
-                (let ((sibling current))
-                  (while (setq sibling (org-export-get-previous-element
-                                        sibling info))
-                    (when (eq (org-element-property :todo-type sibling) 'todo)
-                      (throw 'blockedp t)))))
-               (t (setq current parent))))
-            (org-export-get-genealogy headline))
-       nil))))
+       (dolist (parent (org-element-lineage headline))
+        (cond
+         ((not (org-element-property :todo-keyword parent))
+          (throw 'blockedp nil))
+         ((org-not-nil (org-element-property :ORDERED parent))
+          (let ((sibling current))
+            (while (setq sibling (org-export-get-previous-element
+                                  sibling info))
+              (when (eq (org-element-property :todo-type sibling) 'todo)
+                (throw 'blockedp t)))))
+         (t (setq current parent))))))))
 
 (defun org-icalendar-use-UTC-date-time-p ()
   "Non-nil when `org-icalendar-date-time-format' requires UTC time."
@@ -393,8 +396,8 @@ Universal Time, ignoring `org-icalendar-date-time-format'."
       ;; Convert timestamp into internal time in order to use
       ;; `format-time-string' and fix any mistake (i.e. MI >= 60).
       (encode-time 0 mi h d m y)
-      (not (not (or utc (and with-time-p
-                             (org-icalendar-use-UTC-date-time-p)))))))))
+      (and (or utc (and with-time-p (org-icalendar-use-UTC-date-time-p)))
+          t)))))
 
 (defun org-icalendar-dtstamp ()
   "Return DTSTAMP property, as a string."
@@ -405,27 +408,25 @@ Universal Time, ignoring 
`org-icalendar-date-time-format'."
 ENTRY is a headline or an inlinetask element.  INFO is a plist
 used as a communication channel."
   (mapconcat
-   'identity
+   #'identity
    (org-uniquify
     (let (categories)
-      (mapc (lambda (type)
-             (case type
-               (category
-                (push (org-export-get-category entry info) categories))
-               (todo-state
-                (let ((todo (org-element-property :todo-keyword entry)))
-                  (and todo (push todo categories))))
-               (local-tags
-                (setq categories
-                      (append (nreverse (org-export-get-tags entry info))
-                              categories)))
-               (all-tags
-                (setq categories
-                      (append (nreverse (org-export-get-tags entry info nil t))
-                              categories)))))
-           org-icalendar-categories)
-      ;; Return list of categories, following specified order.
-      (nreverse categories))) ","))
+      (dolist (type org-icalendar-categories (nreverse categories))
+       (cl-case type
+         (category
+          (push (org-export-get-category entry info) categories))
+         (todo-state
+          (let ((todo (org-element-property :todo-keyword entry)))
+            (and todo (push todo categories))))
+         (local-tags
+          (setq categories
+                (append (nreverse (org-export-get-tags entry info))
+                        categories)))
+         (all-tags
+          (setq categories
+                (append (nreverse (org-export-get-tags entry info nil t))
+                        categories)))))))
+   ","))
 
 (defun org-icalendar-transcode-diary-sexp (sexp uid summary)
   "Transcode a diary sexp into iCalendar format.
@@ -457,7 +458,7 @@ or subject for the event."
    (mapconcat
     (lambda (line)
       ;; Limit each line to a maximum of 75 characters.  If it is
-      ;; longer, fold it by using "\n " as a continuation marker.
+      ;; longer, fold it by using "\r\n " as a continuation marker.
       (let ((len (length line)))
        (if (<= len 75) line
          (let ((folded-line (substring line 0 75))
@@ -467,17 +468,17 @@ or subject for the event."
            ;; line, real contents must be split at 74 chars.
            (while (< (setq chunk-end (+ chunk-start 74)) len)
              (setq folded-line
-                   (concat folded-line "\n "
+                   (concat folded-line "\r\n "
                            (substring line chunk-start chunk-end))
                    chunk-start chunk-end))
-           (concat folded-line "\n " (substring line chunk-start))))))
-    (org-split-string s "\n") "\n")))
+           (concat folded-line "\r\n " (substring line chunk-start))))))
+    (org-split-string s "\n") "\r\n")))
 
 
 
 ;;; Filters
 
-(defun org-icalendar-clear-blank-lines (headline back-end info)
+(defun org-icalendar-clear-blank-lines (headline _back-end _info)
   "Remove blank lines in HEADLINE export.
 HEADLINE is a string representing a transcoded headline.
 BACK-END and INFO are ignored."
@@ -522,99 +523,97 @@ inlinetask within the section."
                     (cons 'org-data
                           (cons nil (org-element-contents first))))))))
       (concat
-       (unless (and (plist-get info :icalendar-agenda-view)
-                   (not (org-element-property :ICALENDAR-MARK entry)))
-        (let ((todo-type (org-element-property :todo-type entry))
-              (uid (or (org-element-property :ID entry) (org-id-new)))
-              (summary (org-icalendar-cleanup-string
-                        (or (org-element-property :SUMMARY entry)
-                            (org-export-data
-                             (org-element-property :title entry) info))))
-              (loc (org-icalendar-cleanup-string
-                    (org-element-property :LOCATION entry)))
-              ;; Build description of the entry from associated
-              ;; section (headline) or contents (inlinetask).
-              (desc
-               (org-icalendar-cleanup-string
-                (or (org-element-property :DESCRIPTION entry)
-                    (let ((contents (org-export-data inside info)))
-                      (cond
-                       ((not (org-string-nw-p contents)) nil)
-                       ((wholenump org-icalendar-include-body)
-                        (let ((contents (org-trim contents)))
-                          (substring
-                           contents 0 (min (length contents)
-                                           org-icalendar-include-body))))
-                       (org-icalendar-include-body (org-trim contents)))))))
-              (cat (org-icalendar-get-categories entry info)))
-          (concat
-           ;; Events: Delegate to `org-icalendar--vevent' to
-           ;; generate "VEVENT" component from scheduled, deadline,
-           ;; or any timestamp in the entry.
-           (let ((deadline (org-element-property :deadline entry)))
-             (and deadline
-                  (memq (if todo-type 'event-if-todo 'event-if-not-todo)
-                        org-icalendar-use-deadline)
-                  (org-icalendar--vevent
-                   entry deadline (concat "DL-" uid)
-                   (concat "DL: " summary) loc desc cat)))
-           (let ((scheduled (org-element-property :scheduled entry)))
-             (and scheduled
-                  (memq (if todo-type 'event-if-todo 'event-if-not-todo)
-                        org-icalendar-use-scheduled)
-                  (org-icalendar--vevent
-                   entry scheduled (concat "SC-" uid)
-                   (concat "S: " summary) loc desc cat)))
-           ;; When collecting plain timestamps from a headline and
-           ;; its title, skip inlinetasks since collection will
-           ;; happen once ENTRY is one of them.
+       (let ((todo-type (org-element-property :todo-type entry))
+            (uid (or (org-element-property :ID entry) (org-id-new)))
+            (summary (org-icalendar-cleanup-string
+                      (or (org-element-property :SUMMARY entry)
+                          (org-export-data
+                           (org-element-property :title entry) info))))
+            (loc (org-icalendar-cleanup-string
+                  (org-element-property :LOCATION entry)))
+            ;; Build description of the entry from associated section
+            ;; (headline) or contents (inlinetask).
+            (desc
+             (org-icalendar-cleanup-string
+              (or (org-element-property :DESCRIPTION entry)
+                  (let ((contents (org-export-data inside info)))
+                    (cond
+                     ((not (org-string-nw-p contents)) nil)
+                     ((wholenump org-icalendar-include-body)
+                      (let ((contents (org-trim contents)))
+                        (substring
+                         contents 0 (min (length contents)
+                                         org-icalendar-include-body))))
+                     (org-icalendar-include-body (org-trim contents)))))))
+            (cat (org-icalendar-get-categories entry info)))
+        (concat
+         ;; Events: Delegate to `org-icalendar--vevent' to generate
+         ;; "VEVENT" component from scheduled, deadline, or any
+         ;; timestamp in the entry.
+         (let ((deadline (org-element-property :deadline entry)))
+           (and deadline
+                (memq (if todo-type 'event-if-todo 'event-if-not-todo)
+                      org-icalendar-use-deadline)
+                (org-icalendar--vevent
+                 entry deadline (concat "DL-" uid)
+                 (concat "DL: " summary) loc desc cat)))
+         (let ((scheduled (org-element-property :scheduled entry)))
+           (and scheduled
+                (memq (if todo-type 'event-if-todo 'event-if-not-todo)
+                      org-icalendar-use-scheduled)
+                (org-icalendar--vevent
+                 entry scheduled (concat "SC-" uid)
+                 (concat "S: " summary) loc desc cat)))
+         ;; When collecting plain timestamps from a headline and its
+         ;; title, skip inlinetasks since collection will happen once
+         ;; ENTRY is one of them.
+         (let ((counter 0))
+           (mapconcat
+            #'identity
+            (org-element-map (cons (org-element-property :title entry)
+                                   (org-element-contents inside))
+                'timestamp
+              (lambda (ts)
+                (when (let ((type (org-element-property :type ts)))
+                        (cl-case (plist-get info :with-timestamps)
+                          (active (memq type '(active active-range)))
+                          (inactive (memq type '(inactive inactive-range)))
+                          ((t) t)))
+                  (let ((uid (format "TS%d-%s" (cl-incf counter) uid)))
+                    (org-icalendar--vevent
+                     entry ts uid summary loc desc cat))))
+              info nil (and (eq type 'headline) 'inlinetask))
+            ""))
+         ;; Task: First check if it is appropriate to export it.  If
+         ;; so, call `org-icalendar--vtodo' to transcode it into
+         ;; a "VTODO" component.
+         (when (and todo-type
+                    (cl-case (plist-get info :icalendar-include-todo)
+                      (all t)
+                      (unblocked
+                       (and (eq type 'headline)
+                            (not (org-icalendar-blocked-headline-p
+                                  entry info))))
+                      ((t) (eq todo-type 'todo))))
+           (org-icalendar--vtodo entry uid summary loc desc cat))
+         ;; Diary-sexp: Collect every diary-sexp element within ENTRY
+         ;; and its title, and transcode them.  If ENTRY is
+         ;; a headline, skip inlinetasks: they will be handled
+         ;; separately.
+         (when org-icalendar-include-sexps
            (let ((counter 0))
-             (mapconcat
-              #'identity
-              (org-element-map (cons (org-element-property :title entry)
-                                     (org-element-contents inside))
-                  'timestamp
-                (lambda (ts)
-                  (when (let ((type (org-element-property :type ts)))
-                          (case (plist-get info :with-timestamps)
-                            (active (memq type '(active active-range)))
-                            (inactive (memq type '(inactive inactive-range)))
-                            ((t) t)))
-                    (let ((uid (format "TS%d-%s" (incf counter) uid)))
-                      (org-icalendar--vevent
-                       entry ts uid summary loc desc cat))))
-                info nil (and (eq type 'headline) 'inlinetask))
-              ""))
-           ;; Task: First check if it is appropriate to export it.
-           ;; If so, call `org-icalendar--vtodo' to transcode it
-           ;; into a "VTODO" component.
-           (when (and todo-type
-                      (case (plist-get info :with-vtodo)
-                        (all t)
-                        (unblocked
-                         (and (eq type 'headline)
-                              (not (org-icalendar-blocked-headline-p
-                                    entry info))))
-                        ((t) (eq todo-type 'todo))))
-             (org-icalendar--vtodo entry uid summary loc desc cat))
-           ;; Diary-sexp: Collect every diary-sexp element within
-           ;; ENTRY and its title, and transcode them.  If ENTRY is
-           ;; a headline, skip inlinetasks: they will be handled
-           ;; separately.
-           (when org-icalendar-include-sexps
-             (let ((counter 0))
-               (mapconcat #'identity
-                          (org-element-map
-                              (cons (org-element-property :title entry)
-                                    (org-element-contents inside))
-                              'diary-sexp
-                            (lambda (sexp)
-                              (org-icalendar-transcode-diary-sexp
-                               (org-element-property :value sexp)
-                               (format "DS%d-%s" (incf counter) uid)
-                               summary))
-                            info nil (and (eq type 'headline) 'inlinetask))
-                          ""))))))
+             (mapconcat #'identity
+                        (org-element-map
+                            (cons (org-element-property :title entry)
+                                  (org-element-contents inside))
+                            'diary-sexp
+                          (lambda (sexp)
+                            (org-icalendar-transcode-diary-sexp
+                             (org-element-property :value sexp)
+                             (format "DS%d-%s" (cl-incf counter) uid)
+                             summary))
+                          info nil (and (eq type 'headline) 'inlinetask))
+                        "")))))
        ;; If ENTRY is a headline, call current function on every
        ;; inlinetask within it.  In agenda export, this is independent
        ;; from the mark (or lack thereof) on the entry.
@@ -627,7 +626,7 @@ inlinetask within the section."
        contents))))
 
 (defun org-icalendar--vevent
-  (entry timestamp uid summary location description categories)
+    (entry timestamp uid summary location description categories)
   "Create a VEVENT component.
 
 ENTRY is either a headline or an inlinetask element.  TIMESTAMP
@@ -651,7 +650,7 @@ Return VEVENT component as a string."
             ;; RRULE.
             (when (org-element-property :repeater-type timestamp)
               (format "RRULE:FREQ=%s;INTERVAL=%d\n"
-                      (case (org-element-property :repeater-unit timestamp)
+                      (cl-case (org-element-property :repeater-unit timestamp)
                         (hour "HOURLY") (day "DAILY") (week "WEEKLY")
                         (month "MONTHLY") (year "YEARLY"))
                       (org-element-property :repeater-value timestamp)))
@@ -821,7 +820,8 @@ Return ICS file name."
   ;; links will not be collected at the end of sections.
   (let ((outfile (org-export-output-file-name ".ics" subtreep)))
     (org-export-to-file 'icalendar outfile
-      async subtreep visible-only body-only '(:ascii-charset utf-8)
+      async subtreep visible-only body-only
+      '(:ascii-charset utf-8 :ascii-links-to-notes nil)
       (lambda (file)
        (run-hook-with-args 'org-icalendar-after-save-hook file) nil))))
 
@@ -835,27 +835,23 @@ external process."
       ;; Asynchronous export is not interactive, so we will not call
       ;; `org-check-agenda-file'.  Instead we remove any non-existent
       ;; agenda file from the list.
-      (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t))))
+      (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t))))
        (org-export-async-start
            (lambda (results)
-             (mapc (lambda (f) (org-export-add-to-stack f 'icalendar))
-                   results))
+             (dolist (f results) (org-export-add-to-stack f 'icalendar)))
          `(let (output-files)
-            (mapc (lambda (file)
-                    (with-current-buffer (org-get-agenda-file-buffer file)
-                      (push (expand-file-name (org-icalendar-export-to-ics))
-                            output-files)))
-                  ',files)
-            output-files)))
+            (dolist (file ',files outputfiles)
+              (with-current-buffer (org-get-agenda-file-buffer file)
+                (push (expand-file-name (org-icalendar-export-to-ics))
+                      output-files))))))
     (let ((files (org-agenda-files t)))
       (org-agenda-prepare-buffers files)
       (unwind-protect
-         (mapc (lambda (file)
-                 (catch 'nextfile
-                   (org-check-agenda-file file)
-                   (with-current-buffer (org-get-agenda-file-buffer file)
-                     (org-icalendar-export-to-ics))))
-               files)
+         (dolist (file files)
+           (catch 'nextfile
+             (org-check-agenda-file file)
+             (with-current-buffer (org-get-agenda-file-buffer file)
+               (org-icalendar-export-to-ics))))
        (org-release-buffers org-agenda-new-buffers)))))
 
 ;;;###autoload
@@ -870,56 +866,52 @@ The file is stored under the name chosen in
 `org-icalendar-combined-agenda-file'."
   (interactive)
   (if async
-      (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t))))
+      (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t))))
        (org-export-async-start
-           (lambda (dummy)
+           (lambda (_)
              (org-export-add-to-stack
               (expand-file-name org-icalendar-combined-agenda-file)
               'icalendar))
-         `(apply 'org-icalendar--combine-files nil ',files)))
-    (apply 'org-icalendar--combine-files nil (org-agenda-files t))))
+         `(apply #'org-icalendar--combine-files ',files)))
+    (apply #'org-icalendar--combine-files (org-agenda-files t))))
 
 (defun org-icalendar-export-current-agenda (file)
   "Export current agenda view to an iCalendar FILE.
 This function assumes major mode for current buffer is
 `org-agenda-mode'."
-  (let (org-export-babel-evaluate ; Don't evaluate Babel block
-       (org-icalendar-combined-agenda-file file)
-       (marker-list
-        ;; Collect the markers pointing to entries in the current
-        ;; agenda buffer.
-        (let (markers)
-          (save-excursion
-            (goto-char (point-min))
-            (while (not (eobp))
-              (let ((m (or (org-get-at-bol 'org-hd-marker)
-                           (org-get-at-bol 'org-marker))))
-                (and m (push m markers)))
-              (beginning-of-line 2)))
-          (nreverse markers))))
-    (apply 'org-icalendar--combine-files
-          ;; Build restriction alist.
-          (let (restriction)
-            ;; Sort markers in each association within RESTRICTION.
-            (mapcar (lambda (x) (setcdr x (sort (copy-sequence (cdr x)) '<)) x)
-                    (dolist (m marker-list restriction)
-                      (let* ((pos (marker-position m))
-                             (file (buffer-file-name
-                                    (org-base-buffer (marker-buffer m))))
-                             (file-markers (assoc file restriction)))
-                        ;; Add POS in FILE association if one exists
-                        ;; or create a new association for FILE.
-                        (if file-markers (push pos (cdr file-markers))
-                          (push (list file pos) restriction))))))
-          (org-agenda-files nil 'ifmode))))
-
-(defun org-icalendar--combine-files (restriction &rest files)
+  (let* ((org-export-babel-evaluate)   ; Don't evaluate Babel block.
+        (contents
+         (org-export-string-as
+          (with-output-to-string
+            (save-excursion
+              (let ((p (point-min)))
+                (while (setq p (next-single-property-change p 'org-hd-marker))
+                  (let ((m (get-text-property p 'org-hd-marker)))
+                    (when m
+                      (with-current-buffer (marker-buffer m)
+                        (org-with-wide-buffer
+                         (goto-char (marker-position m))
+                         (princ
+                          (org-element-normalize-string
+                           (buffer-substring
+                            (point) (progn (outline-next-heading) 
(point)))))))))
+                  (forward-line)))))
+          'icalendar t
+          '(:ascii-charset utf-8 :ascii-links-to-notes nil
+                           :icalendar-include-todo all))))
+    (with-temp-file file
+      (insert
+       (org-icalendar--vcalendar
+       org-icalendar-combined-name
+       user-full-name
+       (or (org-string-nw-p org-icalendar-timezone) (cadr (current-time-zone)))
+       org-icalendar-combined-description
+       contents)))
+    (run-hook-with-args 'org-icalendar-after-save-hook file)))
+
+(defun org-icalendar--combine-files (&rest files)
   "Combine entries from multiple files into an iCalendar file.
-RESTRICTION, when non-nil, is an alist where key is a file name
-and value a list of buffer positions pointing to entries that
-should appear in the calendar.  It only makes sense if the
-function was called from an agenda buffer.  FILES is a list of
-files to build the calendar from."
+FILES is a list of files to build the calendar from."
   (org-agenda-prepare-buffers files)
   (unwind-protect
       (progn
@@ -943,29 +935,12 @@ files to build the calendar from."
                (catch 'nextfile
                  (org-check-agenda-file file)
                  (with-current-buffer (org-get-agenda-file-buffer file)
-                   (let ((marks (cdr (assoc (expand-file-name file)
-                                            restriction))))
-                     ;; Create ID if necessary.
-                     (when org-icalendar-store-UID
-                       (org-icalendar-create-uid file t marks))
-                     (unless (and restriction (not marks))
-                       ;; Add a hook adding :ICALENDAR_MARK: property
-                       ;; to each entry appearing in agenda view.
-                       ;; Use `apply-partially' because the function
-                       ;; still has to accept one argument.
-                       (let ((org-export-before-processing-hook
-                              (cons (apply-partially
-                                     (lambda (m-list dummy)
-                                       (mapc (lambda (m)
-                                               (org-entry-put
-                                                m "ICALENDAR-MARK" "t"))
-                                             m-list))
-                                     (sort marks '>))
-                                    org-export-before-processing-hook)))
-                         (org-export-as
-                          'icalendar nil nil t
-                          (list :ascii-charset 'utf-8
-                                :icalendar-agenda-view restriction))))))))
+                   ;; Create ID if necessary.
+                   (when org-icalendar-store-UID
+                     (org-icalendar-create-uid file t))
+                   (org-export-as
+                    'icalendar nil nil t
+                    '(:ascii-charset utf-8 :ascii-links-to-notes nil)))))
              files "")
             ;; BBDB anniversaries.
             (when (and org-icalendar-include-bbdb-anniversaries
diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el
index 3eee86a..f11a8a6 100644
--- a/lisp/org/ox-latex.el
+++ b/lisp/org/ox-latex.el
@@ -1,4 +1,4 @@
-;;; ox-latex.el --- LaTeX Back-End for Org Export Engine
+;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -26,7 +26,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'ox)
 (require 'ox-publish)
 
@@ -43,8 +43,6 @@
     (center-block . org-latex-center-block)
     (clock . org-latex-clock)
     (code . org-latex-code)
-    (comment . (lambda (&rest args) ""))
-    (comment-block . (lambda (&rest args) ""))
     (drawer . org-latex-drawer)
     (dynamic-block . org-latex-dynamic-block)
     (entity . org-latex-entity)
@@ -65,13 +63,13 @@
     (latex-fragment . org-latex-latex-fragment)
     (line-break . org-latex-line-break)
     (link . org-latex-link)
+    (node-property . org-latex-node-property)
     (paragraph . org-latex-paragraph)
     (plain-list . org-latex-plain-list)
     (plain-text . org-latex-plain-text)
     (planning . org-latex-planning)
-    (property-drawer . (lambda (&rest args) ""))
+    (property-drawer . org-latex-property-drawer)
     (quote-block . org-latex-quote-block)
-    (quote-section . org-latex-quote-section)
     (radio-target . org-latex-radio-target)
     (section . org-latex-section)
     (special-block . org-latex-special-block)
@@ -88,8 +86,10 @@
     (timestamp . org-latex-timestamp)
     (underline . org-latex-underline)
     (verbatim . org-latex-verbatim)
-    (verse-block . org-latex-verse-block))
-  :export-block '("LATEX" "TEX")
+    (verse-block . org-latex-verse-block)
+    ;; Pseudo objects and elements.
+    (latex-math-block . org-latex-math-block)
+    (latex-matrices . org-latex-matrices))
   :menu-entry
   '(?l "Export to LaTeX"
        ((?L "As LaTeX buffer" org-latex-export-as-latex)
@@ -99,13 +99,57 @@
            (lambda (a s v b)
              (if a (org-latex-export-to-pdf t s v b)
                (org-open-file (org-latex-export-to-pdf nil s v b)))))))
-  :options-alist '((:latex-class "LATEX_CLASS" nil org-latex-default-class t)
-                  (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t)
-                  (:latex-header "LATEX_HEADER" nil nil newline)
-                  (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline)
-                  (:latex-hyperref-p nil "texht" org-latex-with-hyperref t)
-                  ;; Redefine regular options.
-                  (:date "DATE" nil "\\today" t)))
+  :filters-alist '((:filter-options . org-latex-math-block-options-filter)
+                  (:filter-paragraph . org-latex-clean-invalid-line-breaks)
+                  (:filter-parse-tree org-latex-math-block-tree-filter
+                                      org-latex-matrices-tree-filter)
+                  (:filter-verse-block . org-latex-clean-invalid-line-breaks))
+  :options-alist
+  '((:latex-class "LATEX_CLASS" nil org-latex-default-class t)
+    (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t)
+    (:latex-header "LATEX_HEADER" nil nil newline)
+    (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline)
+    (:description "DESCRIPTION" nil nil parse)
+    (:keywords "KEYWORDS" nil nil parse)
+    (:subtitle "SUBTITLE" nil nil parse)
+    ;; Other variables.
+    (:latex-active-timestamp-format nil nil org-latex-active-timestamp-format)
+    (:latex-caption-above nil nil org-latex-caption-above)
+    (:latex-classes nil nil org-latex-classes)
+    (:latex-default-figure-position nil nil org-latex-default-figure-position)
+    (:latex-default-table-environment nil nil 
org-latex-default-table-environment)
+    (:latex-default-table-mode nil nil org-latex-default-table-mode)
+    (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format)
+    (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format)
+    (:latex-footnote-separator nil nil org-latex-footnote-separator)
+    (:latex-format-drawer-function nil nil org-latex-format-drawer-function)
+    (:latex-format-headline-function nil nil 
org-latex-format-headline-function)
+    (:latex-format-inlinetask-function nil nil 
org-latex-format-inlinetask-function)
+    (:latex-hyperref-template nil nil org-latex-hyperref-template t)
+    (:latex-image-default-height nil nil org-latex-image-default-height)
+    (:latex-image-default-option nil nil org-latex-image-default-option)
+    (:latex-image-default-width nil nil org-latex-image-default-width)
+    (:latex-images-centered nil nil org-latex-images-centered)
+    (:latex-inactive-timestamp-format nil nil 
org-latex-inactive-timestamp-format)
+    (:latex-inline-image-rules nil nil org-latex-inline-image-rules)
+    (:latex-link-with-unknown-path-format nil nil 
org-latex-link-with-unknown-path-format)
+    (:latex-listings nil nil org-latex-listings)
+    (:latex-listings-langs nil nil org-latex-listings-langs)
+    (:latex-listings-options nil nil org-latex-listings-options)
+    (:latex-minted-langs nil nil org-latex-minted-langs)
+    (:latex-minted-options nil nil org-latex-minted-options)
+    (:latex-prefer-user-labels nil nil org-latex-prefer-user-labels)
+    (:latex-subtitle-format nil nil org-latex-subtitle-format)
+    (:latex-subtitle-separate nil nil org-latex-subtitle-separate)
+    (:latex-table-scientific-notation nil nil 
org-latex-table-scientific-notation)
+    (:latex-tables-booktabs nil nil org-latex-tables-booktabs)
+    (:latex-tables-centered nil nil org-latex-tables-centered)
+    (:latex-text-markup-alist nil nil org-latex-text-markup-alist)
+    (:latex-title-command nil nil org-latex-title-command)
+    (:latex-toc-command nil nil org-latex-toc-command)
+    (:latex-compiler "LATEX_COMPILER" nil org-latex-compiler)
+    ;; Redefine regular options.
+    (:date "DATE" nil "\\today" parse)))
 
 
 
@@ -164,11 +208,112 @@
     ("uk" . "ukrainian"))
   "Alist between language code and corresponding Babel option.")
 
+(defconst org-latex-polyglossia-language-alist
+  '(("am" "amharic")
+    ("ast" "asturian")
+    ("ar" "arabic")
+    ("bo" "tibetan")
+    ("bn" "bengali")
+    ("bg" "bulgarian")
+    ("br" "breton")
+    ("bt-br" "brazilian")
+    ("ca" "catalan")
+    ("cop" "coptic")
+    ("cs" "czech")
+    ("cy" "welsh")
+    ("da" "danish")
+    ("de" "german" "german")
+    ("de-at" "german" "austrian")
+    ("de-de" "german" "german")
+    ("dv" "divehi")
+    ("el" "greek")
+    ("en" "english" "usmax")
+    ("en-au" "english" "australian")
+    ("en-gb" "english" "uk")
+    ("en-nz" "english" "newzealand")
+    ("en-us" "english" "usmax")
+    ("eo" "esperanto")
+    ("es" "spanish")
+    ("et" "estonian")
+    ("eu" "basque")
+    ("fa" "farsi")
+    ("fi" "finnish")
+    ("fr" "french")
+    ("fu" "friulan")
+    ("ga" "irish")
+    ("gd" "scottish")
+    ("gl" "galician")
+    ("he" "hebrew")
+    ("hi" "hindi")
+    ("hr" "croatian")
+    ("hu" "magyar")
+    ("hy" "armenian")
+    ("id" "bahasai")
+    ("ia" "interlingua")
+    ("is" "icelandic")
+    ("it" "italian")
+    ("kn" "kannada")
+    ("la" "latin" "modern")
+    ("la-modern" "latin" "modern")
+    ("la-classic" "latin" "classic")
+    ("la-medieval" "latin" "medieval")
+    ("lo" "lao")
+    ("lt" "lithuanian")
+    ("lv" "latvian")
+    ("mr" "maranthi")
+    ("ml" "malayalam")
+    ("nl" "dutch")
+    ("nb" "norsk")
+    ("nn" "nynorsk")
+    ("nko" "nko")
+    ("no" "norsk")
+    ("oc" "occitan")
+    ("pl" "polish")
+    ("pms" "piedmontese")
+    ("pt" "portuges")
+    ("rm" "romansh")
+    ("ro" "romanian")
+    ("ru" "russian")
+    ("sa" "sanskrit")
+    ("hsb" "usorbian")
+    ("dsb" "lsorbian")
+    ("sk" "slovak")
+    ("sl" "slovenian")
+    ("se" "samin")
+    ("sq" "albanian")
+    ("sr" "serbian")
+    ("sv" "swedish")
+    ("syr" "syriac")
+    ("ta" "tamil")
+    ("te" "telugu")
+    ("th" "thai")
+    ("tk" "turkmen")
+    ("tr" "turkish")
+    ("uk" "ukrainian")
+    ("ur" "urdu")
+    ("vi" "vietnamese"))
+  "Alist between language code and corresponding Polyglossia option")
+
+
+
 (defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr")
-                                           ("qbordermatrix" . "\\cr")
-                                           ("kbordermatrix" . "\\\\"))
+                                         ("qbordermatrix" . "\\cr")
+                                         ("kbordermatrix" . "\\\\"))
   "Alist between matrix macros and their row ending.")
 
+(defconst org-latex-math-environments-re
+  (format
+   "\\`[ \t]*\\\\begin{%s\\*?}"
+   (regexp-opt
+          '("equation" "eqnarray" "math" "displaymath"
+            "align"  "gather" "multline" "flalign"  "alignat"
+            "xalignat" "xxalignat"
+            "subequations"
+            ;; breqn
+            "dmath" "dseries" "dgroup" "darray"
+            ;; empheq
+            "empheq")))
+  "Regexp of LaTeX math environments.")
 
 
 ;;; User Configurable Variables
@@ -178,6 +323,79 @@
   :tag "Org Export LaTeX"
   :group 'org-export)
 
+;;;; Generic
+
+(defcustom org-latex-caption-above '(table)
+  "When non-nil, place caption string at the beginning of elements.
+Otherwise, place it near the end.  When value is a list of
+symbols, put caption above selected elements only.  Allowed
+symbols are: `image', `table', `src-block' and `special-block'."
+  :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice
+         (const :tag "For all elements" t)
+         (const :tag "For no element" nil)
+         (set :tag "For the following elements only" :greedy t
+              (const :tag "Images" image)
+              (const :tag "Tables" table)
+              (const :tag "Source code" src-block)
+              (const :tag "Special blocks" special-block))))
+
+(defcustom org-latex-prefer-user-labels nil
+   "Use user-provided labels instead of internal ones when non-nil.
+
+When this variable is non-nil, Org will use the value of
+CUSTOM_ID property, NAME keyword or Org target as the key for the
+\\label commands generated.
+
+By default, Org generates its own internal labels during LaTeX
+export.  This process ensures that the \\label keys are unique
+and valid, but it means the keys are not available in advance of
+the export process.
+
+Setting this variable gives you control over how Org generates
+labels during LaTeX export, so that you may know their keys in
+advance.  One reason to do this is that it allows you to refer to
+various elements using a single label both in Org's link syntax
+and in embedded LaTeX code.
+
+For example, when this variable is non-nil, a headline like this:
+
+  ** Some section
+     :PROPERTIES:
+     :CUSTOM_ID: sec:foo
+     :END:
+  This is section [[#sec:foo]].
+  #+BEGIN_EXPORT latex
+  And this is still section \\ref{sec:foo}.
+  #+END_EXPORT
+
+will be exported to LaTeX as:
+
+  \\subsection{Some section}
+  \\label{sec:foo}
+  This is section \\ref{sec:foo}.
+  And this is still section \\ref{sec:foo}.
+
+Note, however, that setting this variable introduces a limitation
+on the possible values for CUSTOM_ID and NAME.  When this
+variable is non-nil, Org passes their value to \\label unchanged.
+You are responsible for ensuring that the value is a valid LaTeX
+\\label key, and that no other \\label commands with the same key
+appear elsewhere in your document.  (Keys may contain letters,
+numbers, and the following punctuation: '_' '.'  '-' ':'.)  There
+are no such limitations on CUSTOM_ID and NAME when this variable
+is nil.
+
+For headlines that do not define the CUSTOM_ID property or
+elements without a NAME, Org will continue to use its default
+labeling scheme to generate labels and resolve links into proper
+references."
+  :group 'org-export-latex
+  :type 'boolean
+  :version "26.1"
+  :package-version '(Org . "8.3"))
 
 ;;;; Preamble
 
@@ -264,11 +482,15 @@ AUTO will automatically be replaced with a coding system 
derived
 from `buffer-file-coding-system'.  See also the variable
 `org-latex-inputenc-alist' for a way to influence this mechanism.
 
-Likewise, if your header contains \"\\usepackage[AUTO]{babel}\",
-AUTO will be replaced with the language related to the language
-code specified by `org-export-default-language', which see.  Note
-that constructions such as \"\\usepackage[french,AUTO,english]{babel}\"
-are permitted.
+Likewise, if your header contains \"\\usepackage[AUTO]{babel}\"
+or \"\\usepackage[AUTO]{polyglossia}\", AUTO will be replaced
+with the language related to the language code specified by
+`org-export-default-language'.  Note that constructions such as
+\"\\usepackage[french,AUTO,english]{babel}\" are permitted.  For
+Polyglossia the language will be set via the macros
+\"\\setmainlanguage\" and \"\\setotherlanguage\".  See also
+`org-latex-guess-babel-language' and
+`org-latex-guess-polyglossia-language'.
 
 The sectioning structure
 ------------------------
@@ -328,11 +550,42 @@ are written as utf8 files."
 
 (defcustom org-latex-title-command "\\maketitle"
   "The command used to insert the title just after \\begin{document}.
-If this string contains the formatting specification \"%s\" then
-it will be used as a formatting string, passing the title as an
-argument."
+
+This format string may contain these elements:
+
+  %a for AUTHOR keyword
+  %t for TITLE keyword
+  %s for SUBTITLE keyword
+  %k for KEYWORDS line
+  %d for DESCRIPTION line
+  %c for CREATOR line
+  %l for Language keyword
+  %L for capitalized language keyword
+  %D for DATE keyword
+
+If you need to use a \"%\" character, you need to escape it
+like that: \"%%\".
+
+Setting :latex-title-command in publishing projects will take
+precedence over this variable."
   :group 'org-export-latex
-  :type 'string)
+  :type '(string :tag "Format string"))
+
+(defcustom org-latex-subtitle-format "\\\\\\medskip\n\\large %s"
+  "Format string used for transcoded subtitle.
+The format string should have at most one \"%s\"-expression,
+which is replaced with the subtitle."
+  :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(string :tag "Format string"))
+
+(defcustom org-latex-subtitle-separate nil
+  "Non-nil means the subtitle is not typeset as part of title."
+  :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean)
 
 (defcustom org-latex-toc-command "\\tableofcontents\n\n"
   "LaTeX command to set the table of contents, list of figures, etc.
@@ -341,10 +594,36 @@ the toc:nil option, not to those generated with #+TOC 
keyword."
   :group 'org-export-latex
   :type 'string)
 
-(defcustom org-latex-with-hyperref t
-  "Toggle insertion of \\hypersetup{...} in the preamble."
+(defcustom org-latex-hyperref-template
+  "\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k},
+ pdfsubject={%d},\n pdfcreator={%c}, \n pdflang={%L}}\n"
+  "Template for hyperref package options.
+
+This format string may contain these elements:
+
+  %a for AUTHOR keyword
+  %t for TITLE keyword
+  %s for SUBTITLE keyword
+  %k for KEYWORDS line
+  %d for DESCRIPTION line
+  %c for CREATOR line
+  %l for Language keyword
+  %L for capitalized language keyword
+  %D for DATE keyword
+
+If you need to use a \"%\" character, you need to escape it
+like that: \"%%\".
+
+As a special case, a nil value prevents template from being
+inserted.
+
+Setting :latex-hyperref-template in publishing projects will take
+precedence over this variable."
   :group 'org-export-latex
-  :type 'boolean)
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type '(choice (const :tag "No template" nil)
+                (string :tag "Format string")))
 
 ;;;; Headline
 
@@ -352,17 +631,15 @@ the toc:nil option, not to those generated with #+TOC 
keyword."
   'org-latex-format-headline-default-function
   "Function for formatting the headline's text.
 
-This function will be called with 5 arguments:
-TODO      the todo keyword (string or nil).
+This function will be called with six arguments:
+TODO      the todo keyword (string or nil)
 TODO-TYPE the type of todo (symbol: `todo', `done', nil)
 PRIORITY  the priority of the headline (integer or nil)
-TEXT      the main headline text (string).
-TAGS      the tags as a list of strings (list of strings or nil).
-
-The function result will be used in the section format string.
+TEXT      the main headline text (string)
+TAGS      the tags (list of strings or nil)
+INFO      the export options (plist)
 
-Use `org-latex-format-headline-default-function' by default,
-which format headlines like for Org version prior to 8.0."
+The function result will be used in the section format string."
   :group 'org-export-latex
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -376,6 +653,16 @@ which format headlines like for Org version prior to 8.0."
   :group 'org-export-latex
   :type 'string)
 
+(defcustom org-latex-footnote-defined-format "\\textsuperscript{\\ref{%s}}"
+  "Format string used to format reference to footnote already defined.
+%s will be replaced by the label of the referred footnote."
+  :group 'org-export-latex
+  :type '(choice
+         (const :tag "Use plain superscript (default)" 
"\\textsuperscript{\\ref{%s}}")
+         (const :tag "Use Memoir/KOMA-Script footref" "\\footref{%s}")
+         (string :tag "Other format string"))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
 
 ;;;; Timestamps
 
@@ -397,6 +684,14 @@ which format headlines like for Org version prior to 8.0."
 
 ;;;; Links
 
+(defcustom org-latex-images-centered t
+  "When non-nil, images are centered."
+  :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type 'boolean
+  :safe #'booleanp)
+
 (defcustom org-latex-image-default-option ""
   "Default option for images."
   :group 'org-export-latex
@@ -422,10 +717,13 @@ environment."
   :package-version '(Org . "8.0")
   :type 'string)
 
-(defcustom org-latex-default-figure-position "htb"
-  "Default position for latex figures."
+(defcustom org-latex-default-figure-position "htbp"
+  "Default position for LaTeX figures."
   :group 'org-export-latex
-  :type 'string)
+  :type 'string
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :safe #'stringp)
 
 (defcustom org-latex-inline-image-rules
   '(("file" . 
"\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\|tikz\\|pgf\\|svg\\)\\'"))
@@ -489,12 +787,14 @@ When modifying this variable, it may be useful to change
   :type '(choice (const :tag "Table" table)
                 (const :tag "Matrix" math)
                 (const :tag "Inline matrix" inline-math)
-                (const :tag "Verbatim" verbatim)))
+                (const :tag "Verbatim" verbatim))
+  :safe (lambda (s) (memq s '(table math inline-math verbatim))))
 
 (defcustom org-latex-tables-centered t
   "When non-nil, tables are exported in a center environment."
   :group 'org-export-latex
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-latex-tables-booktabs nil
   "When non-nil, display tables in a formal \"booktabs\" style.
@@ -505,13 +805,8 @@ attributes."
   :group 'org-export-latex
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'boolean)
-
-(defcustom org-latex-table-caption-above t
-  "When non-nil, place caption string at the beginning of the table.
-Otherwise, place it near the end."
-  :group 'org-export-latex
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-latex-table-scientific-notation "%s\\,(%s)"
   "Format string to display numbers in scientific notation.
@@ -526,11 +821,10 @@ When nil, no transformation is made."
          (string :tag "Format string")
          (const :tag "No formatting" nil)))
 
-
 ;;;; Text markup
 
 (defcustom org-latex-text-markup-alist '((bold . "\\textbf{%s}")
-                                        (code . verb)
+                                        (code . protectedtexttt)
                                         (italic . "\\emph{%s}")
                                         (strike-through . "\\sout{%s}")
                                         (underline . "\\uline{%s}")
@@ -550,14 +844,15 @@ to typeset and try to protect special characters.
 If no association can be found for a given markup, text will be
 returned as-is."
   :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type 'alist
   :options '(bold code italic strike-through underline verbatim))
 
 
 ;;;; Drawers
 
-(defcustom org-latex-format-drawer-function
-  (lambda (name contents) contents)
+(defcustom org-latex-format-drawer-function (lambda (_ contents) contents)
   "Function called to format a drawer in LaTeX code.
 
 The function must accept two parameters:
@@ -575,44 +870,24 @@ The default function simply returns the value of 
CONTENTS."
 
 ;;;; Inlinetasks
 
-(defcustom org-latex-format-inlinetask-function 'ignore
+(defcustom org-latex-format-inlinetask-function
+  'org-latex-format-inlinetask-default-function
   "Function called to format an inlinetask in LaTeX code.
 
-The function must accept six parameters:
-  TODO      the todo keyword, as a string
-  TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
-  PRIORITY  the inlinetask priority, as a string
-  NAME      the inlinetask name, as a string.
-  TAGS      the inlinetask tags, as a list of strings.
-  CONTENTS  the contents of the inlinetask, as a string.
-
-The function should return the string to be exported.
+The function must accept seven parameters:
+  TODO      the todo keyword (string or nil)
+  TODO-TYPE the todo type (symbol: `todo', `done', nil)
+  PRIORITY  the inlinetask priority (integer or nil)
+  NAME      the inlinetask name (string)
+  TAGS      the inlinetask tags (list of strings or nil)
+  CONTENTS  the contents of the inlinetask (string or nil)
+  INFO      the export options (plist)
 
-For example, the variable could be set to the following function
-in order to mimic default behavior:
-
-\(defun org-latex-format-inlinetask (todo type priority name tags contents)
-\"Format an inline task element for LaTeX export.\"
-  (let ((full-title
-        (concat
-         (when todo
-            (format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo))
-         (when priority (format \"\\\\framebox{\\\\#%c} \" priority))
-         title
-         (when tags
-            (format \"\\\\hfill{}\\\\textsc{:%s:}\"
-                    (mapconcat \\='identity tags \":\")))))
-    (format (concat \"\\\\begin{center}\\n\"
-                   \"\\\\fbox{\\n\"
-                   \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
-                   \"%s\\n\\n\"
-                   \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
-                   \"%s\"
-                   \"\\\\end{minipage}}\"
-                   \"\\\\end{center}\")
-           full-title contents))"
+The function should return the string to be exported."
   :group 'org-export-latex
-  :type 'function)
+  :type 'function
+  :version "26.1"
+  :package-version '(Org . "8.3"))
 
 
 ;; Src blocks
@@ -640,7 +915,7 @@ the minted package to `org-latex-packages-alist', for 
example
 using customize, or with
 
   (require \\='ox-latex)
-  (add-to-list \\='org-latex-packages-alist \\='(\"\" \"minted\"))
+  (add-to-list \\='org-latex-packages-alist \\='(\"newfloat\" \"minted\"))
 
 In addition, it is necessary to install pygments
 \(http://pygments.org), and to configure the variable
@@ -656,7 +931,8 @@ into previewing problems, please consult
   :type '(choice
          (const :tag "Use listings" t)
          (const :tag "Use minted" minted)
-         (const :tag "Export verbatim" nil)))
+         (const :tag "Export verbatim" nil))
+  :safe (lambda (s) (memq s '(t nil minted))))
 
 (defcustom org-latex-listings-langs
   '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp")
@@ -668,7 +944,9 @@ into previewing problems, please consult
     (shell-script "bash")
     (gnuplot "Gnuplot")
     (ocaml "Caml") (caml "Caml")
-    (sql "SQL") (sqlite "sql"))
+    (sql "SQL") (sqlite "sql")
+    (makefile "make")
+    (R "r"))
   "Alist mapping languages to their listing language counterpart.
 The key is a symbol, the major mode symbol without the \"-mode\".
 The value is the string that should be inserted as the language
@@ -676,6 +954,8 @@ parameter for the listings package.  If the mode name and 
the
 listings name are the same, the language does not need an entry
 in this list - but it does not hurt if it is present."
   :group 'org-export-latex
+  :version "24.4"
+  :package-version '(Org . "8.3")
   :type '(repeat
          (list
           (symbol :tag "Major mode       ")
@@ -697,7 +977,13 @@ will typeset the code in a small size font with 
underlined, bold
 black keywords.
 
 Note that the same options will be applied to blocks of all
-languages."
+languages.  If you need block-specific options, you may use the
+following syntax:
+
+  #+ATTR_LATEX: :options key1=value1,key2=value2
+  #+BEGIN_SRC <LANG>
+  ...
+  #+END_SRC"
   :group 'org-export-latex
   :type '(repeat
          (list
@@ -744,41 +1030,132 @@ will result in src blocks being exported with
 \\begin{minted}[bgcolor=bg,frame=lines]{<LANG>}
 
 as the start of the minted environment. Note that the same
-options will be applied to blocks of all languages."
+options will be applied to blocks of all languages.  If you need
+block-specific options, you may use the following syntax:
+
+  #+ATTR_LATEX: :options key1=value1,key2=value2
+  #+BEGIN_SRC <LANG>
+  ...
+  #+END_SRC"
   :group 'org-export-latex
   :type '(repeat
          (list
           (string :tag "Minted option name ")
           (string :tag "Minted option value"))))
 
-(defvar org-latex-custom-lang-environments nil
+(defcustom org-latex-custom-lang-environments nil
   "Alist mapping languages to language-specific LaTeX environments.
 
 It is used during export of src blocks by the listings and minted
-latex packages.  For example,
+latex packages.  The environment may be a simple string, composed of
+only letters and numbers.  In this case, the string is directly the
+name of the latex environment to use.  The environment may also be
+a format string.  In this case the format string will be directly
+exported.  This format string may contain these elements:
+
+  %s for the formatted source
+  %c for the caption
+  %f for the float attribute
+  %l for an appropriate label
+  %o for the LaTeX attributes
+
+For example,
 
   (setq org-latex-custom-lang-environments
-     \\='((python \"pythoncode\")))
+     \\='((python \"pythoncode\")
+       (ocaml \"\\\\begin{listing}
+\\\\begin{minted}[%o]{ocaml}
+%s\\\\end{minted}
+\\\\caption{%c}
+\\\\label{%l}\")))
 
-would have the effect that if org encounters begin_src python
-during latex export it will output
+would have the effect that if Org encounters a Python source block
+during LaTeX export it will produce
 
   \\begin{pythoncode}
   <src block body>
-  \\end{pythoncode}")
+  \\end{pythoncode}
+
+and if Org encounters an Ocaml source block during LaTeX export it
+will produce
+
+  \\begin{listing}
+  \\begin{minted}[<attr_latex options>]{ocaml}
+  <src block body>
+  \\end{minted}
+  \\caption{<caption>}
+  \\label{<label>}
+  \\end{listing}"
+  :group 'org-export-latex
+  :type '(repeat
+         (list
+          (symbol :tag "Language name                    ")
+          (string :tag "Environment name or format string")))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
 
 
 ;;;; Compilation
 
+(defcustom org-latex-compiler-file-string "%% Intended LaTeX compiler: %s\n"
+  "LaTeX compiler format-string.
+See also `org-latex-compiler'."
+  :group 'org-export-latex
+  :type '(choice
+         (const :tag "Comment" "%% Intended LaTeX compiler: %s\n")
+         (const :tag "latex-mode file variable" "%% -*- latex-run-command: %s 
-*-\n")
+         (const :tag "AUCTeX file variable" "%% -*- LaTeX-command: %s -*-\n")
+         (string :tag "custom format" "%% %s"))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
+
+(defcustom org-latex-compiler "pdflatex"
+  "LaTeX compiler to use.
+
+Must be an element in `org-latex-compilers' or the empty quote.
+Can also be set in buffers via #+LATEX_COMPILER.  See also
+`org-latex-compiler-file-string'."
+  :group 'org-export-latex
+  :type '(choice
+         (const :tag "pdfLaTeX" "pdflatex")
+         (const :tag "XeLaTeX"  "xelatex")
+         (const :tag "LuaLaTeX" "lualatex")
+         (const :tag "Unset" ""))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
+
+(defconst org-latex-compilers '("pdflatex" "xelatex" "lualatex")
+  "Known LaTeX compilers.
+See also `org-latex-compiler'.")
+
+(defcustom org-latex-bib-compiler "bibtex"
+  "Command to process a LaTeX file's bibliography.
+
+The shorthand %bib in `org-latex-pdf-process' is replaced with
+this value.
+
+A better approach is to use a compiler suit such as `latexmk'."
+  :group 'org-export-latex
+  :type '(choice (const :tag "BibTeX" "bibtex")
+                (const :tag "Biber" "biber")
+                (string :tag "Other process"))
+  :version "26.1"
+  :package-version '(Org . "9.0"))
+
 (defcustom org-latex-pdf-process
-  '("pdflatex -interaction nonstopmode -output-directory %o %f"
-    "pdflatex -interaction nonstopmode -output-directory %o %f"
-    "pdflatex -interaction nonstopmode -output-directory %o %f")
+  '("%latex -interaction nonstopmode -output-directory %o %f"
+    "%latex -interaction nonstopmode -output-directory %o %f"
+    "%latex -interaction nonstopmode -output-directory %o %f")
   "Commands to process a LaTeX file to a PDF file.
+
 This is a list of strings, each of them will be given to the
 shell as a command.  %f in the command will be replaced by the
-full file name, %b by the file base name (i.e. without directory
-and extension parts) and %o by the base directory of the file.
+relative file name, %F by the absolute file name, %b by the file
+base name (i.e. without directory and extension parts), %o by the
+base directory of the file, %O by the absolute file name of the
+output file, %latex is the LaTeX compiler (see
+`org-latex-compiler'), and %bib is the BibTeX-like compiler (see
+`org-latex-bib-compiler').
 
 The reason why this is a list is that it usually takes several
 runs of `pdflatex', maybe mixed with a call to `bibtex'.  Org
@@ -786,18 +1163,8 @@ does not have a clever mechanism to detect which of these
 commands have to be run to get to a stable result, and it also
 does not do any error checking.
 
-By default, Org uses 3 runs of `pdflatex' to do the processing.
-If you have texi2dvi on your system and if that does not cause
-the infamous egrep/locale bug:
-
-     http://lists.gnu.org/archive/html/bug-texinfo/2010-03/msg00031.html
-
-then `texi2dvi' is the superior choice as it automates the LaTeX
-build process by calling the \"correct\" combinations of
-auxiliary programs.  Org does offer `texi2dvi' as one of the
-customize options.  Alternatively, `rubber' and `latexmk' also
-provide similar functionality.  The latter supports `biber' out
-of the box.
+Consider a smart LaTeX compiler such as `texi2dvi' or `latexmk',
+which calls the \"correct\" combinations of auxiliary programs.
 
 Alternatively, this may be a Lisp function that does the
 processing, so you could use this to apply the machinery of
@@ -807,44 +1174,33 @@ file name as its single argument."
   :type '(choice
          (repeat :tag "Shell command sequence"
                  (string :tag "Shell command"))
-         (const :tag "2 runs of pdflatex"
-                ("pdflatex -interaction nonstopmode -output-directory %o %f"
-                  "pdflatex -interaction nonstopmode -output-directory %o %f"))
-         (const :tag "3 runs of pdflatex"
-                ("pdflatex -interaction nonstopmode -output-directory %o %f"
-                  "pdflatex -interaction nonstopmode -output-directory %o %f"
-                  "pdflatex -interaction nonstopmode -output-directory %o %f"))
-         (const :tag "pdflatex,bibtex,pdflatex,pdflatex"
-                ("pdflatex -interaction nonstopmode -output-directory %o %f"
-                  "bibtex %b"
-                  "pdflatex -interaction nonstopmode -output-directory %o %f"
-                  "pdflatex -interaction nonstopmode -output-directory %o %f"))
-         (const :tag "2 runs of xelatex"
-                ("xelatex -interaction nonstopmode -output-directory %o %f"
-                 "xelatex -interaction nonstopmode -output-directory %o %f"))
-         (const :tag "3 runs of xelatex"
-                ("xelatex -interaction nonstopmode -output-directory %o %f"
-                 "xelatex -interaction nonstopmode -output-directory %o %f"
-                 "xelatex -interaction nonstopmode -output-directory %o %f"))
-         (const :tag "xelatex,bibtex,xelatex,xelatex"
-                ("xelatex -interaction nonstopmode -output-directory %o %f"
-                 "bibtex %b"
-                 "xelatex -interaction nonstopmode -output-directory %o %f"
-                 "xelatex -interaction nonstopmode -output-directory %o %f"))
+         (const :tag "2 runs of latex"
+                ("%latex -interaction nonstopmode -output-directory %o %f"
+                 "%latex -interaction nonstopmode -output-directory %o %f"))
+         (const :tag "3 runs of latex"
+                ("%latex -interaction nonstopmode -output-directory %o %f"
+                 "%latex -interaction nonstopmode -output-directory %o %f"
+                 "%latex -interaction nonstopmode -output-directory %o %f"))
+         (const :tag "latex,bibtex,latex,latex"
+                ("%latex -interaction nonstopmode -output-directory %o %f"
+                 "%bib %b"
+                 "%latex -interaction nonstopmode -output-directory %o %f"
+                 "%latex -interaction nonstopmode -output-directory %o %f"))
          (const :tag "texi2dvi"
-                ("texi2dvi -p -b -V %f"))
-         (const :tag "rubber"
-                ("rubber -d --into %o %f"))
+                ("cd %o; LATEX=\"%latex\" texi2dvi -p -b -V %b.tex"))
          (const :tag "latexmk"
-                ("latexmk -g -pdf %f"))
+                ("latexmk -g -pdf -pdflatex=\"%latex\" -outdir=%o %f"))
          (function)))
 
 (defcustom org-latex-logfiles-extensions
-  '("aux" "idx" "log" "out" "toc" "nav" "snm" "vrb")
+  '("aux" "bcf" "blg" "fdb_latexmk" "fls" "figlist" "idx" "log" "nav" "out"
+    "ptc" "run.xml" "snm" "toc" "vrb" "xdv")
   "The list of file extensions to consider as LaTeX logfiles.
-The logfiles will be remove if `org-latex-remove-logfiles' is
+The logfiles will be removed if `org-latex-remove-logfiles' is
 non-nil."
   :group 'org-export-latex
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(repeat (string :tag "Extension")))
 
 (defcustom org-latex-remove-logfiles t
@@ -855,19 +1211,20 @@ logfiles to remove, set `org-latex-logfiles-extensions'."
   :group 'org-export-latex
   :type 'boolean)
 
-(defcustom org-latex-known-errors
-  '(("Reference.*?undefined" .  "[undefined reference]")
-    ("Citation.*?undefined" .  "[undefined citation]")
-    ("Undefined control sequence" .  "[undefined control sequence]")
-    ("^! LaTeX.*?Error" .  "[LaTeX error]")
-    ("^! Package.*?Error" .  "[package error]")
-    ("Runaway argument" .  "Runaway argument"))
+(defcustom org-latex-known-warnings
+  '(("Reference.*?undefined" . "[undefined reference]")
+    ("Runaway argument" . "[runaway argument]")
+    ("Underfull \\hbox" . "[underfull hbox]")
+    ("Overfull \\hbox" . "[overfull hbox]")
+    ("Citation.*?undefined" . "[undefined citation]")
+    ("Undefined control sequence" . "[undefined control sequence]"))
   "Alist of regular expressions and associated messages for the user.
-The regular expressions are used to find possible errors in the
-log of a latex-run."
+The regular expressions are used to find possible warnings in the
+log of a latex-run.  These warnings will be reported after
+calling `org-latex-compile'."
   :group 'org-export-latex
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(repeat
          (cons
           (string :tag "Regexp")
@@ -877,6 +1234,54 @@ log of a latex-run."
 
 ;;; Internal Functions
 
+(defun org-latex--caption-above-p (element info)
+  "Non nil when caption is expected to be located above ELEMENT.
+INFO is a plist holding contextual information."
+  (let ((above (plist-get info :latex-caption-above)))
+    (if (symbolp above) above
+      (let ((type (org-element-type element)))
+       (memq (if (eq type 'link) 'image type) above)))))
+
+(defun org-latex--label (datum info &optional force full)
+  "Return an appropriate label for DATUM.
+DATUM is an element or a `target' type object.  INFO is the
+current export state, as a plist.
+
+Return nil if element DATUM has no NAME or VALUE affiliated
+keyword or no CUSTOM_ID property, unless FORCE is non-nil.  In
+this case always return a unique label.
+
+Eventually, if FULL is non-nil, wrap label within \"\\label{}\"."
+  (let* ((type (org-element-type datum))
+        (user-label
+         (org-element-property
+          (cl-case type
+            ((headline inlinetask) :CUSTOM_ID)
+            (target :value)
+            (otherwise :name))
+          datum))
+        (label
+         (and (or user-label force)
+              (if (and user-label (plist-get info :latex-prefer-user-labels))
+                  user-label
+                (concat (cl-case type
+                          (headline "sec:")
+                          (table "tab:")
+                          (latex-environment
+                           (and (string-match-p
+                                 org-latex-math-environments-re
+                                 (org-element-property :value datum))
+                                "eq:"))
+                          (paragraph
+                           (and (org-element-property :caption datum)
+                                "fig:")))
+                        (org-export-get-reference datum info))))))
+    (cond ((not full) label)
+         (label (format "\\label{%s}%s"
+                        label
+                        (if (eq type 'target) "" "\n")))
+         (t ""))))
+
 (defun org-latex--caption/label-string (element info)
   "Return caption and label LaTeX string for ELEMENT.
 
@@ -884,25 +1289,38 @@ INFO is a plist holding contextual information.  If 
there's no
 caption nor label, return the empty string.
 
 For non-floats, see `org-latex--wrap-label'."
-  (let* ((label (org-element-property :name element))
-        (label-str (if (not (org-string-nw-p label)) ""
-                     (format "\\label{%s}"
-                             (org-export-solidify-link-text label))))
+  (let* ((label (org-latex--label element info nil t))
         (main (org-export-get-caption element))
+        (attr (org-export-read-attribute :attr_latex element))
+        (type (org-element-type element))
+        (nonfloat (or (and (plist-member attr :float)
+                           (not (plist-get attr :float))
+                           main)
+                      (and (eq type 'src-block)
+                           (not (plist-get attr :float))
+                           (null (plist-get info :latex-listings)))))
         (short (org-export-get-caption element t))
-        (caption-from-attr-latex (org-export-read-attribute :attr_latex 
element :caption)))
+        (caption-from-attr-latex (plist-get attr :caption)))
     (cond
      ((org-string-nw-p caption-from-attr-latex)
       (concat caption-from-attr-latex "\n"))
-     ((and (not main) (equal label-str "")) "")
-     ((not main) (concat label-str "\n"))
+     ((and (not main) (equal label "")) "")
+     ((not main) label)
      ;; Option caption format with short name.
-     (short (format "\\caption[%s]{%s%s}\n"
-                   (org-export-data short info)
-                   label-str
-                   (org-export-data main info)))
-     ;; Standard caption format.
-     (t (format "\\caption{%s%s}\n" label-str (org-export-data main info))))))
+     (t
+      (format (if nonfloat "\\captionof{%s}%s{%s%s}\n"
+               "\\caption%s%s{%s%s}\n")
+             (if nonfloat
+                 (cl-case type
+                   (paragraph "figure")
+                   (src-block (if (plist-get info :latex-listings)
+                                  "listing"
+                                "figure"))
+                   (t (symbol-name type)))
+               "")
+             (if short (format "[%s]" (org-export-data short info)) "")
+             label
+             (org-export-data main info))))))
 
 (defun org-latex-guess-inputenc (header)
   "Set the coding system in inputenc to what the buffer is.
@@ -945,8 +1363,8 @@ Return the new header."
        header
       (let ((options (save-match-data
                       (org-split-string (match-string 1 header) ",[ \t]*")))
-           (language (cdr (assoc language-code
-                                 org-latex-babel-language-alist))))
+           (language (cdr (assoc-string language-code
+                                        org-latex-babel-language-alist t))))
        ;; If LANGUAGE is already loaded, return header without AUTO.
        ;; Otherwise, replace AUTO with language or append language if
        ;; AUTO is not present.
@@ -958,13 +1376,90 @@ Return the new header."
                    ", ")
         t nil header 1)))))
 
+(defun org-latex-guess-polyglossia-language (header info)
+  "Set the Polyglossia language according to the LANGUAGE keyword.
+
+HEADER is the LaTeX header string.  INFO is the plist used as
+a communication channel.
+
+Insertion of guessed language only happens when the Polyglossia
+package has been explicitly loaded.
+
+The argument to Polyglossia may be \"AUTO\" which is then
+replaced with the language of the document or
+`org-export-default-language'.  Note, the language is really set
+using \setdefaultlanguage and not as an option to the package.
+
+Return the new header."
+  (let ((language (plist-get info :language)))
+    ;; If no language is set or Polyglossia is not loaded, return
+    ;; HEADER as-is.
+    (if (or (not (stringp language))
+           (not (string-match
+                 "\\\\usepackage\\(?:\\[\\([^]]+?\\)\\]\\){polyglossia}\n"
+                 header)))
+       header
+      (let* ((options (org-string-nw-p (match-string 1 header)))
+            (languages (and options
+                            ;; Reverse as the last loaded language is
+                            ;; the main language.
+                            (nreverse
+                             (delete-dups
+                              (save-match-data
+                                (org-split-string
+                                 (replace-regexp-in-string
+                                  "AUTO" language options t)
+                                 ",[ \t]*"))))))
+            (main-language-set
+             (string-match-p "\\\\setmainlanguage{.*?}" header)))
+       (replace-match
+        (concat "\\usepackage{polyglossia}\n"
+                (mapconcat
+                 (lambda (l)
+                   (let ((l (or (assoc l org-latex-polyglossia-language-alist)
+                                l)))
+                     (format (if main-language-set "\\setotherlanguage%s{%s}\n"
+                               (setq main-language-set t)
+                               "\\setmainlanguage%s{%s}\n")
+                             (if (and (consp l) (= (length l) 3))
+                                 (format "[variant=%s]" (nth 2 l))
+                               "")
+                             (nth 1 l))))
+                 languages
+                 ""))
+        t t header 0)))))
+
+(defun org-latex--remove-packages (pkg-alist info)
+  "Remove packages based on the current LaTeX compiler.
+
+If the fourth argument of an element is set in pkg-alist, and it
+is not a member of the LaTeX compiler of the document, the packages
+is removed.  See also `org-latex-compiler'.
+
+Return modified pkg-alist."
+  (let ((compiler (or (plist-get info :latex-compiler) "")))
+    (if (member-ignore-case compiler org-latex-compilers)
+       (delq nil
+             (mapcar
+              (lambda (pkg)
+                (unless (and
+                         (listp pkg)
+                         (let ((third (nth 3 pkg)))
+                           (and third
+                                (not (member-ignore-case
+                                      compiler
+                                      (if (listp third) third (list 
third)))))))
+                  pkg))
+              pkg-alist))
+      pkg-alist)))
+
 (defun org-latex--find-verb-separator (s)
   "Return a character not used in string S.
 This is used to choose a separator for constructs like \\verb."
   (let ((ll 
"~,./?;':\"|address@hidden&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
-    (loop for c across ll
-         when (not (string-match (regexp-quote (char-to-string c)) s))
-         return (char-to-string c))))
+    (cl-loop for c across ll
+            when (not (string-match (regexp-quote (char-to-string c)) s))
+            return (char-to-string c))))
 
 (defun org-latex--make-option-string (options)
   "Return a comma separated string of keywords and values.
@@ -972,135 +1467,201 @@ OPTIONS is an alist where the key is the options 
keyword as
 a string, and the value a list containing the keyword value, or
 nil."
   (mapconcat (lambda (pair)
-              (concat (first pair)
-                      (when (> (length (second pair)) 0)
-                        (concat "=" (second pair)))))
+              (pcase-let ((`(,keyword ,value) pair))
+                (concat keyword
+                        (and (> (length value) 0)
+                             (concat "=" value)))))
             options
             ","))
 
-(defun org-latex--wrap-label (element output)
+(defun org-latex--wrap-label (element output info)
   "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
-This function shouldn't be used for floats.  See
+INFO is the current export state, as a plist.  This function
+should not be used for floats.  See
 `org-latex--caption/label-string'."
-  (let ((label (org-element-property :name element)))
-    (if (not (and (org-string-nw-p output) (org-string-nw-p label))) output
-      (concat (format "\\label{%s}\n" (org-export-solidify-link-text label))
-             output))))
+  (if (not (and (org-string-nw-p output) (org-element-property :name element)))
+      output
+    (concat (format "\\phantomsection\n\\label{%s}\n"
+                   (org-latex--label element info))
+           output)))
 
-(defun org-latex--text-markup (text markup)
+(defun org-latex--protect-text (text)
+  "Protect special characters in string TEXT and return it."
+  (replace-regexp-in-string "[\\{}$%&_#~^]" "\\\\\\&" text))
+
+(defun org-latex--text-markup (text markup info)
   "Format TEXT depending on MARKUP text markup.
-See `org-latex-text-markup-alist' for details."
-  (let ((fmt (cdr (assq markup org-latex-text-markup-alist))))
-    (cond
-     ;; No format string: Return raw text.
-     ((not fmt) text)
-     ;; Handle the `verb' special case: Find and appropriate separator
-     ;; and use "\\verb" command.
-     ((eq 'verb fmt)
-      (let ((separator (org-latex--find-verb-separator text)))
-       (concat "\\verb" separator
-               (replace-regexp-in-string "\n" " " text)
-               separator)))
-     ;; Handle the `protectedtexttt' special case: Protect some
-     ;; special chars and use "\texttt{%s}" format string.
-     ((eq 'protectedtexttt fmt)
-      (let ((start 0)
-           (trans '(("\\" . "\\textbackslash{}")
-                    ("~" . "\\textasciitilde{}")
-                    ("^" . "\\textasciicircum{}")))
-           (rtn "")
-           char)
-       (while (string-match "[\\{}$%&_#~^]" text)
-         (setq char (match-string 0 text))
-         (if (> (match-beginning 0) 0)
-             (setq rtn (concat rtn (substring text 0 (match-beginning 0)))))
-         (setq text (substring text (1+ (match-beginning 0))))
-         (setq char (or (cdr (assoc char trans)) (concat "\\" char))
-               rtn (concat rtn char)))
-       (setq text (concat rtn text)
-             fmt "\\texttt{%s}")
-       (while (string-match "--" text)
-         (setq text (replace-match "-{}-" t t text)))
-       (format fmt text)))
-     ;; Else use format string.
-     (t (format fmt text)))))
+INFO is a plist used as a communication channel.  See
+`org-latex-text-markup-alist' for details."
+  (let ((fmt (cdr (assq markup (plist-get info :latex-text-markup-alist)))))
+    (cl-case fmt
+      ;; No format string: Return raw text.
+      ((nil) text)
+      ;; Handle the `verb' special case: Find an appropriate separator
+      ;; and use "\\verb" command.
+      (verb
+       (let ((separator (org-latex--find-verb-separator text)))
+        (concat "\\verb"
+                separator
+                (replace-regexp-in-string "\n" " " text)
+                separator)))
+      ;; Handle the `protectedtexttt' special case: Protect some
+      ;; special chars and use "\texttt{%s}" format string.
+      (protectedtexttt
+       (format "\\texttt{%s}"
+              (replace-regexp-in-string
+               "--\\|[\\{}$%&_#~^]"
+               (lambda (m)
+                 (cond ((equal m "--") "-{}-")
+                       ((equal m "\\") "\\textbackslash{}")
+                       ((equal m "~") "\\textasciitilde{}")
+                       ((equal m "^") "\\textasciicircum{}")
+                       (t (org-latex--protect-text m))))
+               text nil t)))
+      ;; Else use format string.
+      (t (format fmt text)))))
 
 (defun org-latex--delayed-footnotes-definitions (element info)
   "Return footnotes definitions in ELEMENT as a string.
 
 INFO is a plist used as a communication channel.
 
-Footnotes definitions are returned within \"\\footnotetxt{}\"
+Footnotes definitions are returned within \"\\footnotetext{}\"
 commands.
 
 This function is used within constructs that don't support
-\"\\footnote{}\" command (i.e. an item's tag).  In that case,
+\"\\footnote{}\" command (e.g., an item tag).  In that case,
 \"\\footnotemark\" is used within the construct and the function
 just outside of it."
   (mapconcat
    (lambda (ref)
-     (format
-      "\\footnotetext[%s]{%s}"
-      (org-export-get-footnote-number ref info)
-      (org-trim
-       (org-export-data
-       (org-export-get-footnote-definition ref info) info))))
+     (let ((def (org-export-get-footnote-definition ref info)))
+       (format "\\footnotetext[%d]{%s%s}"
+              (org-export-get-footnote-number ref info)
+              (org-trim (org-latex--label def info t t))
+              (org-trim (org-export-data def info)))))
    ;; Find every footnote reference in ELEMENT.
-   (let* (all-refs
-         search-refs                   ; For byte-compiler.
-         (search-refs
-          (function
-           (lambda (data)
-             ;; Return a list of all footnote references never seen
-             ;; before in DATA.
-             (org-element-map data 'footnote-reference
-               (lambda (ref)
-                 (when (org-export-footnote-first-reference-p ref info)
-                   (push ref all-refs)
-                   (when (eq (org-element-property :type ref) 'standard)
-                     (funcall search-refs
-                              (org-export-get-footnote-definition ref info)))))
-               info)
-             (reverse all-refs)))))
+   (letrec ((all-refs nil)
+           (search-refs
+            (lambda (data)
+              ;; Return a list of all footnote references never seen
+              ;; before in DATA.
+              (org-element-map data 'footnote-reference
+                (lambda (ref)
+                  (when (org-export-footnote-first-reference-p ref info)
+                    (push ref all-refs)
+                    (when (eq (org-element-property :type ref) 'standard)
+                      (funcall search-refs
+                               (org-export-get-footnote-definition ref 
info)))))
+                info)
+              (reverse all-refs))))
      (funcall search-refs element))
    ""))
 
+(defun org-latex--translate (s info)
+  "Translate string S according to specified language.
+INFO is a plist used as a communication channel."
+  (org-export-translate s :latex info))
+
+(defun org-latex--format-spec (info)
+  "Create a format-spec for document meta-data.
+INFO is a plist used as a communication channel."
+  (let ((language (let ((lang (plist-get info :language)))
+                   (or (cdr (assoc-string lang org-latex-babel-language-alist 
t))
+                       (nth 1 (assoc-string lang 
org-latex-polyglossia-language-alist t))
+                       lang))))
+    `((?a . ,(org-export-data (plist-get info :author) info))
+      (?t . ,(org-export-data (plist-get info :title) info))
+      (?k . ,(org-export-data (org-latex--wrap-latex-math-block
+                              (plist-get info :keywords) info)
+                             info))
+      (?d . ,(org-export-data (org-latex--wrap-latex-math-block
+                              (plist-get info :description) info)
+                             info))
+      (?c . ,(plist-get info :creator))
+      (?l . ,language)
+      (?L . ,(capitalize language))
+      (?D . ,(org-export-get-date info)))))
+
+(defun org-latex--insert-compiler (info)
+  "Insert LaTeX_compiler info into the document.
+INFO is a plist used as a communication channel."
+  (let ((compiler (plist-get info :latex-compiler)))
+       (and (org-string-nw-p org-latex-compiler-file-string)
+           (member (or compiler "") org-latex-compilers)
+           (format org-latex-compiler-file-string compiler))))
+
+
+;;; Filters
+
+(defun org-latex-matrices-tree-filter (tree _backend info)
+  (org-latex--wrap-latex-matrices tree info))
+
+(defun org-latex-math-block-tree-filter (tree _backend info)
+  (org-latex--wrap-latex-math-block tree info))
+
+(defun org-latex-math-block-options-filter (info _backend)
+  (dolist (prop '(:author :date :title) info)
+    (plist-put info prop
+              (org-latex--wrap-latex-math-block (plist-get info prop) info))))
+
+(defun org-latex-clean-invalid-line-breaks (data _backend _info)
+  (replace-regexp-in-string
+   "\\(\\end{[A-Za-z0-9*]+}\\|^\\)[ \t]*\\\\\\\\[ \t]*$" "\\1"
+   data))
 
 
 ;;; Template
 
+;;;###autoload
+(defun org-latex-make-preamble (info &optional template snippet?)
+  "Return a formatted LaTeX preamble.
+INFO is a plist used as a communication channel.  Optional
+argument TEMPLATE, when non-nil, is the header template string,
+as expected by `org-splice-latex-header'.  When SNIPPET? is
+non-nil, only includes packages relevant to image generation, as
+specified in `org-latex-default-packages-alist' or
+`org-latex-packages-alist'."
+  (let* ((class (plist-get info :latex-class))
+        (class-options (plist-get info :latex-class-options))
+        (header (nth 1 (assoc class (plist-get info :latex-classes))))
+        (class-template
+         (or template
+             (and (stringp header)
+                  (if (not class-options) header
+                    (replace-regexp-in-string
+                     "^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)"
+                     class-options header t nil 1)))
+             (user-error "Unknown LaTeX class `%s'" class))))
+    (org-latex-guess-polyglossia-language
+     (org-latex-guess-babel-language
+      (org-latex-guess-inputenc
+       (org-element-normalize-string
+       (org-splice-latex-header
+        class-template
+        (org-latex--remove-packages org-latex-default-packages-alist info)
+        (org-latex--remove-packages org-latex-packages-alist info)
+        snippet?
+        (mapconcat #'org-element-normalize-string
+                   (list (plist-get info :latex-header)
+                         (plist-get info :latex-header-extra)) ""))))
+      info)
+     info)))
+
 (defun org-latex-template (contents info)
   "Return complete document string after LaTeX conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
-  (let ((title (org-export-data (plist-get info :title) info)))
+  (let ((title (org-export-data (plist-get info :title) info))
+       (spec (org-latex--format-spec info)))
     (concat
      ;; Time-stamp.
      (and (plist-get info :time-stamp-file)
          (format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
+     ;; LaTeX compiler.
+     (org-latex--insert-compiler info)
      ;; Document class and packages.
-     (let* ((class (plist-get info :latex-class))
-           (class-options (plist-get info :latex-class-options))
-           (header (nth 1 (assoc class org-latex-classes)))
-           (document-class-string
-            (and (stringp header)
-                 (if (not class-options) header
-                   (replace-regexp-in-string
-                    "^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)"
-                    class-options header t nil 1)))))
-       (if (not document-class-string)
-          (user-error "Unknown LaTeX class `%s'" class)
-        (org-latex-guess-babel-language
-         (org-latex-guess-inputenc
-          (org-element-normalize-string
-           (org-splice-latex-header
-            document-class-string
-            org-latex-default-packages-alist
-            org-latex-packages-alist nil
-            (concat (org-element-normalize-string
-                     (plist-get info :latex-header))
-                    (plist-get info :latex-header-extra)))))
-         info)))
+     (org-latex-make-preamble info)
      ;; Possibly limit depth for headline numbering.
      (let ((sec-num (plist-get info :section-numbers)))
        (when (integerp sec-num)
@@ -1117,40 +1678,46 @@ holding export options."
      ;; Date.
      (let ((date (and (plist-get info :with-date) (org-export-get-date info))))
        (format "\\date{%s}\n" (org-export-data date info)))
-     ;; Title
-     (format "\\title{%s}\n" title)
+     ;; Title and subtitle.
+     (let* ((subtitle (plist-get info :subtitle))
+           (formatted-subtitle
+            (when subtitle
+              (format (plist-get info :latex-subtitle-format)
+                      (org-export-data subtitle info))))
+           (separate (plist-get info :latex-subtitle-separate)))
+       (concat
+       (format "\\title{%s%s}\n" title
+               (if separate "" (or formatted-subtitle "")))
+       (when (and separate subtitle)
+         (concat formatted-subtitle "\n"))))
      ;; Hyperref options.
-     (when (plist-get info :latex-hyperref-p)
-       (format "\\hypersetup{\n  pdfkeywords={%s},\n  pdfsubject={%s},\n  
pdfcreator={%s}}\n"
-              (or (plist-get info :keywords) "")
-              (or (plist-get info :description) "")
-              (if (not (plist-get info :with-creator)) ""
-                (plist-get info :creator))))
+     (let ((template (plist-get info :latex-hyperref-template)))
+       (and (stringp template)
+            (format-spec template spec)))
      ;; Document start.
      "\\begin{document}\n\n"
      ;; Title command.
-     (org-element-normalize-string
-      (cond ((string= "" title) nil)
-           ((not (stringp org-latex-title-command)) nil)
-           ((string-match "\\(?:[^%]\\|^\\)%s"
-                          org-latex-title-command)
-            (format org-latex-title-command title))
-           (t org-latex-title-command)))
+     (let* ((title-command (plist-get info :latex-title-command))
+            (command (and (stringp title-command)
+                          (format-spec title-command spec))))
+       (org-element-normalize-string
+       (cond ((not (plist-get info :with-title)) nil)
+             ((string= "" title) nil)
+             ((not (stringp command)) nil)
+             ((string-match "\\(?:[^%]\\|^\\)%s" command)
+              (format command title))
+             (t command))))
      ;; Table of contents.
      (let ((depth (plist-get info :with-toc)))
        (when depth
         (concat (when (wholenump depth)
                   (format "\\setcounter{tocdepth}{%d}\n" depth))
-                org-latex-toc-command)))
+                (plist-get info :latex-toc-command))))
      ;; Document's body.
      contents
      ;; Creator.
-     (let ((creator-info (plist-get info :with-creator)))
-       (cond
-       ((not creator-info) "")
-       ((eq creator-info 'comment)
-        (format "%% %s\n" (plist-get info :creator)))
-       (t (concat (plist-get info :creator) "\n"))))
+     (and (plist-get info :with-creator)
+         (concat (plist-get info :creator) "\n"))
      ;; Document end.
      "\\end{document}")))
 
@@ -1160,11 +1727,11 @@ holding export options."
 
 ;;;; Bold
 
-(defun org-latex-bold (bold contents info)
+(defun org-latex-bold (_bold contents info)
   "Transcode BOLD from Org to LaTeX.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
-  (org-latex--text-markup contents 'bold))
+  (org-latex--text-markup contents 'bold info))
 
 
 ;;;; Center Block
@@ -1174,23 +1741,20 @@ contextual information."
 CONTENTS holds the contents of the center block.  INFO is a plist
 holding contextual information."
   (org-latex--wrap-label
-   center-block
-   (format "\\begin{center}\n%s\\end{center}" contents)))
+   center-block (format "\\begin{center}\n%s\\end{center}" contents) info))
 
 
 ;;;; Clock
 
-(defun org-latex-clock (clock contents info)
+(defun org-latex-clock (clock _contents info)
   "Transcode a CLOCK element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (concat
    "\\noindent"
    (format "\\textbf{%s} " org-clock-string)
-   (format org-latex-inactive-timestamp-format
-          (concat (org-translate-time
-                   (org-element-property :raw-value
-                                         (org-element-property :value clock)))
+   (format (plist-get info :latex-inactive-timestamp-format)
+          (concat (org-timestamp-translate (org-element-property :value clock))
                   (let ((time (org-element-property :duration clock)))
                     (and time (format " (%s)" time)))))
    "\\\\"))
@@ -1198,11 +1762,11 @@ information."
 
 ;;;; Code
 
-(defun org-latex-code (code contents info)
+(defun org-latex-code (code _contents info)
   "Transcode a CODE object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (org-latex--text-markup (org-element-property :value code) 'code))
+  (org-latex--text-markup (org-element-property :value code) 'code info))
 
 
 ;;;; Drawer
@@ -1212,9 +1776,9 @@ channel."
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   (let* ((name (org-element-property :drawer-name drawer))
-        (output (funcall org-latex-format-drawer-function
+        (output (funcall (plist-get info :latex-format-drawer-function)
                          name contents)))
-    (org-latex--wrap-label drawer output)))
+    (org-latex--wrap-label drawer output info)))
 
 
 ;;;; Dynamic Block
@@ -1223,35 +1787,40 @@ holding contextual information."
   "Transcode a DYNAMIC-BLOCK element from Org to LaTeX.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information.  See `org-export-data'."
-  (org-latex--wrap-label dynamic-block contents))
+  (org-latex--wrap-label dynamic-block contents info))
 
 
 ;;;; Entity
 
-(defun org-latex-entity (entity contents info)
+(defun org-latex-entity (entity _contents _info)
   "Transcode an ENTITY object from Org to LaTeX.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
-  (let ((ent (org-element-property :latex entity)))
-    (if (org-element-property :latex-math-p entity) (format "$%s$" ent) ent)))
+  (org-element-property :latex entity))
 
 
 ;;;; Example Block
 
-(defun org-latex-example-block (example-block contents info)
+(defun org-latex-example-block (example-block _contents info)
   "Transcode an EXAMPLE-BLOCK element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (when (org-string-nw-p (org-element-property :value example-block))
-    (org-latex--wrap-label
-     example-block
-     (format "\\begin{verbatim}\n%s\\end{verbatim}"
-            (org-export-format-code-default example-block info)))))
+    (let ((environment (or (org-export-read-attribute
+                           :attr_latex example-block :environment)
+                          "verbatim")))
+      (org-latex--wrap-label
+       example-block
+       (format "\\begin{%s}\n%s\\end{%s}"
+              environment
+              (org-export-format-code-default example-block info)
+              environment)
+       info))))
 
 
 ;;;; Export Block
 
-(defun org-latex-export-block (export-block contents info)
+(defun org-latex-export-block (export-block _contents _info)
   "Transcode a EXPORT-BLOCK element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (member (org-element-property :type export-block) '("LATEX" "TEX"))
@@ -1260,7 +1829,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Export Snippet
 
-(defun org-latex-export-snippet (export-snippet contents info)
+(defun org-latex-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (eq (org-export-snippet-backend export-snippet) 'latex)
@@ -1269,46 +1838,60 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Fixed Width
 
-(defun org-latex-fixed-width (fixed-width contents info)
+(defun org-latex-fixed-width (fixed-width _contents info)
   "Transcode a FIXED-WIDTH element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-latex--wrap-label
    fixed-width
    (format "\\begin{verbatim}\n%s\\end{verbatim}"
           (org-remove-indentation
-           (org-element-property :value fixed-width)))))
+           (org-element-property :value fixed-width)))
+   info))
 
 
 ;;;; Footnote Reference
 
-(defun org-latex-footnote-reference (footnote-reference contents info)
+(defun org-latex-footnote-reference (footnote-reference _contents info)
   "Transcode a FOOTNOTE-REFERENCE element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (concat
-   ;; Insert separator between two footnotes in a row.
-   (let ((prev (org-export-get-previous-element footnote-reference info)))
-     (when (eq (org-element-type prev) 'footnote-reference)
-       org-latex-footnote-separator))
-   (cond
-    ;; Use \footnotemark if the footnote has already been defined.
-    ((not (org-export-footnote-first-reference-p footnote-reference info))
-     (format "\\footnotemark[%s]{}"
-            (org-export-get-footnote-number footnote-reference info)))
-    ;; Use \footnotemark if reference is within another footnote
-    ;; reference, footnote definition or table cell.
-    ((loop for parent in (org-export-get-genealogy footnote-reference)
-          thereis (memq (org-element-type parent)
-                        '(footnote-reference footnote-definition table-cell)))
-     "\\footnotemark")
-    ;; Otherwise, define it with \footnote command.
-    (t
-     (let ((def (org-export-get-footnote-definition footnote-reference info)))
-       (concat
-       (format "\\footnote{%s}" (org-trim (org-export-data def info)))
-       ;; Retrieve all footnote references within the footnote and
-       ;; add their definition after it, since LaTeX doesn't support
-       ;; them inside.
-       (org-latex--delayed-footnotes-definitions def info)))))))
+  (let ((label (org-element-property :label footnote-reference)))
+    (concat
+     ;; Insert separator between two footnotes in a row.
+     (let ((prev (org-export-get-previous-element footnote-reference info)))
+       (when (eq (org-element-type prev) 'footnote-reference)
+        (plist-get info :latex-footnote-separator)))
+     (cond
+      ;; Use `:latex-footnote-defined-format' if the footnote has
+      ;; already been defined.
+      ((not (org-export-footnote-first-reference-p footnote-reference info))
+       (format (plist-get info :latex-footnote-defined-format)
+              (org-latex--label
+               (org-export-get-footnote-definition footnote-reference info)
+               info t)))
+      ;; Use \footnotemark if reference is within another footnote
+      ;; reference, footnote definition or table cell.
+      ((org-element-lineage footnote-reference
+                           '(footnote-reference footnote-definition 
table-cell))
+       "\\footnotemark")
+      ;; Otherwise, define it with \footnote command.
+      (t
+       (let ((def (org-export-get-footnote-definition footnote-reference 
info)))
+        (concat
+         (format "\\footnote{%s%s}" (org-trim (org-export-data def info))
+                 ;; Only insert a \label if there exist another
+                 ;; reference to def.
+                 (cond ((not label) "")
+                       ((org-element-map (plist-get info :parse-tree) 
'footnote-reference
+                           (lambda (f)
+                             (and (not (eq f footnote-reference))
+                                  (equal (org-element-property :label f) label)
+                                  (org-trim (org-latex--label def info t t))))
+                           info t))
+                       (t "")))
+         ;; Retrieve all footnote references within the footnote and
+         ;; add their definition after it, since LaTeX doesn't support
+         ;; them inside.
+         (org-latex--delayed-footnotes-definitions def info))))))))
 
 
 ;;;; Headline
@@ -1321,7 +1904,7 @@ holding contextual information."
     (let* ((class (plist-get info :latex-class))
           (level (org-export-get-relative-level headline info))
           (numberedp (org-export-numbered-headline-p headline info))
-          (class-sectioning (assoc class org-latex-classes))
+          (class-sectioning (assoc class (plist-get info :latex-classes)))
           ;; Section formatting will set two placeholders: one for
           ;; the title and the other for the contents.
           (section-fmt
@@ -1365,16 +1948,12 @@ holding contextual information."
                          (org-element-property :priority headline)))
           ;; Create the headline text along with a no-tag version.
           ;; The latter is required to remove tags from toc.
-          (full-text (funcall org-latex-format-headline-function
-                              todo todo-type priority text tags))
+          (full-text (funcall (plist-get info :latex-format-headline-function)
+                              todo todo-type priority text tags info))
           ;; Associate \label to the headline for internal links.
-          (headline-label
-           (format "\\label{sec-%s}\n"
-                   (mapconcat 'number-to-string
-                              (org-export-get-headline-number headline info)
-                              "-")))
+          (headline-label (org-latex--label headline info t t))
           (pre-blanks
-           (make-string (org-element-property :pre-blank headline) 10)))
+           (make-string (org-element-property :pre-blank headline) ?\n)))
       (if (or (not section-fmt) (org-export-low-level-p headline info))
          ;; This is a deep sub-tree: export it as a list item.  Also
          ;; export as items headlines for which no section format has
@@ -1386,7 +1965,8 @@ holding contextual information."
                    (format "\\begin{%s}\n" (if numberedp 'enumerate 'itemize)))
                  ;; Itemize headline
                  "\\item"
-                 (and full-text (org-string-match-p "\\`[ \t]*\\[" full-text)
+                 (and full-text
+                      (string-match-p "\\`[ \t]*\\[" full-text)
                       "\\relax")
                  " " full-text "\n"
                  headline-label
@@ -1404,15 +1984,32 @@ holding contextual information."
        ;; an alternative heading when possible, and when this is not
        ;; identical to the usual heading.
        (let ((opt-title
-              (funcall org-latex-format-headline-function
+              (funcall (plist-get info :latex-format-headline-function)
                        todo todo-type priority
                        (org-export-data-with-backend
                         (org-export-get-alt-title headline info)
                         section-back-end info)
-                       (and (eq (plist-get info :with-tags) t) tags))))
-         (if (and numberedp opt-title
+                       (and (eq (plist-get info :with-tags) t) tags)
+                       info))
+             ;; Maybe end local TOC (see `org-latex-keyword').
+             (contents
+              (concat
+               contents
+               (let ((case-fold-search t)
+                     (section
+                      (let ((first (car (org-element-contents headline))))
+                        (and (eq (org-element-type first) 'section) first))))
+                 (org-element-map section 'keyword
+                   (lambda (k)
+                     (and (equal (org-element-property :key k) "TOC")
+                          (let ((v (org-element-property :value k)))
+                            (and (string-match-p "\\<headlines\\>" v)
+                                 (string-match-p "\\<local\\>" v)
+                                 (format "\\stopcontents[level-%d]" level)))))
+                   info t)))))
+         (if (and opt-title
                   (not (equal opt-title full-text))
-                  (string-match "\\`\\\\\\(.*?[^*]\\){" section-fmt))
+                  (string-match "\\`\\\\\\(.+?\\){" section-fmt))
              (format (replace-match "\\1[%s]" nil nil section-fmt 1)
                      ;; Replace square brackets with parenthesis
                      ;; since square brackets are not supported in
@@ -1427,7 +2024,7 @@ holding contextual information."
                    (concat headline-label pre-blanks contents))))))))
 
 (defun org-latex-format-headline-default-function
-  (todo todo-type priority text tags)
+    (todo _todo-type priority text tags _info)
   "Default format function for a headline.
 See `org-latex-format-headline-function' for details."
   (concat
@@ -1435,12 +2032,13 @@ See `org-latex-format-headline-function' for details."
    (and priority (format "\\framebox{\\#%c} " priority))
    text
    (and tags
-       (format "\\hfill{}\\textsc{%s}" (mapconcat 'identity tags ":")))))
+       (format "\\hfill{}\\textsc{%s}"
+               (mapconcat #'org-latex--protect-text tags ":")))))
 
 
 ;;;; Horizontal Rule
 
-(defun org-latex-horizontal-rule (horizontal-rule contents info)
+(defun org-latex-horizontal-rule (horizontal-rule _contents info)
   "Transcode an HORIZONTAL-RULE object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((attr (org-export-read-attribute :attr_latex horizontal-rule))
@@ -1454,47 +2052,47 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
        "\n")
      (org-latex--wrap-label
       horizontal-rule
-      (format "\\rule{%s}{%s}"
-             (or (plist-get attr :width) "\\linewidth")
-             (or (plist-get attr :thickness) "0.5pt"))))))
+      (format "\\noindent\\rule{%s}{%s}"
+             (or (plist-get attr :width) "\\textwidth")
+             (or (plist-get attr :thickness) "0.5pt"))
+      info))))
 
 
 ;;;; Inline Src Block
 
-(defun org-latex-inline-src-block (inline-src-block contents info)
+(defun org-latex-inline-src-block (inline-src-block _contents info)
   "Transcode an INLINE-SRC-BLOCK element from Org to LaTeX.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (let* ((code (org-element-property :value inline-src-block))
         (separator (org-latex--find-verb-separator code)))
-    (cond
-     ;; Do not use a special package: transcode it verbatim.
-     ((not org-latex-listings)
-      (concat "\\verb" separator code separator))
-     ;; Use minted package.
-     ((eq org-latex-listings 'minted)
-      (let* ((org-lang (org-element-property :language inline-src-block))
-            (mint-lang (or (cadr (assq (intern org-lang)
-                                       org-latex-minted-langs))
-                           (downcase org-lang)))
-            (options (org-latex--make-option-string
-                      org-latex-minted-options)))
-       (concat (format "\\mint%s{%s}"
-                       (if (string= options "") "" (format "[%s]" options))
-                       mint-lang)
-               separator code separator)))
-     ;; Use listings package.
-     (t
-      ;; Maybe translate language's name.
-      (let* ((org-lang (org-element-property :language inline-src-block))
-            (lst-lang (or (cadr (assq (intern org-lang)
-                                      org-latex-listings-langs))
-                          org-lang))
-            (options (org-latex--make-option-string
-                      (append org-latex-listings-options
-                              `(("language" ,lst-lang))))))
-       (concat (format "\\lstinline[%s]" options)
-               separator code separator))))))
+    (cl-case (plist-get info :latex-listings)
+      ;; Do not use a special package: transcode it verbatim.
+      ((nil) (format "\\texttt{%s}" (org-latex--text-markup code 'code info)))
+      ;; Use minted package.
+      (minted
+       (let* ((org-lang (org-element-property :language inline-src-block))
+             (mint-lang (or (cadr (assq (intern org-lang)
+                                        (plist-get info :latex-minted-langs)))
+                            (downcase org-lang)))
+             (options (org-latex--make-option-string
+                       (plist-get info :latex-minted-options))))
+        (format "\\mintinline%s{%s}{%s}"
+                (if (string= options "") "" (format "[%s]" options))
+                mint-lang
+                code)))
+      ;; Use listings package.
+      (otherwise
+       ;; Maybe translate language's name.
+       (let* ((org-lang (org-element-property :language inline-src-block))
+             (lst-lang (or (cadr (assq (intern org-lang)
+                                       (plist-get info :latex-listings-langs)))
+                           org-lang))
+             (options (org-latex--make-option-string
+                       (append (plist-get info :latex-listings-options)
+                               `(("language" ,lst-lang))))))
+        (concat (format "\\lstinline[%s]" options)
+                separator code separator))))))
 
 
 ;;;; Inlinetask
@@ -1511,40 +2109,40 @@ holding contextual information."
        (tags (and (plist-get info :with-tags)
                   (org-export-get-tags inlinetask info)))
        (priority (and (plist-get info :with-priority)
-                      (org-element-property :priority inlinetask))))
-    ;; If `org-latex-format-inlinetask-function' is provided, call it
-    ;; with appropriate arguments.
-    (if (not (eq org-latex-format-inlinetask-function 'ignore))
-       (funcall org-latex-format-inlinetask-function
-                todo todo-type priority title tags contents)
-      ;; Otherwise, use a default template.
-      (org-latex--wrap-label
-       inlinetask
-       (let ((full-title
-             (concat
-              (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
-              (when priority (format "\\framebox{\\#%c} " priority))
-              title
-              (when tags (format "\\hfill{}\\textsc{:%s:}"
-                                 (mapconcat #'identity tags ":"))))))
-        (concat "\\begin{center}\n"
-                "\\fbox{\n"
-                "\\begin{minipage}[c]{.6\\textwidth}\n"
-                full-title "\n\n"
-                (and (org-string-nw-p contents)
-                     (concat "\\rule[.8em]{\\textwidth}{2pt}\n\n" contents))
-                "\\end{minipage}\n"
-                "}\n"
-                "\\end{center}"))))))
+                      (org-element-property :priority inlinetask)))
+       (contents (concat (org-latex--label inlinetask info) contents)))
+    (funcall (plist-get info :latex-format-inlinetask-function)
+            todo todo-type priority title tags contents info)))
+
+(defun org-latex-format-inlinetask-default-function
+    (todo _todo-type priority title tags contents _info)
+  "Default format function for a inlinetasks.
+See `org-latex-format-inlinetask-function' for details."
+  (let ((full-title
+        (concat (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
+                (when priority (format "\\framebox{\\#%c} " priority))
+                title
+                (when tags
+                  (format "\\hfill{}\\textsc{:%s:}"
+                          (mapconcat #'org-latex--protect-text tags ":"))))))
+    (concat "\\begin{center}\n"
+           "\\fbox{\n"
+           "\\begin{minipage}[c]{.6\\textwidth}\n"
+           full-title "\n\n"
+           (and (org-string-nw-p contents)
+                (concat "\\rule[.8em]{\\textwidth}{2pt}\n\n" contents))
+           "\\end{minipage}\n"
+           "}\n"
+           "\\end{center}")))
 
 
 ;;;; Italic
 
-(defun org-latex-italic (italic contents info)
+(defun org-latex-italic (_italic contents info)
   "Transcode ITALIC from Org to LaTeX.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
-  (org-latex--text-markup contents 'italic))
+  (org-latex--text-markup contents 'italic info))
 
 
 ;;;; Item
@@ -1565,14 +2163,14 @@ contextual information."
                     (when (and (eq (org-element-type parent) 'plain-list)
                                (eq (org-element-property :type parent)
                                    'ordered))
-                      (incf level)))
+                      (cl-incf level)))
                   level)))
            (and count
                 (< level 5)
                 (format "\\setcounter{enum%s}{%s}\n"
                         (nth (1- level) '("i" "ii" "iii" "iv"))
                         (1- count)))))
-        (checkbox (case (org-element-property :checkbox item)
+        (checkbox (cl-case (org-element-property :checkbox item)
                     (on "$\\boxtimes$ ")
                     (off "$\\square$ ")
                     (trans "$\\boxminus$ ")))
@@ -1591,7 +2189,7 @@ contextual information."
             ;; unless the brackets comes from an initial export
             ;; snippet (i.e. it is inserted willingly by the user).
             ((and contents
-                  (org-string-match-p "\\`[ \t]*\\[" contents)
+                  (string-match-p "\\`[ \t]*\\[" contents)
                   (not (let ((e (car (org-element-contents item))))
                          (and (eq (org-element-type e) 'paragraph)
                               (let ((o (car (org-element-contents e))))
@@ -1612,7 +2210,7 @@ contextual information."
 
 ;;;; Keyword
 
-(defun org-latex-keyword (keyword contents info)
+(defun org-latex-keyword (keyword _contents info)
   "Transcode a KEYWORD element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((key (org-element-property :key keyword))
@@ -1621,36 +2219,42 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
      ((string= key "LATEX") value)
      ((string= key "INDEX") (format "\\index{%s}" value))
      ((string= key "TOC")
-      (let ((value (downcase value)))
+      (let ((case-fold-search t))
        (cond
-        ((string-match "\\<headlines\\>" value)
-         (let ((depth (or (and (string-match "[0-9]+" value)
-                               (string-to-number (match-string 0 value)))
-                          (plist-get info :with-toc))))
-           (concat
-            (when (wholenump depth)
-              (format "\\setcounter{tocdepth}{%s}\n" depth))
-            "\\tableofcontents")))
-        ((string= "tables" value) "\\listoftables")
-        ((string= "listings" value)
-         (cond
-          ((eq org-latex-listings 'minted) "\\listoflistings")
-          (org-latex-listings "\\lstlistoflistings")
-          ;; At the moment, src blocks with a caption are wrapped
-          ;; into a figure environment.
-          (t "\\listoffigures")))))))))
+        ((string-match-p "\\<headlines\\>" value)
+         (let* ((localp (string-match-p "\\<local\\>" value))
+                (parent (org-element-lineage keyword '(headline)))
+                (level (if (not (and localp parent)) 0
+                         (org-export-get-relative-level parent info)))
+                (depth
+                 (and (string-match "\\<[0-9]+\\>" value)
+                      (format
+                       "\\setcounter{tocdepth}{%d}"
+                       (+ (string-to-number (match-string 0 value)) level)))))
+           (if (and localp parent)
+               ;; Start local TOC, assuming package "titletoc" is
+               ;; required.
+               (format "\\startcontents[level-%d]
+\\printcontents[level-%d]{}{0}{%s}"
+                       level level (or depth ""))
+             (concat depth (and depth "\n") "\\tableofcontents"))))
+        ((string-match-p "\\<tables\\>" value) "\\listoftables")
+        ((string-match-p "\\<listings\\>" value)
+         (cl-case (plist-get info :latex-listings)
+           ((nil) "\\listoffigures")
+           (minted "\\listoflistings")
+           (otherwise "\\lstlistoflistings")))))))))
 
 
 ;;;; Latex Environment
 
-(defun org-latex-latex-environment (latex-environment contents info)
+(defun org-latex-latex-environment (latex-environment _contents info)
   "Transcode a LATEX-ENVIRONMENT element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (plist-get info :with-latex)
-    (let ((label (org-element-property :name latex-environment))
-         (value (org-remove-indentation
+    (let ((value (org-remove-indentation
                  (org-element-property :value latex-environment))))
-      (if (not (org-string-nw-p label)) value
+      (if (not (org-element-property :name latex-environment)) value
        ;; Environment is labeled: label must be within the environment
        ;; (otherwise, a reference pointing to that element will count
        ;; the section instead).
@@ -1658,23 +2262,26 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
          (insert value)
          (goto-char (point-min))
          (forward-line)
-         (insert
-          (format "\\label{%s}\n" (org-export-solidify-link-text label)))
+         (insert (org-latex--label latex-environment info nil t))
          (buffer-string))))))
 
 
 ;;;; Latex Fragment
 
-(defun org-latex-latex-fragment (latex-fragment contents info)
+(defun org-latex-latex-fragment (latex-fragment _contents _info)
   "Transcode a LATEX-FRAGMENT object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (when (plist-get info :with-latex)
-    (org-element-property :value latex-fragment)))
+  (let ((value (org-element-property :value latex-fragment)))
+    ;; Trim math markers since the fragment is enclosed within
+    ;; a latex-math-block object anyway.
+    (cond ((string-match-p "\\`\\$[^$]" value) (substring value 1 -1))
+         ((string-prefix-p "\\(" value) (substring value 2 -2))
+         (t value))))
 
 
 ;;;; Line Break
 
-(defun org-latex-line-break (line-break contents info)
+(defun org-latex-line-break (_line-break _contents _info)
   "Transcode a LINE-BREAK object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   "\\\\\n")
@@ -1692,36 +2299,43 @@ used as a communication channel."
                   (expand-file-name raw-path))))
         (filetype (file-name-extension path))
         (caption (org-latex--caption/label-string parent info))
+        (caption-above-p (org-latex--caption-above-p link info))
         ;; Retrieve latex attributes from the element around.
         (attr (org-export-read-attribute :attr_latex parent))
         (float (let ((float (plist-get attr :float)))
-                 (cond ((and (not float) (plist-member attr :float)) nil)
-                       ((string= float "wrap") 'wrap)
+                 (cond ((string= float "wrap") 'wrap)
+                       ((string= float "sideways") 'sideways)
                        ((string= float "multicolumn") 'multicolumn)
+                       ((and (plist-member attr :float) (not float)) 'nonfloat)
                        ((or float
                             (org-element-property :caption parent)
                             (org-string-nw-p (plist-get attr :caption)))
-                        'figure))))
+                        'figure)
+                       (t 'nonfloat))))
         (placement
          (let ((place (plist-get attr :placement)))
-           (cond (place (format "%s" place))
-                 ((eq float 'wrap) "{l}{0.5\\textwidth}")
-                 ((eq float 'figure)
-                  (format "[%s]" org-latex-default-figure-position))
-                 (t ""))))
+           (cond
+            (place (format "%s" place))
+            ((eq float 'wrap) "{l}{0.5\\textwidth}")
+            ((eq float 'figure)
+             (format "[%s]" (plist-get info :latex-default-figure-position)))
+            (t ""))))
+        (center
+         (if (plist-member attr :center) (plist-get attr :center)
+           (plist-get info :latex-images-centered)))
         (comment-include (if (plist-get attr :comment-include) "%" ""))
         ;; It is possible to specify width and height in the
         ;; ATTR_LATEX line, and also via default variables.
         (width (cond ((plist-get attr :width))
                      ((plist-get attr :height) "")
                      ((eq float 'wrap) "0.48\\textwidth")
-                     (t org-latex-image-default-width)))
+                     (t (plist-get info :latex-image-default-width))))
         (height (cond ((plist-get attr :height))
                       ((or (plist-get attr :width)
                            (memq float '(figure wrap))) "")
-                      (t org-latex-image-default-height)))
+                      (t (plist-get info :latex-image-default-height))))
         (options (let ((opt (or (plist-get attr :options)
-                                org-latex-image-default-option)))
+                                (plist-get info :latex-image-default-option))))
                    (if (not (string-match "\\`\\[\\(.*\\)\\]\\'" opt)) opt
                      (match-string 1 opt))))
         image-code)
@@ -1750,11 +2364,17 @@ used as a communication channel."
        (setq options (concat options ",width=" width)))
       (when (org-string-nw-p height)
        (setq options (concat options ",height=" height)))
+      (let ((search-option (org-element-property :search-option link)))
+        (when (and search-option
+                   (equal filetype "pdf")
+                   (string-match-p "\\`[0-9]+\\'" search-option)
+                   (not (string-match-p "page=" options)))
+          (setq options (concat options ",page=" search-option))))
       (setq image-code
            (format "\\includegraphics%s{%s}"
                    (cond ((not (org-string-nw-p options)) "")
-                         ((= (aref options 0) ?,)
-                          (format "[%s]"(substring options 1)))
+                         ((string-prefix-p "," options)
+                          (format "[%s]" (substring options 1)))
                          (t (format "[%s]" options)))
                    path))
       (when (equal filetype "svg")
@@ -1767,20 +2387,53 @@ used as a communication channel."
                                                   image-code
                                                   nil t))))
     ;; Return proper string, depending on FLOAT.
-    (case float
-      (wrap (format "\\begin{wrapfigure}%s
-\\centering
+    (pcase float
+      (`wrap (format "\\begin{wrapfigure}%s
 %s%s
-%s\\end{wrapfigure}" placement comment-include image-code caption))
-      (multicolumn (format "\\begin{figure*}%s
-\\centering
 %s%s
-%s\\end{figure*}" placement comment-include image-code caption))
-      (figure (format "\\begin{figure}%s
-\\centering
+%s\\end{wrapfigure}"
+                    placement
+                    (if caption-above-p caption "")
+                    (if center "\\centering" "")
+                    comment-include image-code
+                    (if caption-above-p "" caption)))
+      (`sideways (format "\\begin{sidewaysfigure}
 %s%s
-%s\\end{figure}" placement comment-include image-code caption))
-      (otherwise image-code))))
+%s%s
+%s\\end{sidewaysfigure}"
+                        (if caption-above-p caption "")
+                        (if center "\\centering" "")
+                        comment-include image-code
+                        (if caption-above-p "" caption)))
+      (`multicolumn (format "\\begin{figure*}%s
+%s%s
+%s%s
+%s\\end{figure*}"
+                           placement
+                           (if caption-above-p caption "")
+                           (if center "\\centering" "")
+                           comment-include image-code
+                           (if caption-above-p "" caption)))
+      (`figure (format "\\begin{figure}%s
+%s%s
+%s%s
+%s\\end{figure}"
+                      placement
+                      (if caption-above-p caption "")
+                      (if center "\\centering" "")
+                      comment-include image-code
+                      (if caption-above-p "" caption)))
+      ((guard center)
+       (format "\\begin{center}
+%s%s
+%s\\end{center}"
+              (if caption-above-p caption "")
+              image-code
+              (if caption-above-p "" caption)))
+      (_
+       (concat (if caption-above-p caption "")
+              image-code
+              (if caption-above-p caption ""))))))
 
 (defun org-latex-link (link desc info)
   "Transcode a LINK object from Org to LaTeX.
@@ -1789,20 +2442,19 @@ DESC is the description part of the link, or the empty 
string.
 INFO is a plist holding contextual information.  See
 `org-export-data'."
   (let* ((type (org-element-property :type link))
-        (raw-path (replace-regexp-in-string
-                   "%" "\\%" (org-element-property :path link) nil t))
+        (raw-path (org-element-property :path link))
         ;; Ensure DESC really exists, or set it to nil.
         (desc (and (not (string= desc "")) desc))
         (imagep (org-export-inline-image-p
-                 link org-latex-inline-image-rules))
-        (path (cond
-               ((member type '("http" "https" "ftp" "mailto"))
-                (concat type ":" raw-path))
-               ((and (string= type "file") (file-name-absolute-p raw-path))
-                (concat "file:" raw-path))
-               (t raw-path)))
-        protocol)
+                 link (plist-get info :latex-inline-image-rules)))
+        (path (org-latex--protect-text
+               (cond ((member type '("http" "https" "ftp" "mailto" "doi"))
+                      (concat type ":" raw-path))
+                     ((string= type "file") (org-export-file-uri raw-path))
+                     (t raw-path)))))
     (cond
+     ;; Link type is handled by a special function.
+     ((org-export-custom-protocol-maybe link desc 'latex))
      ;; Image file.
      (imagep (org-latex--inline-image link info))
      ;; Radio link: Transcode target's contents and use them as link's
@@ -1811,8 +2463,7 @@ INFO is a plist holding contextual information.  See
       (let ((destination (org-export-resolve-radio-link link info)))
        (if (not destination) desc
          (format "\\hyperref[%s]{%s}"
-                 (org-export-solidify-link-text
-                  (org-element-property :value destination))
+                 (org-export-get-reference destination info)
                  desc))))
      ;; Links pointing to a headline: Find destination and build
      ;; appropriate referencing command.
@@ -1820,14 +2471,14 @@ INFO is a plist holding contextual information.  See
       (let ((destination (if (string= type "fuzzy")
                             (org-export-resolve-fuzzy-link link info)
                           (org-export-resolve-id-link link info))))
-       (case (org-element-type destination)
+       (cl-case (org-element-type destination)
          ;; Id link points to an external file.
          (plain-text
           (if desc (format "\\href{%s}{%s}" destination desc)
             (format "\\url{%s}" destination)))
          ;; Fuzzy link points nowhere.
-         ('nil
-          (format org-latex-link-with-unknown-path-format
+         ((nil)
+          (format (plist-get info :latex-link-with-unknown-path-format)
                   (or desc
                       (org-export-data
                        (org-element-property :raw-link link) info))))
@@ -1836,12 +2487,7 @@ INFO is a plist holding contextual information.  See
          ;; number.  Otherwise, display description or headline's
          ;; title.
          (headline
-          (let ((label
-                 (format "sec-%s"
-                         (mapconcat
-                          'number-to-string
-                          (org-export-get-headline-number destination info)
-                          "-"))))
+          (let ((label (org-latex--label destination info t)))
             (if (and (not desc)
                      (org-export-numbered-headline-p destination info))
                 (format "\\ref{%s}" label)
@@ -1851,28 +2497,37 @@ INFO is a plist holding contextual information.  See
                            (org-element-property :title destination) info))))))
           ;; Fuzzy link points to a target.  Do as above.
          (otherwise
-          (let ((path (org-export-solidify-link-text path)))
-            (if (not desc) (format "\\ref{%s}" path)
-              (format "\\hyperref[%s]{%s}" path desc)))))))
+          (let ((ref (org-latex--label destination info t)))
+            (if (not desc) (format "\\ref{%s}" ref)
+              (format "\\hyperref[%s]{%s}" ref desc)))))))
      ;; Coderef: replace link with the reference name or the
      ;; equivalent line number.
      ((string= type "coderef")
       (format (org-export-get-coderef-format path desc)
              (org-export-resolve-coderef path info)))
-     ;; Link type is handled by a special function.
-     ((functionp (setq protocol (nth 2 (assoc type org-link-protocols))))
-      (funcall protocol (org-link-unescape path) desc 'latex))
      ;; External link with a description part.
      ((and path desc) (format "\\href{%s}{%s}" path desc))
      ;; External link without a description part.
      (path (format "\\url{%s}" path))
      ;; No path, only description.  Try to do something useful.
-     (t (format org-latex-link-with-unknown-path-format desc)))))
+     (t (format (plist-get info :latex-link-with-unknown-path-format) desc)))))
+
+
+;;;; Node Property
+
+(defun org-latex-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to LaTeX.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
 
 
 ;;;; Paragraph
 
-(defun org-latex-paragraph (paragraph contents info)
+(defun org-latex-paragraph (_paragraph contents _info)
   "Transcode a PARAGRAPH element from Org to LaTeX.
 CONTENTS is the contents of the paragraph, as a string.  INFO is
 the plist used as a communication channel."
@@ -1898,7 +2553,8 @@ contextual information."
             latex-type
             (or (plist-get attr :options) "")
             contents
-            latex-type))))
+            latex-type)
+     info)))
 
 
 ;;;; Plain Text
@@ -1907,54 +2563,42 @@ contextual information."
   "Transcode a TEXT string from Org to LaTeX.
 TEXT is the string to transcode.  INFO is a plist holding
 contextual information."
-  (let ((specialp (plist-get info :with-special-strings))
-       (output text))
-    ;; Protect %, #, &, $, _, { and }.
-    (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}_]\\)" output)
-      (setq output
-           (replace-match
-            (format "\\%s" (match-string 2 output)) nil t output 2)))
-    ;; Protect ^.
-    (setq output
-         (replace-regexp-in-string
-          "\\([^\\]\\|^\\)\\(\\^\\)" "\\\\^{}" output nil nil 2))
-    ;; Protect \.  If special strings are used, be careful not to
-    ;; protect "\" in "\-" constructs.
-    (let ((symbols (if specialp "-%$#&{}^_\\" "%$#&{}^_\\")))
-      (setq output
+  (let* ((specialp (plist-get info :with-special-strings))
+        (output
+         ;; Turn LaTeX into \LaTeX{} and TeX into \TeX{}.
+         (let ((case-fold-search nil))
            (replace-regexp-in-string
-            (format "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%s]\\|$\\)" symbols)
-            "$\\backslash$" output nil t 1)))
-    ;; Protect ~.
-    (setq output
-         (replace-regexp-in-string
-          "\\([^\\]\\|^\\)\\(~\\)" "\\textasciitilde{}" output nil t 2))
+            "\\<\\(?:La\\)?TeX\\>" "\\\\\\&{}"
+            ;; Protect ^, ~, %, #, &, $, _, { and }.  Also protect \.
+            ;; However, if special strings are used, be careful not
+            ;; to protect "\" in "\-" constructs.
+            (replace-regexp-in-string
+             (concat "[%$#&{}_~^]\\|\\\\" (and specialp "\\([^-]\\|$\\)"))
+             (lambda (m)
+               (cl-case (string-to-char m)
+                 (?\\ "$\\\\backslash$\\1")
+                 (?~ "\\\\textasciitilde{}")
+                 (?^ "\\\\^{}")
+                 (t "\\\\\\&")))
+             text)))))
     ;; Activate smart quotes.  Be sure to provide original TEXT string
     ;; since OUTPUT may have been modified.
     (when (plist-get info :with-smart-quotes)
       (setq output (org-export-activate-smart-quotes output :latex info text)))
-    ;; LaTeX into \LaTeX{} and TeX into \TeX{}.
-    (let ((case-fold-search nil)
-         (start 0))
-      (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" output start)
-       (setq output (replace-match
-                     (format "\\%s{}" (match-string 1 output)) nil t output)
-             start (match-end 0))))
     ;; Convert special strings.
     (when specialp
-      (setq output
-           (replace-regexp-in-string "\\.\\.\\." "\\ldots{}" output nil t)))
+      (setq output (replace-regexp-in-string "\\.\\.\\." "\\\\ldots{}" 
output)))
     ;; Handle break preservation if required.
     (when (plist-get info :preserve-breaks)
       (setq output (replace-regexp-in-string
-                   "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" output)))
+                   "\\(?:[ \t]*\\\\\\\\\\)?[ \t]*\n" "\\\\\n" output nil t)))
     ;; Return value.
     output))
 
 
 ;;;; Planning
 
-(defun org-latex-planning (planning contents info)
+(defun org-latex-planning (planning _contents info)
   "Transcode a PLANNING element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
@@ -1968,27 +2612,165 @@ information."
             (when closed
               (concat
                (format "\\textbf{%s} " org-closed-string)
-               (format org-latex-inactive-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value closed))))))
+               (format (plist-get info :latex-inactive-timestamp-format)
+                       (org-timestamp-translate closed)))))
           (let ((deadline (org-element-property :deadline planning)))
             (when deadline
               (concat
                (format "\\textbf{%s} " org-deadline-string)
-               (format org-latex-active-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value deadline))))))
+               (format (plist-get info :latex-active-timestamp-format)
+                       (org-timestamp-translate deadline)))))
           (let ((scheduled (org-element-property :scheduled planning)))
             (when scheduled
               (concat
                (format "\\textbf{%s} " org-scheduled-string)
-               (format org-latex-active-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value scheduled))))))))
+               (format (plist-get info :latex-active-timestamp-format)
+                       (org-timestamp-translate scheduled)))))))
     " ")
    "\\\\"))
 
 
+;;;; Property Drawer
+
+(defun org-latex-property-drawer (_property-drawer contents _info)
+  "Transcode a PROPERTY-DRAWER element from Org to LaTeX.
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (format "\\begin{verbatim}\n%s\\end{verbatim}" contents)))
+
+
+;;;; Pseudo Element: LaTeX Matrices
+
+;; `latex-matrices' elements have the following properties:
+;; `:caption', `:post-blank' and `:markup' (`inline', `equation' or
+;; `math').
+
+(defun org-latex--wrap-latex-matrices (data info)
+  "Merge contiguous tables with the same mode within a pseudo-element.
+DATA is a parse tree or a secondary string.  INFO is a plist
+containing export options.  Modify DATA by side-effect and return
+it."
+  (org-element-map data 'table
+    (lambda (table)
+      (when (eq (org-element-property :type table) 'org)
+       (let ((mode (or (org-export-read-attribute :attr_latex table :mode)
+                       (plist-get info :latex-default-table-mode))))
+         (when (and (member mode '("inline-math" "math"))
+                    ;; Do not wrap twice the same table.
+                    (not (eq (org-element-type
+                              (org-element-property :parent table))
+                             'latex-matrices)))
+           (let* ((caption (and (not (string= mode "inline-math"))
+                                (org-element-property :caption table)))
+                  (matrices
+                   (list 'latex-matrices
+                         (list :caption caption
+                               :markup
+                               (cond ((string= mode "inline-math") 'inline)
+                                     (caption 'equation)
+                                     (t 'math)))))
+                  (previous table)
+                  (next (org-export-get-next-element table info)))
+             (org-element-insert-before matrices table)
+             ;; Swallow all contiguous tables sharing the same mode.
+             (while (and
+                     (zerop (or (org-element-property :post-blank previous) 0))
+                     (setq next (org-export-get-next-element previous info))
+                     (eq (org-element-type next) 'table)
+                     (eq (org-element-property :type next) 'org)
+                     (string= (or (org-export-read-attribute
+                                   :attr_latex next :mode)
+                                  (plist-get info :latex-default-table-mode))
+                              mode))
+               (org-element-extract-element previous)
+               (org-element-adopt-elements matrices previous)
+               (setq previous next))
+             ;; Inherit `:post-blank' from the value of the last
+             ;; swallowed table.  Set the latter's `:post-blank'
+             ;; value to 0 so as to not duplicate empty lines.
+             (org-element-put-property
+              matrices :post-blank (org-element-property :post-blank previous))
+             (org-element-put-property previous :post-blank 0)
+             (org-element-extract-element previous)
+             (org-element-adopt-elements matrices previous))))))
+    info)
+  data)
+
+(defun org-latex-matrices (matrices contents _info)
+  "Transcode a MATRICES element from Org to LaTeX.
+CONTENTS is a string.  INFO is a plist used as a communication
+channel."
+  (format (cl-case (org-element-property :markup matrices)
+           (inline "\\(%s\\)")
+           (equation "\\begin{equation}\n%s\\end{equation}")
+           (t "\\[\n%s\\]"))
+         contents))
+
+
+;;;; Pseudo Object: LaTeX Math Block
+
+;; `latex-math-block' objects have the following property:
+;; `:post-blank'.
+
+(defun org-latex--wrap-latex-math-block (data info)
+  "Merge contiguous math objects in a pseudo-object container.
+DATA is a parse tree or a secondary string.  INFO is a plist
+containing export options.  Modify DATA by side-effect and return it."
+  (let ((valid-object-p
+        ;; Non-nil when OBJ can be added to the latex math block B.
+        (lambda (obj b)
+          (pcase (org-element-type obj)
+            (`entity (org-element-property :latex-math-p obj))
+            (`latex-fragment
+             (let ((value (org-element-property :value obj)))
+               (or (string-prefix-p "\\(" value)
+                   (string-match-p "\\`\\$[^$]" value))))
+            ((and type (or `subscript `superscript))
+             (not (memq type (mapcar #'org-element-type
+                                     (org-element-contents b)))))))))
+    (org-element-map data '(entity latex-fragment subscript superscript)
+      (lambda (object)
+       ;; Skip objects already wrapped.
+       (when (and (not (eq (org-element-type
+                            (org-element-property :parent object))
+                           'latex-math-block))
+                  (funcall valid-object-p object nil))
+         (let ((math-block (list 'latex-math-block nil))
+               (next-elements (org-export-get-next-element object info t))
+               (last object))
+           ;; Wrap MATH-BLOCK around OBJECT in DATA.
+           (org-element-insert-before math-block object)
+           (org-element-extract-element object)
+           (org-element-adopt-elements math-block object)
+           (when (zerop (or (org-element-property :post-blank object) 0))
+             ;; MATH-BLOCK swallows consecutive math objects.
+             (catch 'exit
+               (dolist (next next-elements)
+                 (unless (funcall valid-object-p next math-block)
+                   (throw 'exit nil))
+                 (org-element-extract-element next)
+                 (org-element-adopt-elements math-block next)
+                 ;; Eschew the case: \beta$x$ -> \(\betax\).
+                 (unless (memq (org-element-type next)
+                               '(subscript superscript))
+                   (org-element-put-property last :post-blank 1))
+                 (setq last next)
+                 (when (> (or (org-element-property :post-blank next) 0) 0)
+                   (throw 'exit nil)))))
+           (org-element-put-property
+            math-block :post-blank (org-element-property :post-blank last)))))
+      info nil '(subscript superscript latex-math-block) t)
+    ;; Return updated DATA.
+    data))
+
+(defun org-latex-math-block (_math-block contents _info)
+  "Transcode a MATH-BLOCK object from Org to LaTeX.
+CONTENTS is a string.  INFO is a plist used as a communication
+channel."
+  (when (org-string-nw-p contents)
+    (format "\\(%s\\)" (org-trim contents))))
+
 ;;;; Quote Block
 
 (defun org-latex-quote-block (quote-block contents info)
@@ -1996,18 +2778,7 @@ information."
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   (org-latex--wrap-label
-   quote-block
-   (format "\\begin{quote}\n%s\\end{quote}" contents)))
-
-
-;;;; Quote Section
-
-(defun org-latex-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to LaTeX.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((value (org-remove-indentation
-               (org-element-property :value quote-section))))
-    (when value (format "\\begin{verbatim}\n%s\\end{verbatim}" value))))
+   quote-block (format "\\begin{quote}\n%s\\end{quote}" contents) info))
 
 
 ;;;; Radio Target
@@ -2016,15 +2787,12 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
   "Transcode a RADIO-TARGET object from Org to LaTeX.
 TEXT is the text of the target.  INFO is a plist holding
 contextual information."
-  (format "\\label{%s}%s"
-         (org-export-solidify-link-text
-          (org-element-property :value radio-target))
-         text))
+  (format "\\label{%s}%s" (org-export-get-reference radio-target info) text))
 
 
 ;;;; Section
 
-(defun org-latex-section (section contents info)
+(defun org-latex-section (_section contents _info)
   "Transcode a SECTION element from Org to LaTeX.
 CONTENTS holds the contents of the section.  INFO is a plist
 holding contextual information."
@@ -2037,85 +2805,110 @@ holding contextual information."
   "Transcode a SPECIAL-BLOCK element from Org to LaTeX.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (let ((type (downcase (org-element-property :type special-block)))
-       (opt (org-export-read-attribute :attr_latex special-block :options)))
+  (let ((type (org-element-property :type special-block))
+       (opt (org-export-read-attribute :attr_latex special-block :options))
+       (caption (org-latex--caption/label-string special-block info))
+       (caption-above-p (org-latex--caption-above-p special-block info)))
     (concat (format "\\begin{%s}%s\n" type (or opt ""))
-           ;; Insert any label or caption within the block
-           ;; (otherwise, a reference pointing to that element will
-           ;; count the section instead).
-           (org-latex--caption/label-string special-block info)
+           (and caption-above-p caption)
            contents
+           (and (not caption-above-p) caption)
            (format "\\end{%s}" type))))
 
 
 ;;;; Src Block
 
-(defun org-latex-src-block (src-block contents info)
+(defun org-latex-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to LaTeX.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (when (org-string-nw-p (org-element-property :value src-block))
     (let* ((lang (org-element-property :language src-block))
           (caption (org-element-property :caption src-block))
+          (caption-above-p (org-latex--caption-above-p src-block info))
           (label (org-element-property :name src-block))
           (custom-env (and lang
                            (cadr (assq (intern lang)
                                        org-latex-custom-lang-environments))))
-          (num-start (case (org-element-property :number-lines src-block)
-                       (continued (org-export-get-loc src-block info))
-                       (new 0)))
+          (num-start (org-export-get-loc src-block info))
           (retain-labels (org-element-property :retain-labels src-block))
           (attributes (org-export-read-attribute :attr_latex src-block))
-          (float (plist-get attributes :float)))
+          (float (plist-get attributes :float))
+          (listings (plist-get info :latex-listings)))
       (cond
        ;; Case 1.  No source fontification.
-       ((not org-latex-listings)
+       ((not listings)
        (let* ((caption-str (org-latex--caption/label-string src-block info))
               (float-env
-               (cond ((and (not float) (plist-member attributes :float)) "%s")
-                     ((string= "multicolumn" float)
-                      (format "\\begin{figure*}[%s]\n%%s%s\n\\end{figure*}"
-                              org-latex-default-figure-position
-                              caption-str))
-                     ((or caption float)
-                      (format "\\begin{figure}[H]\n%%s%s\n\\end{figure}"
-                              caption-str))
+               (cond ((string= "multicolumn" float)
+                      (format "\\begin{figure*}[%s]\n%s%%s\n%s\\end{figure*}"
+                              (plist-get info :latex-default-figure-position)
+                              (if caption-above-p caption-str "")
+                              (if caption-above-p "" caption-str)))
+                     (caption (concat
+                               (if caption-above-p caption-str "")
+                               "%s"
+                               (if caption-above-p "" (concat "\n" 
caption-str))))
                      (t "%s"))))
          (format
           float-env
           (concat (format "\\begin{verbatim}\n%s\\end{verbatim}"
                           (org-export-format-code-default src-block info))))))
        ;; Case 2.  Custom environment.
-       (custom-env (format "\\begin{%s}\n%s\\end{%s}\n"
-                          custom-env
-                          (org-export-format-code-default src-block info)
-                          custom-env))
+       (custom-env
+       (let ((caption-str (org-latex--caption/label-string src-block info))
+              (formatted-src (org-export-format-code-default src-block info)))
+          (if (string-match-p "\\`[a-zA-Z0-9]+\\'" custom-env)
+             (format "\\begin{%s}\n%s\\end{%s}\n"
+                     custom-env
+                     (concat (and caption-above-p caption-str)
+                             formatted-src
+                             (and (not caption-above-p) caption-str))
+                     custom-env)
+           (format-spec custom-env
+                        `((?s . ,formatted-src)
+                          (?c . ,caption)
+                          (?f . ,float)
+                          (?l . ,(org-latex--label src-block info))
+                          (?o . ,(or (plist-get attributes :options) "")))))))
        ;; Case 3.  Use minted package.
-       ((eq org-latex-listings 'minted)
+       ((eq listings 'minted)
        (let* ((caption-str (org-latex--caption/label-string src-block info))
               (float-env
-               (cond ((and (not float) (plist-member attributes :float)) "%s")
-                     ((string= "multicolumn" float)
-                      (format "\\begin{listing*}\n%%s\n%s\\end{listing*}"
-                              caption-str))
-                     ((or caption float)
-                      (format "\\begin{listing}[H]\n%%s\n%s\\end{listing}"
-                              caption-str))
-                     (t "%s")))
+               (cond
+                ((string= "multicolumn" float)
+                 (format "\\begin{listing*}[%s]\n%s%%s\n%s\\end{listing*}"
+                         (plist-get info :latex-default-figure-position)
+                         (if caption-above-p caption-str "")
+                         (if caption-above-p "" caption-str)))
+                (caption
+                 (format "\\begin{listing}[%s]\n%s%%s\n%s\\end{listing}"
+                         (plist-get info :latex-default-figure-position)
+                         (if caption-above-p caption-str "")
+                         (if caption-above-p "" caption-str)))
+                ((string= "t" float)
+                 (concat (format "\\begin{listing}[%s]\n"
+                                 (plist-get info 
:latex-default-figure-position))
+                         "%s\n\\end{listing}"))
+                (t "%s")))
+              (options (plist-get info :latex-minted-options))
               (body
                (format
                 "\\begin{minted}[%s]{%s}\n%s\\end{minted}"
                 ;; Options.
-                (org-latex--make-option-string
-                 (if (or (not num-start)
-                         (assoc "linenos" org-latex-minted-options))
-                     org-latex-minted-options
-                   (append
-                    `(("linenos")
-                      ("firstnumber" ,(number-to-string (1+ num-start))))
-                    org-latex-minted-options)))
+                (concat
+                 (org-latex--make-option-string
+                  (if (or (not num-start) (assoc "linenos" options))
+                      options
+                    (append
+                     `(("linenos")
+                       ("firstnumber" ,(number-to-string (1+ num-start))))
+                     options)))
+                 (let ((local-options (plist-get attributes :options)))
+                   (and local-options (concat "," local-options))))
                 ;; Language.
-                (or (cadr (assq (intern lang) org-latex-minted-langs))
+                (or (cadr (assq (intern lang)
+                                (plist-get info :latex-minted-langs)))
                     (downcase lang))
                 ;; Source code.
                 (let* ((code-info (org-export-unravel-code src-block))
@@ -2126,7 +2919,7 @@ contextual information."
                                                          "\n")))))
                   (org-export-format-code
                    (car code-info)
-                   (lambda (loc num ref)
+                   (lambda (loc _num ref)
                      (concat
                       loc
                       (when ref
@@ -2142,7 +2935,9 @@ contextual information."
        ;; Case 4.  Use listings package.
        (t
        (let ((lst-lang
-              (or (cadr (assq (intern lang) org-latex-listings-langs)) lang))
+              (or (cadr (assq (intern lang)
+                              (plist-get info :latex-listings-langs)))
+                  lang))
              (caption-str
               (when caption
                 (let ((main (org-export-get-caption src-block))
@@ -2151,28 +2946,33 @@ contextual information."
                       (format "{%s}" (org-export-data main info))
                     (format "{[%s]%s}"
                             (org-export-data secondary info)
-                            (org-export-data main info)))))))
+                            (org-export-data main info))))))
+             (lst-opt (plist-get info :latex-listings-options)))
          (concat
           ;; Options.
           (format
            "\\lstset{%s}\n"
-           (org-latex--make-option-string
-            (append
-             org-latex-listings-options
-             (cond
-              ((and (not float) (plist-member attributes :float)) nil)
-              ((string= "multicolumn" float) '(("float" "*")))
-              ((and float (not (assoc "float" org-latex-listings-options)))
-               `(("float" ,org-latex-default-figure-position))))
-             `(("language" ,lst-lang))
-             (if label `(("label" ,label)) '(("label" " ")))
-             (if caption-str `(("caption" ,caption-str)) '(("caption" " ")))
-             (cond ((assoc "numbers" org-latex-listings-options) nil)
-                   ((not num-start) '(("numbers" "none")))
-                   ((zerop num-start) '(("numbers" "left")))
-                   (t `(("numbers" "left")
-                        ("firstnumber"
-                         ,(number-to-string (1+ num-start)))))))))
+           (concat
+            (org-latex--make-option-string
+             (append
+              lst-opt
+              (cond
+               ((and (not float) (plist-member attributes :float)) nil)
+               ((string= "multicolumn" float) '(("float" "*")))
+               ((and float (not (assoc "float" lst-opt)))
+                `(("float" ,(plist-get info :latex-default-figure-position)))))
+              `(("language" ,lst-lang))
+              (if label
+                  `(("label" ,(org-latex--label src-block info)))
+                '(("label" " ")))
+              (if caption-str `(("caption" ,caption-str)) '(("caption" " ")))
+              `(("captionpos" ,(if caption-above-p "t" "b")))
+              (cond ((assoc "numbers" lst-opt) nil)
+                    ((not num-start) '(("numbers" "none")))
+                    (t `(("firstnumber" ,(number-to-string (1+ num-start)))
+                         ("numbers" "left"))))))
+            (let ((local-options (plist-get attributes :options)))
+              (and local-options (concat "," local-options)))))
           ;; Source code.
           (format
            "\\begin{lstlisting}\n%s\\end{lstlisting}"
@@ -2183,21 +2983,21 @@ contextual information."
                                   (org-split-string (car code-info) "\n")))))
              (org-export-format-code
               (car code-info)
-              (lambda (loc num ref)
+              (lambda (loc _num ref)
                 (concat
                  loc
                  (when ref
                    ;; Ensure references are flushed to the right,
                    ;; separated with 6 spaces from the widest line of
                    ;; code
-                   (concat (make-string (+ (- max-width (length loc)) 6) ? )
+                   (concat (make-string (+ (- max-width (length loc)) 6) ?\s)
                            (format "(%s)" ref)))))
               nil (and retain-labels (cdr code-info))))))))))))
 
 
 ;;;; Statistics Cookie
 
-(defun org-latex-statistics-cookie (statistics-cookie contents info)
+(defun org-latex-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (replace-regexp-in-string
@@ -2206,11 +3006,11 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Strike-Through
 
-(defun org-latex-strike-through (strike-through contents info)
+(defun org-latex-strike-through (_strike-through contents info)
   "Transcode STRIKE-THROUGH from Org to LaTeX.
 CONTENTS is the text with strike-through markup.  INFO is a plist
 holding contextual information."
-  (org-latex--text-markup contents 'strike-through))
+  (org-latex--text-markup contents 'strike-through info))
 
 
 ;;;; Subscript
@@ -2219,22 +3019,11 @@ holding contextual information."
   "Transcode a subscript or superscript object.
 OBJECT is an Org object.  INFO is a plist used as a communication
 channel."
-  (let ((in-script-p
-        ;; Non-nil if object is already in a sub/superscript.
-        (let ((parent object))
-          (catch 'exit
-            (while (setq parent (org-export-get-parent parent))
-              (let ((type (org-element-type parent)))
-                (cond ((memq type '(subscript superscript))
-                       (throw 'exit t))
-                      ((memq type org-element-all-elements)
-                       (throw 'exit nil))))))))
-       (type (org-element-type object))
-       (output ""))
+  (let ((output ""))
     (org-element-map (org-element-contents object)
        (cons 'plain-text org-element-all-objects)
       (lambda (obj)
-       (case (org-element-type obj)
+       (cl-case (org-element-type obj)
          ((entity latex-fragment)
           (let ((data (org-trim (org-export-data obj info))))
             (string-match
@@ -2255,33 +3044,14 @@ channel."
                         (let ((blank (org-element-property :post-blank obj)))
                           (and blank (> blank 0) "\\ ")))))))
       info nil org-element-recursive-objects)
-    ;; Result.  Do not wrap into math mode if already in a subscript
-    ;; or superscript.  Do not wrap into curly brackets if OUTPUT is
-    ;; a single character.  Also merge consecutive subscript and
-    ;; superscript into the same math snippet.
-    (concat (and (not in-script-p)
-                (let ((prev (org-export-get-previous-element object info)))
-                  (or (not prev)
-                      (not (eq (org-element-type prev)
-                               (if (eq type 'subscript) 'superscript
-                                 'subscript)))
-                      (let ((blank (org-element-property :post-blank prev)))
-                        (and blank (> blank 0)))))
-                "$")
-           (if (eq (org-element-type object) 'subscript) "_" "^")
+    ;; Result.  Do not wrap into curly brackets if OUTPUT is a single
+    ;; character.
+    (concat (if (eq (org-element-type object) 'subscript) "_" "^")
            (and (> (length output) 1) "{")
            output
-           (and (> (length output) 1) "}")
-           (and (not in-script-p)
-                (or (let ((blank (org-element-property :post-blank object)))
-                      (and blank (> blank 0)))
-                    (not (eq (org-element-type
-                              (org-export-get-next-element object info))
-                             (if (eq type 'subscript) 'superscript
-                               'subscript))))
-                "$"))))
+           (and (> (length output) 1) "}"))))
 
-(defun org-latex-subscript (subscript contents info)
+(defun org-latex-subscript (subscript _contents info)
   "Transcode a SUBSCRIPT object from Org to LaTeX.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -2290,7 +3060,7 @@ contextual information."
 
 ;;;; Superscript
 
-(defun org-latex-superscript (superscript contents info)
+(defun org-latex-superscript (superscript _contents info)
   "Transcode a SUPERSCRIPT object from Org to LaTeX.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -2316,7 +3086,7 @@ contextual information."
       ;; "table.el" table.  Convert it using appropriate tools.
       (org-latex--table.el-table table info)
     (let ((type (or (org-export-read-attribute :attr_latex table :mode)
-                   org-latex-default-table-mode)))
+                   (plist-get info :latex-default-table-mode))))
       (cond
        ;; Case 1: Verbatim table.
        ((string= type "verbatim")
@@ -2333,10 +3103,12 @@ contextual information."
                  ;; table, insert their definition just after it.
                  (org-latex--delayed-footnotes-definitions table info)))))))
 
-(defun org-latex--align-string (table info)
+(defun org-latex--align-string (table info &optional math?)
   "Return an appropriate LaTeX alignment string.
 TABLE is the considered table.  INFO is a plist used as
-a communication channel."
+a communication channel.  When optional argument MATH? is
+non-nil, TABLE is meant to be a matrix, where all cells are
+centered."
   (or (org-export-read-attribute :attr_latex table :align)
       (let (align)
        ;; Extract column groups and alignment from first (non-rule)
@@ -2352,10 +3124,11 @@ a communication channel."
              ;; Check left border for the first cell only.
              (when (and (memq 'left borders) (not align))
                (push "|" align))
-             (push (case (org-export-table-cell-alignment cell info)
-                     (left "l")
-                     (right "r")
-                     (center "c"))
+             (push (if math? "c"       ;center cells in matrices
+                     (cl-case (org-export-table-cell-alignment cell info)
+                       (left "l")
+                       (right "r")
+                       (center "c")))
                    align)
              (when (memq 'right borders) (push "|" align))))
          info)
@@ -2376,14 +3149,15 @@ This function assumes TABLE has `org' as its `:type' 
property and
         (alignment (org-latex--align-string table info))
         ;; Determine environment for the table: longtable, tabular...
         (table-env (or (plist-get attr :environment)
-                       org-latex-default-table-environment))
+                       (plist-get info :latex-default-table-environment)))
         ;; If table is a float, determine environment: table, table*
         ;; or sidewaystable.
         (float-env (unless (member table-env '("longtable" "longtabu"))
                      (let ((float (plist-get attr :float)))
                        (cond
                         ((and (not float) (plist-member attr :float)) nil)
-                        ((string= float "sidewaystable") "sidewaystable")
+                        ((or (string= float "sidewaystable")
+                             (string= float "sideways")) "sidewaystable")
                         ((string= float "multicolumn") "table*")
                         ((or float
                              (org-element-property :caption table)
@@ -2392,23 +3166,26 @@ This function assumes TABLE has `org' as its `:type' 
property and
         ;; Extract others display options.
         (fontsize (let ((font (plist-get attr :font)))
                     (and font (concat font "\n"))))
-        (width (plist-get attr :width))
+        ;; "tabular" environment doesn't allow to define a width.
+        (width (and (not (equal table-env "tabular")) (plist-get attr :width)))
         (spreadp (plist-get attr :spread))
-        (placement (or (plist-get attr :placement)
-                       (format "[%s]" org-latex-default-figure-position)))
+        (placement
+         (or (plist-get attr :placement)
+             (format "[%s]" (plist-get info :latex-default-figure-position))))
         (centerp (if (plist-member attr :center) (plist-get attr :center)
-                   org-latex-tables-centered)))
+                   (plist-get info :latex-tables-centered)))
+        (caption-above-p (org-latex--caption-above-p table info)))
     ;; Prepare the final format string for the table.
     (cond
      ;; Longtable.
      ((equal "longtable" table-env)
       (concat (and fontsize (concat "{" fontsize))
              (format "\\begin{longtable}{%s}\n" alignment)
-             (and org-latex-table-caption-above
+             (and caption-above-p
                   (org-string-nw-p caption)
                   (concat caption "\\\\\n"))
              contents
-             (and (not org-latex-table-caption-above)
+             (and (not caption-above-p)
                   (org-string-nw-p caption)
                   (concat caption "\\\\\n"))
              "\\end{longtable}\n"
@@ -2421,11 +3198,11 @@ This function assumes TABLE has `org' as its `:type' 
property and
                          (format " %s %s "
                                  (if spreadp "spread" "to") width) "")
                      alignment)
-             (and org-latex-table-caption-above
+             (and caption-above-p
                   (org-string-nw-p caption)
                   (concat caption "\\\\\n"))
              contents
-             (and (not org-latex-table-caption-above)
+             (and (not caption-above-p)
                   (org-string-nw-p caption)
                   (concat caption "\\\\\n"))
              "\\end{longtabu}\n"
@@ -2434,9 +3211,15 @@ This function assumes TABLE has `org' as its `:type' 
property and
      (t (concat (cond
                 (float-env
                  (concat (format "\\begin{%s}%s\n" float-env placement)
-                         (if org-latex-table-caption-above caption "")
+                         (if caption-above-p caption "")
                          (when centerp "\\centering\n")
                          fontsize))
+                ((and (not float-env) caption)
+                 (concat
+                  (and centerp "\\begin{center}\n" )
+                  (if caption-above-p caption "")
+                  (cond ((and fontsize centerp) fontsize)
+                        (fontsize (concat "{" fontsize)))))
                 (centerp (concat "\\begin{center}\n" fontsize))
                 (fontsize (concat "{" fontsize)))
                (cond ((equal "tabu" table-env)
@@ -2454,8 +3237,13 @@ This function assumes TABLE has `org' as its `:type' 
property and
                                 table-env)))
                (cond
                 (float-env
-                 (concat (if org-latex-table-caption-above "" caption)
+                 (concat (if caption-above-p "" (concat "\n" caption))
                          (format "\n\\end{%s}" float-env)))
+                ((and (not float-env) caption)
+                 (concat
+                  (if caption-above-p "" (concat "\n" caption))
+                  (and centerp "\n\\end{center}")
+                  (and fontsize (not centerp) "}")))
                 (centerp "\n\\end{center}")
                 (fontsize "}")))))))
 
@@ -2489,10 +3277,10 @@ property."
        (let ((n 0) (pos 0))
          (while (and (< (length output) pos)
                      (setq pos (string-match "^\\\\hline\n?" output pos)))
-           (incf n)
+           (cl-incf n)
            (unless (= n 2) (setq output (replace-match "" nil nil output))))))
       (let ((centerp (if (plist-member attr :center) (plist-get attr :center)
-                      org-latex-tables-centered)))
+                      (plist-get info :latex-tables-centered))))
        (if (not centerp) output
          (format "\\begin{center}\n%s\n\\end{center}" output))))))
 
@@ -2503,12 +3291,10 @@ TABLE is the table type element to transcode.  INFO is 
a plist
 used as a communication channel.
 
 This function assumes TABLE has `org' as its `:type' property and
-`inline-math' or `math' as its `:mode' attribute.."
-  (let* ((caption (org-latex--caption/label-string table info))
-        (attr (org-export-read-attribute :attr_latex table))
-        (inlinep (equal (plist-get attr :mode) "inline-math"))
+`inline-math' or `math' as its `:mode' attribute."
+  (let* ((attr (org-export-read-attribute :attr_latex table))
         (env (or (plist-get attr :environment)
-                 org-latex-default-table-environment))
+                 (plist-get info :latex-default-table-environment)))
         (contents
          (mapconcat
           (lambda (row)
@@ -2519,38 +3305,17 @@ This function assumes TABLE has `org' as its `:type' 
property and
                (mapconcat
                 (lambda (cell)
                   (substring (org-element-interpret-data cell) 0 -1))
-                (org-element-map row 'table-cell 'identity info) "&")
+                (org-element-map row 'table-cell #'identity info) "&")
                (or (cdr (assoc env org-latex-table-matrix-macros)) "\\\\")
                "\n")))
-          (org-element-map table 'table-row 'identity info) ""))
-        ;; Variables related to math clusters (contiguous math tables
-        ;; of the same type).
-        (mode (org-export-read-attribute :attr_latex table :mode))
-        (prev (org-export-get-previous-element table info))
-        (next (org-export-get-next-element table info))
-        (same-mode-p
-         (lambda (table)
-           ;; Non-nil when TABLE has the same mode as current table.
-           (string= (or (org-export-read-attribute :attr_latex table :mode)
-                        org-latex-default-table-mode)
-                    mode))))
+          (org-element-map table 'table-row #'identity info) "")))
     (concat
-     ;; Opening string.  If TABLE is in the middle of a table cluster,
-     ;; do not insert any.
-     (cond ((and prev
-                (eq (org-element-type prev) 'table)
-                (memq (org-element-property :post-blank prev) '(0 nil))
-                (funcall same-mode-p prev))
-           nil)
-          (inlinep "\\(")
-          ((org-string-nw-p caption) (concat "\\begin{equation}\n" caption))
-          (t "\\["))
      ;; Prefix.
-     (or (plist-get attr :math-prefix) "")
+     (plist-get attr :math-prefix)
      ;; Environment.  Also treat special cases.
-     (cond ((equal env "array")
-           (let ((align (org-latex--align-string table info)))
-             (format "\\begin{array}{%s}\n%s\\end{array}" align contents)))
+     (cond ((member env '("array" "tabular"))
+           (format "\\begin{%s}{%s}\n%s\\end{%s}"
+                   env (org-latex--align-string table info t) contents env))
           ((assoc env org-latex-table-matrix-macros)
            (format "\\%s%s{\n%s}"
                    env
@@ -2558,28 +3323,7 @@ This function assumes TABLE has `org' as its `:type' 
property and
                    contents))
           (t (format "\\begin{%s}\n%s\\end{%s}" env contents env)))
      ;; Suffix.
-     (or (plist-get attr :math-suffix) "")
-     ;; Closing string.  If TABLE is in the middle of a table cluster,
-     ;; do not insert any.  If it closes such a cluster, be sure to
-     ;; close the cluster with a string matching the opening string.
-     (cond ((and next
-                (eq (org-element-type next) 'table)
-                (memq (org-element-property :post-blank table) '(0 nil))
-                (funcall same-mode-p next))
-           nil)
-          (inlinep "\\)")
-          ;; Find cluster beginning to know which environment to use.
-          ((let ((cluster-beg table) prev)
-             (while (and (setq prev (org-export-get-previous-element
-                                     cluster-beg info))
-                         (memq (org-element-property :post-blank prev)
-                               '(0 nil))
-                         (funcall same-mode-p prev))
-               (setq cluster-beg prev))
-             (and (or (org-element-property :caption cluster-beg)
-                      (org-element-property :name cluster-beg))
-                  "\n\\end{equation}")))
-          (t "\\]")))))
+     (plist-get attr :math-suffix))))
 
 
 ;;;; Table Cell
@@ -2588,16 +3332,18 @@ This function assumes TABLE has `org' as its `:type' 
property and
   "Transcode a TABLE-CELL element from Org to LaTeX.
 CONTENTS is the cell contents.  INFO is a plist used as
 a communication channel."
-  (concat (if (and contents
-                  org-latex-table-scientific-notation
-                  (string-match orgtbl-exp-regexp contents))
-             ;; Use appropriate format string for scientific
-             ;; notation.
-             (format org-latex-table-scientific-notation
-                     (match-string 1 contents)
-                     (match-string 2 contents))
-           contents)
-         (when (org-export-get-next-element table-cell info) " & ")))
+  (concat
+   (let ((scientific-format (plist-get info :latex-table-scientific-notation)))
+     (if (and contents
+             scientific-format
+             (string-match orgtbl-exp-regexp contents))
+        ;; Use appropriate format string for scientific
+        ;; notation.
+        (format scientific-format
+                (match-string 1 contents)
+                (match-string 2 contents))
+       contents))
+   (when (org-export-get-next-element table-cell info) " & ")))
 
 
 ;;;; Table Row
@@ -2606,87 +3352,106 @@ a communication channel."
   "Transcode a TABLE-ROW element from Org to LaTeX.
 CONTENTS is the contents of the row.  INFO is a plist used as
 a communication channel."
-  ;; Rules are ignored since table separators are deduced from
-  ;; borders of the current row.
-  (when (eq (org-element-property :type table-row) 'standard)
-    (let* ((attr (org-export-read-attribute :attr_latex
-                                           (org-export-get-parent table-row)))
-          (longtablep (member (or (plist-get attr :environment)
-                                   org-latex-default-table-environment)
-                               '("longtable" "longtabu")))
-          (booktabsp (if (plist-member attr :booktabs)
-                         (plist-get attr :booktabs)
-                       org-latex-tables-booktabs))
-          ;; TABLE-ROW's borders are extracted from its first cell.
-          (borders (org-export-table-cell-borders
-                    (car (org-element-contents table-row)) info)))
+  (let* ((attr (org-export-read-attribute :attr_latex
+                                         (org-export-get-parent table-row)))
+        (booktabsp (if (plist-member attr :booktabs) (plist-get attr :booktabs)
+                     (plist-get info :latex-tables-booktabs)))
+        (longtablep
+         (member (or (plist-get attr :environment)
+                     (plist-get info :latex-default-table-environment))
+                 '("longtable" "longtabu"))))
+    (if (eq (org-element-property :type table-row) 'rule)
+       (cond
+        ((not booktabsp) "\\hline")
+        ((not (org-export-get-previous-element table-row info)) "\\toprule")
+        ((not (org-export-get-next-element table-row info)) "\\bottomrule")
+        ((and longtablep
+              (org-export-table-row-ends-header-p
+               (org-export-get-previous-element table-row info) info))
+         "")
+        (t "\\midrule"))
       (concat
        ;; When BOOKTABS are activated enforce top-rule even when no
        ;; hline was specifically marked.
-       (cond ((and booktabsp (memq 'top borders)) "\\toprule\n")
-            ((and (memq 'top borders) (memq 'above borders)) "\\hline\n"))
+       (and booktabsp (not (org-export-get-previous-element table-row info))
+           "\\toprule\n")
        contents "\\\\\n"
        (cond
-       ;; Special case for long tables. Define header and footers.
+       ;; Special case for long tables.  Define header and footers.
        ((and longtablep (org-export-table-row-ends-header-p table-row info))
-        (format "%s
+        (let ((columns (cdr (org-export-table-dimensions
+                             (org-export-get-parent-table table-row) info))))
+          (format "%s
+\\endfirsthead
+\\multicolumn{%d}{l}{%s} \\\\
+%s
+%s \\\\\n
+%s
 \\endhead
-%s\\multicolumn{%d}{r}{Continued on next page} \\\\
+%s\\multicolumn{%d}{r}{%s} \\\\
 \\endfoot
 \\endlastfoot"
-                (if booktabsp "\\midrule" "\\hline")
-                (if booktabsp "\\midrule" "\\hline")
-                ;; Number of columns.
-                (cdr (org-export-table-dimensions
-                      (org-export-get-parent-table table-row) info))))
+                  (if booktabsp "\\midrule" "\\hline")
+                  columns
+                  (org-latex--translate "Continued from previous page" info)
+                  (cond
+                   ((not (org-export-table-row-starts-header-p table-row info))
+                    "")
+                   (booktabsp "\\toprule\n")
+                   (t "\\hline\n"))
+                  contents
+                  (if booktabsp "\\midrule" "\\hline")
+                  (if booktabsp "\\midrule" "\\hline")
+                  columns
+                  (org-latex--translate "Continued on next page" info))))
        ;; When BOOKTABS are activated enforce bottom rule even when
        ;; no hline was specifically marked.
-       ((and booktabsp (memq 'bottom borders)) "\\bottomrule")
-       ((and (memq 'bottom borders) (memq 'below borders)) "\\hline")
-       ((memq 'below borders) (if booktabsp "\\midrule" "\\hline")))))))
+       ((and booktabsp (not (org-export-get-next-element table-row info)))
+        "\\bottomrule"))))))
 
 
 ;;;; Target
 
-(defun org-latex-target (target contents info)
+(defun org-latex-target (target _contents info)
   "Transcode a TARGET object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format "\\label{%s}"
-         (org-export-solidify-link-text (org-element-property :value target))))
+  (format "\\label{%s}" (org-latex--label target info)))
 
 
 ;;;; Timestamp
 
-(defun org-latex-timestamp (timestamp contents info)
+(defun org-latex-timestamp (timestamp _contents info)
   "Transcode a TIMESTAMP object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (let ((value (org-latex-plain-text
-               (org-timestamp-translate timestamp) info)))
-    (case (org-element-property :type timestamp)
-      ((active active-range) (format org-latex-active-timestamp-format value))
-      ((inactive inactive-range)
-       (format org-latex-inactive-timestamp-format value))
-      (otherwise (format org-latex-diary-timestamp-format value)))))
+  (let ((value (org-latex-plain-text (org-timestamp-translate timestamp) 
info)))
+    (format
+     (plist-get info
+               (cl-case (org-element-property :type timestamp)
+                 ((active active-range) :latex-active-timestamp-format)
+                 ((inactive inactive-range) :latex-inactive-timestamp-format)
+                 (otherwise :latex-diary-timestamp-format)))
+     value)))
 
 
 ;;;; Underline
 
-(defun org-latex-underline (underline contents info)
+(defun org-latex-underline (_underline contents info)
   "Transcode UNDERLINE from Org to LaTeX.
 CONTENTS is the text with underline markup.  INFO is a plist
 holding contextual information."
-  (org-latex--text-markup contents 'underline))
+  (org-latex--text-markup contents 'underline info))
 
 
 ;;;; Verbatim
 
-(defun org-latex-verbatim (verbatim contents info)
+(defun org-latex-verbatim (verbatim _contents info)
   "Transcode a VERBATIM object from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (org-latex--text-markup (org-element-property :value verbatim) 'verbatim))
+  (org-latex--text-markup
+   (org-element-property :value verbatim) 'verbatim info))
 
 
 ;;;; Verse Block
@@ -2701,16 +3466,15 @@ contextual information."
    ;; character and change each white space at beginning of a line
    ;; into a space of 1 em.  Also change each blank line with
    ;; a vertical space of 1 em.
-   (progn
-     (setq contents (replace-regexp-in-string
-                    "^ *\\\\\\\\$" "\\\\vspace*{1em}"
-                    (replace-regexp-in-string
-                     "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents)))
-     (while (string-match "^[ \t]+" contents)
-       (let ((new-str (format "\\hspace*{%dem}"
-                             (length (match-string 0 contents)))))
-        (setq contents (replace-match new-str nil t contents))))
-     (format "\\begin{verse}\n%s\\end{verse}" contents))))
+   (format "\\begin{verse}\n%s\\end{verse}"
+          (replace-regexp-in-string
+           "^[ \t]+" (lambda (m) (format "\\hspace*{%dem}" (length m)))
+           (replace-regexp-in-string
+            "^[ \t]*\\\\\\\\$" "\\vspace*{1em}"
+            (replace-regexp-in-string
+             "\\([ \t]*\\\\\\\\\\)?[ \t]*\n" "\\\\\n"
+             contents nil t) nil t) nil t))
+   info))
 
 
 
@@ -2753,9 +3517,9 @@ is non-nil."
 
 ;;;###autoload
 (defun org-latex-convert-region-to-latex ()
-  "Assume the current region has org-mode syntax, and convert it to LaTeX.
+  "Assume the current region has Org syntax, and convert it to LaTeX.
 This can be used in any buffer.  For example, you can write an
-itemized list in org-mode syntax in an LaTeX buffer and use this
+itemized list in Org syntax in an LaTeX buffer and use this
 command to convert it."
   (interactive)
   (org-export-replace-region-by 'latex))
@@ -2831,86 +3595,78 @@ Return PDF file's name."
   "Compile a TeX file.
 
 TEXFILE is the name of the file being compiled.  Processing is
-done through the command specified in `org-latex-pdf-process'.
+done through the command specified in `org-latex-pdf-process',
+which see.  Output is redirected to \"*Org PDF LaTeX Output*\"
+buffer.
 
 When optional argument SNIPPET is non-nil, TEXFILE is a temporary
 file used to preview a LaTeX snippet.  In this case, do not
-create a log buffer and do not bother removing log files.
-
-Return PDF file name or an error if it couldn't be produced."
-  (let* ((base-name (file-name-sans-extension (file-name-nondirectory 
texfile)))
-        (full-name (file-truename texfile))
-        (out-dir (file-name-directory texfile))
-        ;; Properly set working directory for compilation.
-        (default-directory (if (file-name-absolute-p texfile)
-                               (file-name-directory full-name)
-                             default-directory))
-        errors)
-    (unless snippet (message "Processing LaTeX file %s..." texfile))
-    (save-window-excursion
-      (cond
-       ;; A function is provided: Apply it.
-       ((functionp org-latex-pdf-process)
-       (funcall org-latex-pdf-process (shell-quote-argument texfile)))
-       ;; A list is provided: Replace %b, %f and %o with appropriate
-       ;; values in each command before applying it.  Output is
-       ;; redirected to "*Org PDF LaTeX Output*" buffer.
-       ((consp org-latex-pdf-process)
-       (let ((outbuf (and (not snippet)
-                          (get-buffer-create "*Org PDF LaTeX Output*"))))
-         (mapc
-          (lambda (command)
-            (shell-command
-             (replace-regexp-in-string
-              "%b" (shell-quote-argument base-name)
-              (replace-regexp-in-string
-               "%f" (shell-quote-argument full-name)
-               (replace-regexp-in-string
-                "%o" (shell-quote-argument out-dir) command t t) t t) t t)
-             outbuf))
-          org-latex-pdf-process)
-         ;; Collect standard errors from output buffer.
-         (setq errors (and (not snippet) (org-latex--collect-errors outbuf)))))
-       (t (error "No valid command to process to PDF")))
-      (let ((pdffile (concat out-dir base-name ".pdf")))
-       ;; Check for process failure.  Provide collected errors if
-       ;; possible.
-       (if (not (file-exists-p pdffile))
-           (error "PDF file %s wasn't produced%s" pdffile
-                  (if errors (concat ": " errors) ""))
-         ;; Else remove log files, when specified, and signal end of
-         ;; process to user, along with any error encountered.
-         (when (and (not snippet) org-latex-remove-logfiles)
-           (dolist (file (directory-files
-                          out-dir t
-                          (concat (regexp-quote base-name)
-                                  "\\(?:\\.[0-9]+\\)?"
-                                  "\\."
-                                  (regexp-opt org-latex-logfiles-extensions))))
-             (delete-file file)))
-         (message (concat "Process completed"
-                          (if (not errors) "."
-                            (concat " with errors: " errors)))))
-       ;; Return output file name.
-       pdffile))))
-
-(defun org-latex--collect-errors (buffer)
-  "Collect some kind of errors from \"pdflatex\" command output.
-
-BUFFER is the buffer containing output.
-
-Return collected error types as a string, or nil if there was
-none."
+create a log buffer and do not remove log files.
+
+Return PDF file name or raise an error if it couldn't be
+produced."
+  (unless snippet (message "Processing LaTeX file %s..." texfile))
+  (let* ((compiler
+         (or (with-temp-buffer
+               (save-excursion (insert-file-contents texfile))
+               (and (search-forward-regexp (regexp-opt org-latex-compilers)
+                                           (line-end-position 2)
+                                           t)
+                    (progn (beginning-of-line) (looking-at-p "%"))
+                    (match-string 0)))
+             "pdflatex"))
+        (process (if (functionp org-latex-pdf-process) org-latex-pdf-process
+                   ;; Replace "%latex" and "%bibtex" with,
+                   ;; respectively, "%L" and "%B" so as to adhere to
+                   ;; `format-spec' specifications.
+                   (mapcar (lambda (command)
+                             (replace-regexp-in-string
+                              "%\\(?:bib\\|la\\)tex\\>"
+                              (lambda (m) (upcase (substring m 0 2)))
+                              command))
+                           org-latex-pdf-process)))
+         (spec `((?B . ,(shell-quote-argument org-latex-bib-compiler))
+                 (?L . ,(shell-quote-argument compiler))))
+        (log-buf-name "*Org PDF LaTeX Output*")
+         (log-buf (and (not snippet) (get-buffer-create log-buf-name)))
+         (outfile (org-compile-file texfile process "pdf"
+                                   (format "See %S for details" log-buf-name)
+                                   log-buf spec)))
+    (unless snippet
+      (when org-latex-remove-logfiles
+       (mapc #'delete-file
+             (directory-files
+              (file-name-directory outfile)
+              t
+              (concat (regexp-quote (file-name-base outfile))
+                      "\\(?:\\.[0-9]+\\)?\\."
+                      (regexp-opt org-latex-logfiles-extensions))
+              t)))
+      (let ((warnings (org-latex--collect-warnings log-buf)))
+       (message (concat "PDF file produced"
+                        (cond
+                         ((eq warnings 'error) " with errors.")
+                         (warnings (concat " with warnings: " warnings))
+                         (t "."))))))
+    ;; Return output file name.
+    outfile))
+
+(defun org-latex--collect-warnings (buffer)
+  "Collect some warnings from \"pdflatex\" command output.
+BUFFER is the buffer containing output.  Return collected
+warnings types as a string, `error' if a LaTeX error was
+encountered or nil if there was none."
   (with-current-buffer buffer
     (save-excursion
       (goto-char (point-max))
       (when (re-search-backward "^[ \t]*This is .*?TeX.*?Version" nil t)
-       (let ((case-fold-search t)
-             (errors ""))
-         (dolist (latex-error org-latex-known-errors)
-           (when (save-excursion (re-search-forward (car latex-error) nil t))
-             (setq errors (concat errors " " (cdr latex-error)))))
-         (and (org-string-nw-p errors) (org-trim errors)))))))
+       (if (re-search-forward "^!" nil t) 'error
+         (let ((case-fold-search t)
+               (warnings ""))
+           (dolist (warning org-latex-known-warnings)
+             (when (save-excursion (re-search-forward (car warning) nil t))
+               (setq warnings (concat warnings " " (cdr warning)))))
+           (org-string-nw-p (org-trim warnings))))))))
 
 ;;;###autoload
 (defun org-latex-publish-to-latex (plist filename pub-dir)
@@ -2936,9 +3692,13 @@ Return output file name."
   ;; in working directory and then moved to publishing directory.
   (org-publish-attachment
    plist
-   (org-latex-compile
-    (org-publish-org-to
-     'latex filename ".tex" plist (file-name-directory filename)))
+   ;; Default directory could be anywhere when this function is
+   ;; called.  We ensure it is set to source file directory during
+   ;; compilation so as to not break links to external documents.
+   (let ((default-directory (file-name-directory filename)))
+     (org-latex-compile
+      (org-publish-org-to
+       'latex filename ".tex" plist (file-name-directory filename))))
    pub-dir))
 
 
diff --git a/lisp/org/ox-man.el b/lisp/org/ox-man.el
index e5b1479..71718ab 100644
--- a/lisp/org/ox-man.el
+++ b/lisp/org/ox-man.el
@@ -1,4 +1,4 @@
-;; ox-man.el --- Man Back-End for Org Export Engine
+;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
 
@@ -29,18 +29,17 @@
 ;;
 ;;   M-: (org-export-to-buffer 'man "*Test Man*") RET
 ;;
-;; in an org-mode buffer then switch to the buffer to see the Man
-;; export.  See ox.el for more details on how this exporter works.
+;; in an Org buffer then switch to the buffer to see the Man export.
+;; See ox.el for more details on how this exporter works.
 ;;
 ;; It introduces one new buffer keywords:
 ;; "MAN_CLASS_OPTIONS".
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'ox)
 
-(eval-when-compile (require 'cl))
-
 (defvar org-export-man-default-packages-alist)
 (defvar org-export-man-packages-alist)
 (defvar orgtbl-exp-regexp)
@@ -53,10 +52,7 @@
   '((babel-call . org-man-babel-call)
     (bold . org-man-bold)
     (center-block . org-man-center-block)
-    (clock . org-man-clock)
     (code . org-man-code)
-    (comment . (lambda (&rest args) ""))
-    (comment-block . (lambda (&rest args) ""))
     (drawer . org-man-drawer)
     (dynamic-block . org-man-dynamic-block)
     (entity . org-man-entity)
@@ -76,13 +72,13 @@
     (keyword . org-man-keyword)
     (line-break . org-man-line-break)
     (link . org-man-link)
+    (node-property . org-man-node-property)
     (paragraph . org-man-paragraph)
     (plain-list . org-man-plain-list)
     (plain-text . org-man-plain-text)
     (planning . org-man-planning)
-    (property-drawer . (lambda (&rest args) ""))
+    (property-drawer . org-man-property-drawer)
     (quote-block . org-man-quote-block)
-    (quote-section . org-man-quote-section)
     (radio-target . org-man-radio-target)
     (section . org-man-section)
     (special-block . org-man-special-block)
@@ -100,9 +96,8 @@
     (underline . org-man-underline)
     (verbatim . org-man-verbatim)
     (verse-block . org-man-verse-block))
-  :export-block "MAN"
   :menu-entry
-  '(?m "Export to MAN"
+  '(?M "Export to MAN"
        ((?m "As MAN file" org-man-export-to-man)
        (?p "As PDF file" org-man-export-to-pdf)
        (?o "As PDF file and open"
@@ -112,7 +107,13 @@
   :options-alist
   '((:man-class "MAN_CLASS" nil nil t)
     (:man-class-options "MAN_CLASS_OPTIONS" nil nil t)
-    (:man-header-extra "MAN_HEADER" nil nil newline)))
+    (:man-header-extra "MAN_HEADER" nil nil newline)
+    ;; Other variables.
+    (:man-tables-centered nil nil org-man-tables-centered)
+    (:man-tables-verbatim nil nil org-man-tables-verbatim)
+    (:man-table-scientific-notation nil nil org-man-table-scientific-notation)
+    (:man-source-highlight nil nil org-man-source-highlight)
+    (:man-source-highlight-langs nil nil org-man-source-highlight-langs)))
 
 
 
@@ -199,21 +200,6 @@ in this list - but it does not hurt if it is present."
            (string :tag "Listings language"))))
 
 
-
-(defvar org-man-custom-lang-environments nil
-  "Alist mapping languages to language-specific Man environments.
-
-It is used during export of src blocks by the listings and
-man packages.  For example,
-
-  (setq org-man-custom-lang-environments
-     \\='((python \"pythoncode\")))
-
-would have the effect that if org encounters begin_src python
-during man export."
-)
-
-
 ;;; Compilation
 
 (defcustom org-man-pdf-process
@@ -222,11 +208,13 @@ during man export."
     "tbl %f | eqn | groff -man | ps2pdf - > %b.pdf")
 
   "Commands to process a Man file to a PDF file.
+
 This is a list of strings, each of them will be given to the
 shell as a command.  %f in the command will be replaced by the
-full file name, %b by the file base name (i.e. without directory
-and extension parts) and %o by the base directory of the file.
-
+relative file name, %F by the absolute file name, %b by the file
+base name (i.e. without directory and extension parts), %o by the
+base directory of the file and %O by the absolute file name of
+the output file.
 
 By default, Org uses 3 runs of to do the processing.
 
@@ -305,7 +293,8 @@ This function shouldn't be used for floats.  See
   "Return complete document string after Man conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
-  (let* ((title (org-export-data (plist-get info :title) info))
+  (let* ((title (when (plist-get info :with-title)
+                 (org-export-data (plist-get info :title) info)))
         (attr (read (format "(%s)"
                             (mapconcat
                              #'identity
@@ -338,7 +327,7 @@ holding export options."
 
 ;;; Bold
 
-(defun org-man-bold (bold contents info)
+(defun org-man-bold (_bold contents _info)
   "Transcode BOLD from Org to Man.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
@@ -347,7 +336,7 @@ contextual information."
 
 ;;; Center Block
 
-(defun org-man-center-block (center-block contents info)
+(defun org-man-center-block (center-block contents _info)
   "Transcode a CENTER-BLOCK element from Org to Man.
 CONTENTS holds the contents of the center block.  INFO is a plist
 holding contextual information."
@@ -358,37 +347,18 @@ holding contextual information."
            contents)))
 
 
-;;; Clock
-
-(defun org-man-clock (clock contents info)
-  "Transcode a CLOCK element from Org to Man.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  "" )
-
-
 ;;; Code
 
-(defun org-man-code (code contents info)
+(defun org-man-code (code _contents _info)
   "Transcode a CODE object from Org to Man.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
   (format "\\fC%s\\fP" code))
 
 
-;;; Comment
-;;
-;; Comments are ignored.
-
-
-;;; Comment Block
-;;
-;; Comment Blocks are ignored.
-
-
 ;;; Drawer
 
-(defun org-man-drawer (drawer contents info)
+(defun org-man-drawer (_drawer contents _info)
   "Transcode a DRAWER element from Org to Man.
    DRAWER holds the drawer information
    CONTENTS holds the contents of the block.
@@ -398,7 +368,7 @@ channel."
 
 ;;; Dynamic Block
 
-(defun org-man-dynamic-block (dynamic-block contents info)
+(defun org-man-dynamic-block (dynamic-block contents _info)
   "Transcode a DYNAMIC-BLOCK element from Org to Man.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information.  See `org-export-data'."
@@ -407,7 +377,7 @@ holding contextual information.  See `org-export-data'."
 
 ;;; Entity
 
-(defun org-man-entity (entity contents info)
+(defun org-man-entity (entity _contents _info)
   "Transcode an ENTITY object from Org to Man.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
@@ -416,7 +386,7 @@ contextual information."
 
 ;;; Example Block
 
-(defun org-man-example-block (example-block contents info)
+(defun org-man-example-block (example-block _contents info)
   "Transcode an EXAMPLE-BLOCK element from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
@@ -428,7 +398,7 @@ information."
 
 ;;; Export Block
 
-(defun org-man-export-block (export-block contents info)
+(defun org-man-export-block (export-block _contents _info)
   "Transcode a EXPORT-BLOCK element from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (string= (org-element-property :type export-block) "MAN")
@@ -437,7 +407,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;; Export Snippet
 
-(defun org-man-export-snippet (export-snippet contents info)
+(defun org-man-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (eq (org-export-snippet-backend export-snippet) 'man)
@@ -446,7 +416,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;; Fixed Width
 
-(defun org-man-fixed-width (fixed-width contents info)
+(defun org-man-fixed-width (fixed-width _contents _info)
   "Transcode a FIXED-WIDTH element from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-man--wrap-label
@@ -472,16 +442,15 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 CONTENTS holds the contents of the headline.  INFO is a plist
 holding contextual information."
   (let* ((level (org-export-get-relative-level headline info))
-                (numberedp (org-export-numbered-headline-p headline info))
-                ;; Section formatting will set two placeholders: one for the
-                ;; title and the other for the contents.
-                (section-fmt
-                 (case level
-                       (1 ".SH \"%s\"\n%s")
-                       (2 ".SS \"%s\"\n%s")
-                       (3 ".SS \"%s\"\n%s")
-                       (t nil)))
-                (text (org-export-data (org-element-property :title headline) 
info)))
+        ;; Section formatting will set two placeholders: one for the
+        ;; title and the other for the contents.
+        (section-fmt
+         (pcase level
+           (1 ".SH \"%s\"\n%s")
+           (2 ".SS \"%s\"\n%s")
+           (3 ".SS \"%s\"\n%s")
+           (_ nil)))
+        (text (org-export-data (org-element-property :title headline) info)))
 
     (cond
      ;; Case 1: This is a footnote section: ignore it.
@@ -493,20 +462,20 @@ holding contextual information."
      ((or (not section-fmt) (org-export-low-level-p headline info))
       ;; Build the real contents of the sub-tree.
       (let ((low-level-body
-                        (concat
-                         ;; If the headline is the first sibling, start a list.
-                         (when (org-export-first-sibling-p headline info)
-                               (format "%s\n" ".RS"))
-                         ;; Itemize headline
-                         ".TP\n.ft I\n" text "\n.ft\n"
-                         contents ".RE")))
-               ;; If headline is not the last sibling simply return
-               ;; LOW-LEVEL-BODY.  Otherwise, also close the list, before any
-               ;; blank line.
-               (if (not (org-export-last-sibling-p headline info)) 
low-level-body
-                 (replace-regexp-in-string
-                  "[ \t\n]*\\'" ""
-                  low-level-body))))
+            (concat
+             ;; If the headline is the first sibling, start a list.
+             (when (org-export-first-sibling-p headline info)
+               (format "%s\n" ".RS"))
+             ;; Itemize headline
+             ".TP\n.ft I\n" text "\n.ft\n"
+             contents ".RE")))
+       ;; If headline is not the last sibling simply return
+       ;; LOW-LEVEL-BODY.  Otherwise, also close the list, before any
+       ;; blank line.
+       (if (not (org-export-last-sibling-p headline info)) low-level-body
+         (replace-regexp-in-string
+          "[ \t\n]*\\'" ""
+          low-level-body))))
 
      ;; Case 3. Standard headline.  Export it as a section.
      (t (format section-fmt text contents )))))
@@ -520,23 +489,22 @@ holding contextual information."
 
 ;;; Inline Src Block
 
-(defun org-man-inline-src-block (inline-src-block contents info)
+(defun org-man-inline-src-block (inline-src-block _contents info)
   "Transcode an INLINE-SRC-BLOCK element from Org to Man.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (let* ((code (org-element-property :value inline-src-block)))
     (cond
-     (org-man-source-highlight
-      (let* ((tmpdir (if (featurep 'xemacs)
-                         temp-directory
-                       temporary-file-directory ))
+     ((plist-get info :man-source-highlight)
+      (let* ((tmpdir temporary-file-directory)
              (in-file  (make-temp-name
                         (expand-file-name "srchilite" tmpdir)))
              (out-file (make-temp-name
                         (expand-file-name "reshilite" tmpdir)))
              (org-lang (org-element-property :language inline-src-block))
-             (lst-lang (cadr (assq (intern org-lang)
-                                   org-man-source-highlight-langs)))
+             (lst-lang
+             (cadr (assq (intern org-lang)
+                         (plist-get info :man-source-highlight-langs))))
 
              (cmd (concat (expand-file-name "source-highlight")
                           " -s " lst-lang
@@ -564,7 +532,7 @@ contextual information."
 ;;; Inlinetask
 ;;; Italic
 
-(defun org-man-italic (italic contents info)
+(defun org-man-italic (_italic contents _info)
   "Transcode ITALIC from Org to Man.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
@@ -575,17 +543,15 @@ contextual information."
 
 
 (defun org-man-item (item contents info)
-
   "Transcode an ITEM element from Org to Man.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-
   (let* ((bullet (org-element-property :bullet item))
          (type (org-element-property :type (org-element-property :parent 
item)))
-         (checkbox (case (org-element-property :checkbox item)
-                     (on "\\o'\\(sq\\(mu'")                    ;;
-                     (off "\\(sq ")                                    ;;
-                     (trans "\\o'\\(sq\\(mi'"   ))) ;;
+         (checkbox (pcase (org-element-property :checkbox item)
+                     (`on "\\o'\\(sq\\(mu'")
+                     (`off "\\(sq ")
+                     (`trans "\\o'\\(sq\\(mi'")))
 
          (tag (let ((tag (org-element-property :tag item)))
                 ;; Check-boxes must belong to the tag.
@@ -593,24 +559,22 @@ contextual information."
                                  (concat checkbox
                                          (org-export-data tag info)))))))
 
-    (if (and (null tag )
-                        (null checkbox))
-               (let* ((bullet (org-trim bullet))
-                          (marker (cond  ((string= "-" bullet) "\\(em")
-                                                         ((string= "*" bullet) 
"\\(bu")
-                                                         ((eq type 'ordered)
-                                                          (format "%s " 
(org-trim bullet)))
-                                                         (t "\\(dg"))))
-                 (concat ".IP " marker " 4\n"
-                                 (org-trim (or contents " " ))))
-                                        ; else
+    (if (and (null tag) (null checkbox))
+       (let* ((bullet (org-trim bullet))
+              (marker (cond  ((string= "-" bullet) "\\(em")
+                             ((string= "*" bullet) "\\(bu")
+                             ((eq type 'ordered)
+                              (format "%s " (org-trim bullet)))
+                             (t "\\(dg"))))
+         (concat ".IP " marker " 4\n"
+                 (org-trim (or contents " " ))))
       (concat ".TP\n" (or tag (concat " " checkbox)) "\n"
               (org-trim (or contents " " ))))))
 
 ;;; Keyword
 
 
-(defun org-man-keyword (keyword contents info)
+(defun org-man-keyword (keyword _contents _info)
   "Transcode a KEYWORD element from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((key (org-element-property :key keyword))
@@ -623,16 +587,16 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;; Line Break
 
-(defun org-man-line-break (line-break contents info)
+(defun org-man-line-break (_line-break _contents _info)
   "Transcode a LINE-BREAK object from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  ".br\n")
+  "\n.br\n")
 
 
 ;;; Link
 
 
-(defun org-man-link (link desc info)
+(defun org-man-link (link desc _info)
   "Transcode a LINK object from Org to Man.
 
 DESC is the description part of the link, or the empty string.
@@ -645,11 +609,11 @@ INFO is a plist holding contextual information.  See
          (path (cond
                 ((member type '("http" "https" "ftp" "mailto"))
                  (concat type ":" raw-path))
-                ((and (string= type "file") (file-name-absolute-p raw-path))
-                 (concat "file:" raw-path))
-                (t raw-path)))
-         protocol)
+                ((string= type "file") (org-export-file-uri raw-path))
+                (t raw-path))))
     (cond
+     ;; Link type is handled by a special function.
+     ((org-export-custom-protocol-maybe link desc 'man))
      ;; External link with a description part.
      ((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc))
      ;; External link without a description part.
@@ -657,10 +621,20 @@ INFO is a plist holding contextual information.  See
      ;; No path, only description.  Try to do something useful.
      (t (format "\\fI%s\\fP" desc)))))
 
+;;;; Node Property
+
+(defun org-man-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
 
 ;;; Paragraph
 
-(defun org-man-paragraph (paragraph contents info)
+(defun org-man-paragraph (paragraph contents _info)
   "Transcode a PARAGRAPH element from Org to Man.
 CONTENTS is the contents of the paragraph, as a string.  INFO is
 the plist used as a communication channel."
@@ -681,7 +655,7 @@ the plist used as a communication channel."
 
 ;;; Plain List
 
-(defun org-man-plain-list (plain-list contents info)
+(defun org-man-plain-list (_plain-list contents _info)
   "Transcode a PLAIN-LIST element from Org to Man.
 CONTENTS is the contents of the list.  INFO is a plist holding
 contextual information."
@@ -716,10 +690,16 @@ contextual information."
 
 ;;; Property Drawer
 
+(defun org-man-property-drawer (_property-drawer contents _info)
+  "Transcode a PROPERTY-DRAWER element from Org to Man.
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (format ".RS\n.nf\n%s\n.fi\n.RE" contents)))
 
 ;;; Quote Block
 
-(defun org-man-quote-block (quote-block contents info)
+(defun org-man-quote-block (quote-block contents _info)
   "Transcode a QUOTE-BLOCK element from Org to Man.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
@@ -727,28 +707,19 @@ holding contextual information."
    quote-block
    (format ".RS\n%s\n.RE" contents)))
 
-;;; Quote Section
-
-(defun org-man-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to Man.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((value (org-remove-indentation
-                (org-element-property :value quote-section))))
-    (when value (format ".RS\\fI%s\\fP\n.RE\n" value))))
-
 
 ;;; Radio Target
 
-(defun org-man-radio-target (radio-target text info)
+(defun org-man-radio-target (_radio-target text _info)
   "Transcode a RADIO-TARGET object from Org to Man.
 TEXT is the text of the target.  INFO is a plist holding
 contextual information."
-  text )
+  text)
 
 
 ;;; Section
 
-(defun org-man-section (section contents info)
+(defun org-man-section (_section contents _info)
   "Transcode a SECTION element from Org to Man.
 CONTENTS holds the contents of the section.  INFO is a plist
 holding contextual information."
@@ -757,70 +728,49 @@ holding contextual information."
 
 ;;; Special Block
 
-(defun org-man-special-block (special-block contents info)
+(defun org-man-special-block (special-block contents _info)
   "Transcode a SPECIAL-BLOCK element from Org to Man.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (let ((type (downcase (org-element-property :type special-block))))
-    (org-man--wrap-label
-     special-block
-     (format "%s\n" contents))))
+  (org-man--wrap-label special-block (format "%s\n" contents)))
 
 
 ;;; Src Block
 
-(defun org-man-src-block (src-block contents info)
+(defun org-man-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to Man.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let* ((lang (org-element-property :language src-block))
-         (code (org-element-property :value src-block))
-         (custom-env (and lang
-                          (cadr (assq (intern lang)
-                                      org-man-custom-lang-environments))))
-         (num-start (case (org-element-property :number-lines src-block)
-                      (continued (org-export-get-loc src-block info))
-                      (new 0)))
-         (retain-labels (org-element-property :retain-labels src-block)))
-    (cond
-     ;; Case 1.  No source fontification.
-     ((not org-man-source-highlight)
+  (if (not (plist-get info :man-source-highlight))
       (format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n\n"
-             (org-export-format-code-default src-block info)))
-     (org-man-source-highlight
-      (let* ((tmpdir (if (featurep 'xemacs)
-                        temp-directory
-                      temporary-file-directory ))
-
-            (in-file  (make-temp-name
-                       (expand-file-name "srchilite" tmpdir)))
-            (out-file (make-temp-name
-                       (expand-file-name "reshilite" tmpdir)))
-
-            (org-lang (org-element-property :language src-block))
-            (lst-lang (cadr (assq (intern org-lang)
-                                  org-man-source-highlight-langs)))
-
-            (cmd (concat "source-highlight"
-                         " -s " lst-lang
-                         " -f groff_man "
-                         " -i " in-file
-                         " -o " out-file)))
-
-       (if lst-lang
-           (let ((code-block ""))
-             (with-temp-file in-file (insert code))
-             (shell-command cmd)
-             (setq code-block  (org-file-contents out-file))
-             (delete-file in-file)
-             (delete-file out-file)
-             code-block)
-         (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" code)))))))
+             (org-export-format-code-default src-block info))
+    (let* ((tmpdir temporary-file-directory)
+          (in-file  (make-temp-name (expand-file-name "srchilite" tmpdir)))
+          (out-file (make-temp-name (expand-file-name "reshilite" tmpdir)))
+          (code (org-element-property :value src-block))
+          (org-lang (org-element-property :language src-block))
+          (lst-lang
+           (cadr (assq (intern org-lang)
+                       (plist-get info :man-source-highlight-langs))))
+          (cmd (concat "source-highlight"
+                       " -s " lst-lang
+                       " -f groff_man "
+                       " -i " in-file
+                       " -o " out-file)))
+      (if lst-lang
+         (let ((code-block ""))
+           (with-temp-file in-file (insert code))
+           (shell-command cmd)
+           (setq code-block  (org-file-contents out-file))
+           (delete-file in-file)
+           (delete-file out-file)
+           code-block)
+       (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" code)))))
 
 
 ;;; Statistics Cookie
 
-(defun org-man-statistics-cookie (statistics-cookie contents info)
+(defun org-man-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-element-property :value statistics-cookie))
@@ -828,7 +778,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;; Strike-Through
 
-(defun org-man-strike-through (strike-through contents info)
+(defun org-man-strike-through (_strike-through contents _info)
   "Transcode STRIKE-THROUGH from Org to Man.
 CONTENTS is the text with strike-through markup.  INFO is a plist
 holding contextual information."
@@ -836,7 +786,7 @@ holding contextual information."
 
 ;;; Subscript
 
-(defun org-man-subscript (subscript contents info)
+(defun org-man-subscript (_subscript contents _info)
   "Transcode a SUBSCRIPT object from Org to Man.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -844,7 +794,7 @@ contextual information."
 
 ;;; Superscript "^_%s$
 
-(defun org-man-superscript (superscript contents info)
+(defun org-man-superscript (_superscript contents _info)
   "Transcode a SUPERSCRIPT object from Org to Man.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -868,7 +818,7 @@ CONTENTS is the contents of the table.  INFO is a plist 
holding
 contextual information."
   (cond
    ;; Case 1: verbatim table.
-   ((or org-man-tables-verbatim
+   ((or (plist-get info :man-tables-verbatim)
         (let ((attr (read (format "(%s)"
                  (mapconcat
                   #'identity
@@ -907,14 +857,14 @@ a communication channel."
          (when (and (memq 'left borders) (not alignment))
            (push "|" alignment))
          (push
-          (case (org-export-table-cell-alignment cell info)
-            (left (concat "l" width divider))
-            (right (concat "r" width divider))
-            (center (concat "c" width divider)))
+          (concat (pcase (org-export-table-cell-alignment cell info)
+                    (`left "l") (`right "r") (`center "c"))
+                  width
+                  divider)
           alignment)
          (when (memq 'right borders) (push "|" alignment))))
       info)
-    (apply 'concat (reverse alignment))))
+    (apply #'concat (reverse alignment))))
 
 (defun org-man-table--org-table (table contents info)
   "Return appropriate Man code for an Org table.
@@ -925,7 +875,6 @@ channel.
 
 This function assumes TABLE has `org' as its `:type' attribute."
   (let* ((attr (org-export-read-attribute :attr_man table))
-        (label (org-element-property :name table))
          (caption (and (not (plist-get attr :disable-caption))
                       (org-man--caption/label-string table info)))
          (divider (if (plist-get attr :divider) "|" " "))
@@ -943,7 +892,8 @@ This function assumes TABLE has `org' as its `:type' 
attribute."
                 (let ((placement (plist-get attr :placement)))
                   (cond ((string= placement 'center) "center")
                         ((string= placement 'left) nil)
-                        (t (if org-man-tables-centered "center" ""))))
+                        ((plist-get info :man-tables-centered) "center")
+                        (t "")))
                 (or (plist-get attr :boxtype) "box"))))
 
          (title-line  (plist-get attr :title-line))
@@ -970,14 +920,14 @@ This function assumes TABLE has `org' as its `:type' 
attribute."
                     (format "%s.\n"
                             (let ((final-line ""))
                               (when title-line
-                                (dotimes (i (length first-line))
+                                (dotimes (_ (length first-line))
                                   (setq final-line (concat final-line "cb" 
divider))))
 
                               (setq final-line (concat final-line "\n"))
 
                               (if alignment
                                   (setq final-line (concat final-line 
alignment))
-                                (dotimes (i (length first-line))
+                                (dotimes (_ (length first-line))
                                   (setq final-line (concat final-line "c" 
divider))))
                               final-line ))
 
@@ -1018,69 +968,59 @@ This function assumes TABLE has `org' as its `:type' 
attribute."
   "Transcode a TABLE-CELL element from Org to Man
 CONTENTS is the cell contents.  INFO is a plist used as
 a communication channel."
-    (concat (if (and contents
-                     org-man-table-scientific-notation
-                     (string-match orgtbl-exp-regexp contents))
-                ;; Use appropriate format string for scientific
-                ;; notation.
-              (format org-man-table-scientific-notation
-                        (match-string 1 contents)
-                        (match-string 2 contents))
-              contents )
-            (when (org-export-get-next-element table-cell info) "\t")))
+  (concat
+   (let ((scientific-format (plist-get info :man-table-scientific-notation)))
+     (if (and contents
+             scientific-format
+             (string-match orgtbl-exp-regexp contents))
+        ;; Use appropriate format string for scientific notation.
+        (format scientific-format
+                (match-string 1 contents)
+                (match-string 2 contents))
+       contents))
+   (when (org-export-get-next-element table-cell info) "\t")))
 
 
 ;;; Table Row
 
 (defun org-man-table-row (table-row contents info)
-  "Transcode a TABLE-ROW element from Org to Man
+  "Transcode a TABLE-ROW element from Org to Man.
 CONTENTS is the contents of the row.  INFO is a plist used as
 a communication channel."
-  ;; Rules are ignored since table separators are deduced from
-  ;; borders of the current row.
+  ;; Rules are ignored since table separators are deduced from borders
+  ;; of the current row.
   (when (eq (org-element-property :type table-row) 'standard)
-    (let* ((attr (mapconcat 'identity
-                            (org-element-property
-                             :attr_man (org-export-get-parent table-row))
-                            " "))
-           ;; TABLE-ROW's borders are extracted from its first cell.
-           (borders
-            (org-export-table-cell-borders
-             (car (org-element-contents table-row)) info)))
+    (let ((borders
+          ;; TABLE-ROW's borders are extracted from its first cell.
+          (org-export-table-cell-borders
+           (car (org-element-contents table-row)) info)))
       (concat
-       ;; Mark horizontal lines
-       (cond  ((and (memq 'top borders) (memq 'above borders)) "_\n"))
+       (cond ((and (memq 'top borders) (memq 'above borders)) "_\n"))
        contents
-
-       (cond
-        ;; When BOOKTABS are activated enforce bottom rule even when
-        ;; no hline was specifically marked.
-        ((and (memq 'bottom borders) (memq 'below borders)) "\n_")
-        ((memq 'below borders) "\n_"))))))
+       (cond ((and (memq 'bottom borders) (memq 'below borders)) "\n_")
+            ((memq 'below borders) "\n_"))))))
 
 
 ;;; Target
 
-(defun org-man-target (target contents info)
+(defun org-man-target (target _contents info)
   "Transcode a TARGET object from Org to Man.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format "\\fI%s\\fP"
-          (org-export-solidify-link-text (org-element-property :value 
target))))
+  (format "\\fI%s\\fP" (org-export-get-reference target info)))
 
 
 ;;; Timestamp
 
-(defun org-man-timestamp (timestamp contents info)
+(defun org-man-timestamp (_timestamp _contents _info)
   "Transcode a TIMESTAMP object from Org to Man.
-  CONTENTS is nil.  INFO is a plist holding contextual
-  information."
-  "" )
+ONTENTS is nil.  INFO is a plist holding contextual information."
+  "")
 
 
 ;;; Underline
 
-(defun org-man-underline (underline contents info)
+(defun org-man-underline (_underline contents _info)
   "Transcode UNDERLINE from Org to Man.
 CONTENTS is the text with underline markup.  INFO is a plist
 holding contextual information."
@@ -1089,7 +1029,7 @@ holding contextual information."
 
 ;;; Verbatim
 
-(defun org-man-verbatim (verbatim contents info)
+(defun org-man-verbatim (_verbatim contents _info)
   "Transcode a VERBATIM object from Org to Man.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -1098,7 +1038,7 @@ channel."
 
 ;;; Verse Block
 
-(defun org-man-verse-block (verse-block contents info)
+(defun org-man-verse-block (_verse-block contents _info)
   "Transcode a VERSE-BLOCK element from Org to Man.
 CONTENTS is verse block contents. INFO is a plist holding
 contextual information."
@@ -1182,68 +1122,15 @@ FILE is the name of the file being compiled.  
Processing is done
 through the command specified in `org-man-pdf-process'.
 
 Return PDF file name or an error if it couldn't be produced."
-  (let* ((base-name (file-name-sans-extension (file-name-nondirectory file)))
-        (full-name (file-truename file))
-        (out-dir (file-name-directory file))
-        ;; Properly set working directory for compilation.
-        (default-directory (if (file-name-absolute-p file)
-                               (file-name-directory full-name)
-                             default-directory))
-         errors)
-    (message "Processing Groff file %s..." file)
-    (save-window-excursion
-      (cond
-       ;; A function is provided: Apply it.
-       ((functionp org-man-pdf-process)
-       (funcall org-man-pdf-process (shell-quote-argument file)))
-       ;; A list is provided: Replace %b, %f and %o with appropriate
-       ;; values in each command before applying it.  Output is
-       ;; redirected to "*Org PDF Groff Output*" buffer.
-       ((consp org-man-pdf-process)
-       (let ((outbuf (get-buffer-create "*Org PDF Groff Output*")))
-         (mapc
-          (lambda (command)
-            (shell-command
-             (replace-regexp-in-string
-              "%b" (shell-quote-argument base-name)
-              (replace-regexp-in-string
-               "%f" (shell-quote-argument full-name)
-               (replace-regexp-in-string
-                "%o" (shell-quote-argument out-dir) command t t) t t) t t)
-             outbuf))
-          org-man-pdf-process)
-         ;; Collect standard errors from output buffer.
-         (setq errors (org-man-collect-errors outbuf))))
-       (t (error "No valid command to process to PDF")))
-      (let ((pdffile (concat out-dir base-name ".pdf")))
-       ;; Check for process failure.  Provide collected errors if
-       ;; possible.
-       (if (not (file-exists-p pdffile))
-           (error "PDF file %s wasn't produced%s" pdffile
-                  (if errors (concat ": " errors) ""))
-         ;; Else remove log files, when specified, and signal end of
-         ;; process to user, along with any error encountered.
-         (when org-man-remove-logfiles
-           (dolist (ext org-man-logfiles-extensions)
-             (let ((file (concat out-dir base-name "." ext)))
-               (when (file-exists-p file) (delete-file file)))))
-         (message (concat "Process completed"
-                          (if (not errors) "."
-                            (concat " with errors: " errors)))))
-       ;; Return output file name.
-       pdffile))))
-
-(defun org-man-collect-errors (buffer)
-  "Collect some kind of errors from \"groff\" output
-BUFFER is the buffer containing output.
-Return collected error types as a string, or nil if there was
-none."
-  (with-current-buffer buffer
-    (save-excursion
-      (goto-char (point-max))
-      ;; Find final run
-      nil )))
-
+  (message "Processing Groff file %s..." file)
+  (let ((output (org-compile-file file org-man-pdf-process "pdf")))
+    (when org-man-remove-logfiles
+      (let ((base (file-name-sans-extension output)))
+       (dolist (ext org-man-logfiles-extensions)
+         (let ((file (concat base "." ext)))
+           (when (file-exists-p file) (delete-file file))))))
+    (message "Process completed.")
+    output))
 
 (provide 'ox-man)
 
diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el
index ab73f29..c8ea1fa 100644
--- a/lisp/org/ox-md.el
+++ b/lisp/org/ox-md.el
@@ -1,4 +1,4 @@
-;;; ox-md.el --- Markdown Back-End for Org Export Engine
+;;; ox-md.el --- Markdown Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -28,9 +28,9 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'ox-html)
-
+(require 'ox-publish)
 
 
 ;;; User-Configurable Variables
@@ -51,11 +51,29 @@ This variable can be set to either `atx' or `setext'."
          (const :tag "Use \"Setext\" style" setext)))
 
 
+;;;; Footnotes
+
+(defcustom org-md-footnotes-section "%s%s"
+  "Format string for the footnotes section.
+The first %s placeholder will be replaced with the localized Footnotes section
+heading, the second with the contents of the Footnotes section."
+ :group 'org-export-md
+ :type 'string
+ :version "26.1"
+ :package-version '(Org . "9.0"))
+
+(defcustom org-md-footnote-format "<sup>%s</sup>"
+  "Format string for the footnote reference.
+The %s will be replaced by the footnote reference itself."
+  :group 'org-export-md
+  :type 'string
+  :version "26.1"
+  :package-version '(Org . "9.0"))
+
 
 ;;; Define Back-End
 
 (org-export-define-derived-backend 'md 'html
-  :export-block '("MD" "MARKDOWN")
   :filters-alist '((:filter-parse-tree . org-md-separate-elements))
   :menu-entry
   '(?m "Export to Markdown"
@@ -68,62 +86,64 @@ This variable can be set to either `atx' or `setext'."
                (org-open-file (org-md-export-to-markdown nil s v)))))))
   :translate-alist '((bold . org-md-bold)
                     (code . org-md-verbatim)
-                    (comment . (lambda (&rest args) ""))
-                    (comment-block . (lambda (&rest args) ""))
                     (example-block . org-md-example-block)
+                    (export-block . org-md-export-block)
                     (fixed-width . org-md-example-block)
-                    (footnote-definition . ignore)
-                    (footnote-reference . ignore)
                     (headline . org-md-headline)
                     (horizontal-rule . org-md-horizontal-rule)
                     (inline-src-block . org-md-verbatim)
                     (inner-template . org-md-inner-template)
                     (italic . org-md-italic)
                     (item . org-md-item)
+                    (keyword . org-md-keyword)
                     (line-break . org-md-line-break)
                     (link . org-md-link)
+                    (node-property . org-md-node-property)
                     (paragraph . org-md-paragraph)
                     (plain-list . org-md-plain-list)
                     (plain-text . org-md-plain-text)
+                    (property-drawer . org-md-property-drawer)
                     (quote-block . org-md-quote-block)
-                    (quote-section . org-md-example-block)
                     (section . org-md-section)
                     (src-block . org-md-example-block)
                     (template . org-md-template)
-                    (verbatim . org-md-verbatim)))
-
+                    (verbatim . org-md-verbatim))
+  :options-alist
+  '((:md-footnote-format nil nil org-md-footnote-format)
+    (:md-footnotes-section nil nil org-md-footnotes-section)
+    (:md-headline-style nil nil org-md-headline-style)))
 
 
 ;;; Filters
 
-(defun org-md-separate-elements (tree backend info)
+(defun org-md-separate-elements (tree _backend info)
   "Fix blank lines between elements.
 
 TREE is the parse tree being exported.  BACKEND is the export
 back-end used.  INFO is a plist used as a communication channel.
 
-Enforce a blank line between elements.  There are three
-exceptions to this rule:
+Enforce a blank line between elements.  There are two exceptions
+to this rule:
 
   1. Preserve blank lines between sibling items in a plain list,
 
-  2. Outside of plain lists, preserve blank lines between
-     a paragraph and a plain list,
-
-  3. In an item, remove any blank line before the very first
-     paragraph and the next sub-list.
+  2. In an item, remove any blank line before the very first
+     paragraph and the next sub-list when the latter ends the
+     current item.
 
 Assume BACKEND is `md'."
   (org-element-map tree (remq 'item org-element-all-elements)
     (lambda (e)
-      (cond
-       ((not (and (eq (org-element-type e) 'paragraph)
-                 (eq (org-element-type (org-export-get-next-element e info))
-                     'plain-list)))
-       (org-element-put-property e :post-blank 1))
-       ((not (eq (org-element-type (org-element-property :parent e)) 'item)))
-       (t (org-element-put-property
-          e :post-blank (if (org-export-get-previous-element e info) 1 0))))))
+      (org-element-put-property
+       e :post-blank
+       (if (and (eq (org-element-type e) 'paragraph)
+               (eq (org-element-type (org-element-property :parent e)) 'item)
+               (org-export-first-sibling-p e info)
+               (let ((next (org-export-get-next-element e info)))
+                 (and (eq (org-element-type next) 'plain-list)
+                      (not (org-export-get-next-element next info)))))
+          0
+        1))))
   ;; Return updated tree.
   tree)
 
@@ -133,7 +153,7 @@ Assume BACKEND is `md'."
 
 ;;;; Bold
 
-(defun org-md-bold (bold contents info)
+(defun org-md-bold (_bold contents _info)
   "Transcode BOLD object into Markdown format.
 CONTENTS is the text within bold markup.  INFO is a plist used as
 a communication channel."
@@ -142,22 +162,22 @@ a communication channel."
 
 ;;;; Code and Verbatim
 
-(defun org-md-verbatim (verbatim contents info)
+(defun org-md-verbatim (verbatim _contents _info)
   "Transcode VERBATIM object into Markdown format.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
   (let ((value (org-element-property :value verbatim)))
     (format (cond ((not (string-match "`" value)) "`%s`")
-                 ((or (string-match "\\``" value)
-                      (string-match "`\\'" value))
+                 ((or (string-prefix-p "`" value)
+                      (string-suffix-p "`" value))
                   "`` %s ``")
                  (t "``%s``"))
            value)))
 
 
-;;;; Example Block and Src Block
+;;;; Example Block, Src Block and export Block
 
-(defun org-md-example-block (example-block contents info)
+(defun org-md-example-block (example-block _contents info)
   "Transcode EXAMPLE-BLOCK element into Markdown format.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -166,6 +186,14 @@ channel."
    (org-remove-indentation
     (org-export-format-code-default example-block info))))
 
+(defun org-md-export-block (export-block contents info)
+  "Transcode a EXPORT-BLOCK element from Org to Markdown.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (if (member (org-element-property :type export-block) '("MARKDOWN" "MD"))
+      (org-remove-indentation (org-element-property :value export-block))
+    ;; Also include HTML export blocks.
+    (org-export-with-backend 'html export-block contents info)))
+
 
 ;;;; Headline
 
@@ -189,45 +217,67 @@ a communication channel."
            (and (plist-get info :with-priority)
                 (let ((char (org-element-property :priority headline)))
                   (and char (format "[#%c] " char)))))
-          (anchor
-           (when (plist-get info :with-toc)
-             (org-html--anchor
-              (or (org-element-property :CUSTOM_ID headline)
-                  (concat "sec-"
-                          (mapconcat 'number-to-string
-                                     (org-export-get-headline-number
-                                      headline info) "-"))))))
           ;; Headline text without tags.
-          (heading (concat todo priority title)))
+          (heading (concat todo priority title))
+          (style (plist-get info :md-headline-style)))
       (cond
        ;; Cannot create a headline.  Fall-back to a list.
        ((or (org-export-low-level-p headline info)
-           (not (memq org-md-headline-style '(atx setext)))
-           (and (eq org-md-headline-style 'atx) (> level 6))
-           (and (eq org-md-headline-style 'setext) (> level 2)))
+           (not (memq style '(atx setext)))
+           (and (eq style 'atx) (> level 6))
+           (and (eq style 'setext) (> level 2)))
        (let ((bullet
               (if (not (org-export-numbered-headline-p headline info)) "-"
                 (concat (number-to-string
                          (car (last (org-export-get-headline-number
                                      headline info))))
                         "."))))
-         (concat bullet (make-string (- 4 (length bullet)) ? ) heading tags
-                 "\n\n"
-                 (and contents
-                      (replace-regexp-in-string "^" "    " contents)))))
-       ;; Use "Setext" style.
-       ((eq org-md-headline-style 'setext)
-       (concat heading tags anchor "\n"
-               (make-string (length heading) (if (= level 1) ?= ?-))
-               "\n\n"
-               contents))
-       ;; Use "atx" style.
-       (t (concat (make-string level ?#) " " heading tags anchor "\n\n" 
contents))))))
-
+         (concat bullet (make-string (- 4 (length bullet)) ?\s) heading tags 
"\n\n"
+                 (and contents (replace-regexp-in-string "^" "    " 
contents)))))
+       (t
+       (let ((anchor
+              (and (org-md--headline-referred-p headline info)
+                   (format "<a id=\"%s\"></a>"
+                           (or (org-element-property :CUSTOM_ID headline)
+                               (org-export-get-reference headline info))))))
+         (concat (org-md--headline-title style level title anchor tags)
+                 contents)))))))
+
+
+(defun org-md--headline-referred-p (headline info)
+  "Non-nil when HEADLINE is being referred to.
+INFO is a plist used as a communication channel.  Links and table
+of contents can refer to headlines."
+  (or (plist-get info :with-toc)
+      (org-element-map (plist-get info :parse-tree) 'link
+       (lambda (link)
+         (eq headline
+             (pcase (org-element-property :type link)
+               ((or "custom-id" "id") (org-export-resolve-id-link link info))
+               ("fuzzy" (org-export-resolve-fuzzy-link link info))
+               (_ nil))))
+       info t)))
+
+(defun org-md--headline-title (style level title &optional anchor tags)
+  "Generate a headline title in the preferred Markdown headline style.
+STYLE is the preferred style (`atx' or `setext').  LEVEL is the
+header level.  TITLE is the headline title.  ANCHOR is the HTML
+anchor tag for the section as a string.  TAGS are the tags set on
+the section."
+  (let ((anchor-lines (and anchor (concat anchor "\n\n"))))
+    ;; Use "Setext" style
+    (if (and (eq style 'setext) (< level 3))
+        (let* ((underline-char (if (= level 1) ?= ?-))
+               (underline (concat (make-string (length title) underline-char)
+                                 "\n")))
+          (concat "\n" anchor-lines title tags "\n" underline "\n"))
+        ;; Use "Atx" style
+        (let ((level-mark (make-string level ?#)))
+          (concat "\n" anchor-lines level-mark " " title tags "\n\n")))))
 
 ;;;; Horizontal Rule
 
-(defun org-md-horizontal-rule (horizontal-rule contents info)
+(defun org-md-horizontal-rule (_horizontal-rule _contents _info)
   "Transcode HORIZONTAL-RULE element into Markdown format.
 CONTENTS is the horizontal rule contents.  INFO is a plist used
 as a communication channel."
@@ -236,7 +286,7 @@ as a communication channel."
 
 ;;;; Italic
 
-(defun org-md-italic (italic contents info)
+(defun org-md-italic (_italic contents _info)
   "Transcode ITALIC object into Markdown format.
 CONTENTS is the text within italic markup.  INFO is a plist used
 as a communication channel."
@@ -261,19 +311,31 @@ a communication channel."
                           "."))))
     (concat bullet
            (make-string (- 4 (length bullet)) ? )
-           (case (org-element-property :checkbox item)
-             (on "[X] ")
-             (trans "[-] ")
-             (off "[ ] "))
+           (pcase (org-element-property :checkbox item)
+             (`on "[X] ")
+             (`trans "[-] ")
+             (`off "[ ] "))
            (let ((tag (org-element-property :tag item)))
              (and tag (format "**%s:** "(org-export-data tag info))))
            (and contents
                 (org-trim (replace-regexp-in-string "^" "    " contents))))))
 
 
+
+;;;; Keyword
+
+(defun org-md-keyword (keyword contents info)
+  "Transcode a KEYWORD element into Markdown format.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (if (member (org-element-property :key keyword) '("MARKDOWN" "MD"))
+      (org-element-property :value keyword)
+    (org-export-with-backend 'html keyword contents info)))
+
+
 ;;;; Line Break
 
-(defun org-md-line-break (line-break contents info)
+(defun org-md-line-break (_line-break _contents _info)
   "Transcode LINE-BREAK object into Markdown format.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -287,28 +349,50 @@ channel."
 CONTENTS is the link's description.  INFO is a plist used as
 a communication channel."
   (let ((link-org-files-as-md
-        (function
-         (lambda (raw-path)
-           ;; Treat links to `file.org' as links to `file.md'.
-           (if (string= ".org" (downcase (file-name-extension raw-path ".")))
-               (concat (file-name-sans-extension raw-path) ".md")
-             raw-path))))
+        (lambda (raw-path)
+          ;; Treat links to `file.org' as links to `file.md'.
+          (if (string= ".org" (downcase (file-name-extension raw-path ".")))
+              (concat (file-name-sans-extension raw-path) ".md")
+            raw-path)))
        (type (org-element-property :type link)))
     (cond
-     ((member type '("custom-id" "id"))
-      (let ((destination (org-export-resolve-id-link link info)))
-       (if (stringp destination)       ; External file.
-           (let ((path (funcall link-org-files-as-md destination)))
-             (if (not contents) (format "<%s>" path)
-               (format "[%s](%s)" contents path)))
-         (concat
-          (and contents (concat contents " "))
-          (format "(%s)"
-                  (format (org-export-translate "See section %s" :html info)
-                          (mapconcat 'number-to-string
-                                     (org-export-get-headline-number
-                                      destination info)
-                                     ".")))))))
+     ;; Link type is handled by a special function.
+     ((org-export-custom-protocol-maybe link contents 'md))
+     ((member type '("custom-id" "id" "fuzzy"))
+      (let ((destination (if (string= type "fuzzy")
+                            (org-export-resolve-fuzzy-link link info)
+                          (org-export-resolve-id-link link info))))
+       (pcase (org-element-type destination)
+         (`plain-text                  ; External file.
+          (let ((path (funcall link-org-files-as-md destination)))
+            (if (not contents) (format "<%s>" path)
+              (format "[%s](%s)" contents path))))
+         (`headline
+          (format
+           "[%s](#%s)"
+           ;; Description.
+           (cond ((org-string-nw-p contents))
+                 ((org-export-numbered-headline-p destination info)
+                  (mapconcat #'number-to-string
+                             (org-export-get-headline-number destination info)
+                             "."))
+                 (t (org-export-data (org-element-property :title destination)
+                                     info)))
+           ;; Reference.
+           (or (org-element-property :CUSTOM_ID destination)
+               (org-export-get-reference destination info))))
+         (_
+          (let ((description
+                 (or (org-string-nw-p contents)
+                     (let ((number (org-export-get-ordinal destination info)))
+                       (cond
+                        ((not number) nil)
+                        ((atom number) (number-to-string number))
+                        (t (mapconcat #'number-to-string number ".")))))))
+            (when description
+              (format "[%s](#%s)"
+                      description
+                      (org-export-get-reference destination info))))))))
      ((org-export-inline-image-p link org-html-inline-image-rules)
       (let ((path (let ((raw-path (org-element-property :path link)))
                    (if (not (file-name-absolute-p raw-path)) raw-path
@@ -324,53 +408,46 @@ a communication channel."
        (format (org-export-get-coderef-format ref contents)
                (org-export-resolve-coderef ref info))))
      ((equal type "radio") contents)
-     ((equal type "fuzzy")
-      (let ((destination (org-export-resolve-fuzzy-link link info)))
-       (if (org-string-nw-p contents) contents
-         (when destination
-           (let ((number (org-export-get-ordinal destination info)))
-             (when number
-               (if (atom number) (number-to-string number)
-                 (mapconcat 'number-to-string number "."))))))))
-     ;; Link type is handled by a special function.
-     ((let ((protocol (nth 2 (assoc type org-link-protocols))))
-       (and (functionp protocol)
-            (funcall protocol
-                     (org-link-unescape (org-element-property :path link))
-                     contents
-                     'md))))
      (t (let* ((raw-path (org-element-property :path link))
               (path
                (cond
                 ((member type '("http" "https" "ftp"))
                  (concat type ":" raw-path))
                 ((string= type "file")
-                 (let ((path (funcall link-org-files-as-md raw-path)))
-                   (if (not (file-name-absolute-p path)) path
-                     ;; If file path is absolute, prepend it
-                     ;; with "file:" component.
-                     (concat "file:" path))))
+                 (org-export-file-uri (funcall link-org-files-as-md raw-path)))
                 (t raw-path))))
          (if (not contents) (format "<%s>" path)
            (format "[%s](%s)" contents path)))))))
 
 
+;;;; Node Property
+
+(defun org-md-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element into Markdown syntax.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
+
+
 ;;;; Paragraph
 
-(defun org-md-paragraph (paragraph contents info)
+(defun org-md-paragraph (paragraph contents _info)
   "Transcode PARAGRAPH element into Markdown format.
 CONTENTS is the paragraph contents.  INFO is a plist used as
 a communication channel."
   (let ((first-object (car (org-element-contents paragraph))))
     ;; If paragraph starts with a #, protect it.
-    (if (and (stringp first-object) (string-match "\\`#" first-object))
-       (replace-regexp-in-string "\\`#" "\\#" contents nil t)
+    (if (and (stringp first-object) (string-prefix-p "#" first-object))
+       (concat "\\" contents)
       contents)))
 
 
 ;;;; Plain List
 
-(defun org-md-plain-list (plain-list contents info)
+(defun org-md-plain-list (_plain-list contents _info)
   "Transcode PLAIN-LIST element into Markdown format.
 CONTENTS is the plain-list contents.  INFO is a plist used as
 a communication channel."
@@ -403,9 +480,19 @@ contextual information."
   text)
 
 
+;;;; Property Drawer
+
+(defun org-md-property-drawer (_property-drawer contents _info)
+  "Transcode a PROPERTY-DRAWER element into Markdown format.
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (replace-regexp-in-string "^" "    " contents)))
+
+
 ;;;; Quote Block
 
-(defun org-md-quote-block (quote-block contents info)
+(defun org-md-quote-block (_quote-block contents _info)
   "Transcode QUOTE-BLOCK element into Markdown format.
 CONTENTS is the quote-block contents.  INFO is a plist used as
 a communication channel."
@@ -416,7 +503,7 @@ a communication channel."
 
 ;;;; Section
 
-(defun org-md-section (section contents info)
+(defun org-md-section (_section contents _info)
   "Transcode SECTION element into Markdown format.
 CONTENTS is the section contents.  INFO is a plist used as
 a communication channel."
@@ -425,15 +512,50 @@ a communication channel."
 
 ;;;; Template
 
+(defun org-md--footnote-formatted (footnote info)
+  "Formats a single footnote entry FOOTNOTE.
+FOOTNOTE is a cons cell of the form (number . definition).
+INFO is a plist with contextual information."
+  (let* ((fn-num (car footnote))
+         (fn-text (cdr footnote))
+         (fn-format (plist-get info :md-footnote-format))
+         (fn-anchor (format "fn.%d" fn-num))
+         (fn-href (format " href=\"#fnr.%d\"" fn-num))
+         (fn-link-to-ref (org-html--anchor fn-anchor fn-num fn-href info)))
+    (concat (format fn-format fn-link-to-ref) " " fn-text "\n")))
+
+(defun org-md--footnote-section (info)
+  "Format the footnote section.
+INFO is a plist used as a communication channel."
+  (let* ((fn-alist (org-export-collect-footnote-definitions info))
+         (fn-alist (cl-loop for (n _type raw) in fn-alist collect
+                            (cons n (org-trim (org-export-data raw info)))))
+         (headline-style (plist-get info :md-headline-style))
+         (section-title (org-html--translate "Footnotes" info)))
+    (when fn-alist
+      (format (plist-get info :md-footnotes-section)
+              (org-md--headline-title headline-style 1 section-title)
+              (mapconcat (lambda (fn) (org-md--footnote-formatted fn info))
+                         fn-alist
+                         "\n")))))
+
 (defun org-md-inner-template (contents info)
   "Return body of document after converting it to Markdown syntax.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
   ;; Make sure CONTENTS is separated from table of contents and
   ;; footnotes with at least a blank line.
-  (org-trim (org-html-inner-template (concat "\n" contents "\n") info)))
-
-(defun org-md-template (contents info)
+  (concat
+   ;; Table of contents.
+   (let ((depth (plist-get info :with-toc)))
+     (when depth (org-html-toc depth info)))
+   ;; Document contents.
+   contents
+   "\n"
+   ;; Footnotes section.
+   (org-md--footnote-section info)))
+
+(defun org-md-template (contents _info)
   "Return complete document string after Markdown conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist used
 as a communication channel."
@@ -472,9 +594,9 @@ non-nil."
 
 ;;;###autoload
 (defun org-md-convert-region-to-md ()
-  "Assume the current region has org-mode syntax, and convert it to Markdown.
+  "Assume the current region has Org syntax, and convert it to Markdown.
 This can be used in any buffer.  For example, you can write an
-itemized list in org-mode syntax in a Markdown buffer and use
+itemized list in Org syntax in a Markdown buffer and use
 this command to convert it."
   (interactive)
   (org-export-replace-region-by 'md))
@@ -505,6 +627,16 @@ Return output file's name."
   (let ((outfile (org-export-output-file-name ".md" subtreep)))
     (org-export-to-file 'md outfile async subtreep visible-only)))
 
+;;;###autoload
+(defun org-md-publish-to-md (plist filename pub-dir)
+  "Publish an org file to Markdown.
+
+FILENAME is the filename of the Org file to be published.  PLIST
+is the property list for the given project.  PUB-DIR is the
+publishing directory.
+
+Return output file name."
+  (org-publish-org-to 'md filename ".md" plist pub-dir))
 
 (provide 'ox-md)
 
diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el
index 5430bda..943a6be 100644
--- a/lisp/org/ox-odt.el
+++ b/lisp/org/ox-odt.el
@@ -1,4 +1,4 @@
-;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode
+;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
@@ -25,12 +25,11 @@
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'cl)
-  (require 'table nil 'noerror))
+(require 'cl-lib)
 (require 'format-spec)
 (require 'ox)
 (require 'org-compat)
+(require 'table nil 'noerror)
 
 ;;; Define Back-End
 
@@ -59,13 +58,13 @@
     (latex-fragment . org-odt-latex-fragment)
     (line-break . org-odt-line-break)
     (link . org-odt-link)
+    (node-property . org-odt-node-property)
     (paragraph . org-odt-paragraph)
     (plain-list . org-odt-plain-list)
     (plain-text . org-odt-plain-text)
     (planning . org-odt-planning)
     (property-drawer . org-odt-property-drawer)
     (quote-block . org-odt-quote-block)
-    (quote-section . org-odt-quote-section)
     (radio-target . org-odt-radio-target)
     (section . org-odt-section)
     (special-block . org-odt-special-block)
@@ -83,7 +82,6 @@
     (underline . org-odt-underline)
     (verbatim . org-odt-verbatim)
     (verse-block . org-odt-verse-block))
-  :export-block "ODT"
   :filters-alist '((:filter-parse-tree
                    . (org-odt--translate-latex-fragments
                       org-odt--translate-description-lists
@@ -97,6 +95,22 @@
                (org-open-file (org-odt-export-to-odt nil s v) 'system))))))
   :options-alist
   '((:odt-styles-file "ODT_STYLES_FILE" nil nil t)
+    (:description "DESCRIPTION" nil nil newline)
+    (:keywords "KEYWORDS" nil nil space)
+    (:subtitle "SUBTITLE" nil nil parse)
+    ;; Other variables.
+    (:odt-content-template-file nil nil org-odt-content-template-file)
+    (:odt-display-outline-level nil nil org-odt-display-outline-level)
+    (:odt-fontify-srcblocks nil nil org-odt-fontify-srcblocks)
+    (:odt-format-drawer-function nil nil org-odt-format-drawer-function)
+    (:odt-format-headline-function nil nil org-odt-format-headline-function)
+    (:odt-format-inlinetask-function nil nil 
org-odt-format-inlinetask-function)
+    (:odt-inline-formula-rules nil nil org-odt-inline-formula-rules)
+    (:odt-inline-image-rules nil nil org-odt-inline-image-rules)
+    (:odt-pixels-per-inch nil nil org-odt-pixels-per-inch)
+    (:odt-styles-file nil nil org-odt-styles-file)
+    (:odt-table-styles nil nil org-odt-table-styles)
+    (:odt-use-date-fields nil nil org-odt-use-date-fields)
     ;; Redefine regular option.
     (:with-latex nil "tex" org-odt-with-latex)))
 
@@ -105,21 +119,27 @@
 
 ;;; Hooks
 
-;;; Function Declarations
+;;; Function and Dynamically Scoped Variables Declarations
 
-(declare-function org-id-find-id-file "org-id" (id))
 (declare-function hfy-face-to-style "htmlfontify" (fn))
 (declare-function hfy-face-or-def-to-name "htmlfontify" (fn))
 (declare-function archive-zip-extract "arc-mode" (archive name))
 (declare-function org-create-math-formula "org" (latex-frag &optional 
mathml-file))
 (declare-function browse-url-file-url "browse-url" (file))
 
+(defvar nxml-auto-insert-xml-declaration-flag) ; nxml-mode.el
+(defvar archive-zip-extract)                  ; arc-mode.el
+(defvar hfy-end-span-handler)                 ; htmlfontify.el
+(defvar hfy-begin-span-handler)                       ; htmlfontify.el
+(defvar hfy-face-to-css)                      ; htmlfontify.el
+(defvar hfy-html-quote-map)                   ; htmlfontify.el
+(defvar hfy-html-quote-regex)                 ; htmlfontify.el
 
 
 ;;; Internal Variables
 
 (defconst org-odt-lib-dir
-  (file-name-directory load-file-name)
+  (file-name-directory (or load-file-name (buffer-file-name)))
   "Location of ODT exporter.
 Use this to infer values of `org-odt-styles-dir' and
 `org-odt-schema-dir'.")
@@ -157,7 +177,7 @@ and `org-odt-data-dir'.")
    (eval-when-compile
      (and (boundp 'org-odt-data-dir) org-odt-data-dir ; see make install
          (expand-file-name "./styles/" org-odt-data-dir)))
-   (expand-file-name "../../etc/styles/" org-odt-lib-dir) ; git
+   (expand-file-name "../etc/styles/" org-odt-lib-dir) ; git
    (expand-file-name "./etc/styles/" org-odt-lib-dir)  ; elpa
    (expand-file-name "./org/" data-directory)         ; system
    )
@@ -167,23 +187,14 @@ heuristically based on the values of `org-odt-lib-dir' and
 `org-odt-data-dir'.")
 
 (defconst org-odt-styles-dir
-  (let* ((styles-dir
-         (catch 'styles-dir
-           (message "Debug (ox-odt): Searching for OpenDocument styles 
files...")
-           (mapc (lambda (styles-dir)
-                   (when styles-dir
-                     (message "Debug (ox-odt): Trying %s..." styles-dir)
-                     (when (and (file-readable-p
-                                 (expand-file-name
-                                  "OrgOdtContentTemplate.xml" styles-dir))
-                                (file-readable-p
-                                 (expand-file-name
-                                  "OrgOdtStyles.xml" styles-dir)))
-                       (message "Debug (ox-odt): Using styles under %s"
-                                styles-dir)
-                       (throw 'styles-dir styles-dir))))
-                 org-odt-styles-dir-list)
-           nil)))
+  (let ((styles-dir
+        (cl-find-if
+         (lambda (dir)
+           (and dir
+                (file-readable-p
+                 (expand-file-name "OrgOdtContentTemplate.xml" dir))
+                (file-readable-p (expand-file-name "OrgOdtStyles.xml" dir))))
+         org-odt-styles-dir-list)))
     (unless styles-dir
       (error "Error (ox-odt): Cannot find factory styles files, aborting"))
     styles-dir)
@@ -192,13 +203,12 @@ heuristically based on the values of `org-odt-lib-dir' and
 This directory contains the following XML files -
  \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\".  These
  XML files are used as the default values of
- `org-odt-styles-file' and
- `org-odt-content-template-file'.
+ `org-odt-styles-file' and `org-odt-content-template-file'.
 
 The default value of this variable varies depending on the
-version of org in use and is initialized from
-`org-odt-styles-dir-list'.  Note that the user could be using org
-from one of: org's own private git repository, GNU ELPA tar or
+version of Org in use and is initialized from
+`org-odt-styles-dir-list'.  Note that the user could be using Org
+from one of: Org own private git repository, GNU ELPA tar or
 standard Emacs.")
 
 (defconst org-odt-bookmark-prefix "OrgXref.")
@@ -263,7 +273,6 @@ except that the foreground and background colors are set
 according to the default face identified by the `htmlfontify'.")
 
 (defvar hfy-optimizations)
-(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "25.1")
 (defvar org-odt-embedded-formulas-count 0)
 (defvar org-odt-embedded-images-count 0)
 (defvar org-odt-image-size-probe-method
@@ -369,28 +378,14 @@ visually."
 
 (require 'rng-loc)
 (defcustom org-odt-schema-dir
-  (let* ((schema-dir
-         (catch 'schema-dir
-           (message "Debug (ox-odt): Searching for OpenDocument schema 
files...")
-           (mapc
-            (lambda (schema-dir)
-              (when schema-dir
-                (message "Debug (ox-odt): Trying %s..." schema-dir)
-                (when (and (file-expand-wildcards
-                            (expand-file-name "od-manifest-schema*.rnc"
-                                              schema-dir))
-                           (file-expand-wildcards
-                            (expand-file-name "od-schema*.rnc"
-                                              schema-dir))
-                           (file-readable-p
-                            (expand-file-name "schemas.xml" schema-dir)))
-                  (message "Debug (ox-odt): Using schema files under %s"
-                           schema-dir)
-                  (throw 'schema-dir schema-dir))))
-            org-odt-schema-dir-list)
-           (message "Debug (ox-odt): No OpenDocument schema files installed")
-           nil)))
-    schema-dir)
+  (cl-find-if
+   (lambda (dir)
+     (and dir
+         (file-expand-wildcards
+          (expand-file-name "od-manifest-schema*.rnc" dir))
+         (file-expand-wildcards (expand-file-name "od-schema*.rnc" dir))
+         (file-readable-p (expand-file-name "schemas.xml" dir))))
+   org-odt-schema-dir-list)
   "Directory that contains OpenDocument schema files.
 
 This directory contains:
@@ -647,8 +642,7 @@ values.  See Info node `(emacs) File Variables'."
 
 ;;;; Drawers
 
-(defcustom org-odt-format-drawer-function
-  (lambda (name contents) contents)
+(defcustom org-odt-format-drawer-function (lambda (_name contents) contents)
   "Function called to format a drawer in ODT code.
 
 The function must accept two parameters:
@@ -666,7 +660,8 @@ The default value simply returns the value of CONTENTS."
 
 ;;;; Headline
 
-(defcustom org-odt-format-headline-function 'ignore
+(defcustom org-odt-format-headline-function
+  'org-odt-format-headline-default-function
   "Function to format headline text.
 
 This function will be called with 5 arguments:
@@ -678,14 +673,15 @@ TAGS      the tags string, separated with colons (string 
or nil).
 
 The function result will be used as headline text."
   :group 'org-export-odt
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type 'function)
 
 
 ;;;; Inlinetasks
 
-(defcustom org-odt-format-inlinetask-function 'ignore
+(defcustom org-odt-format-inlinetask-function
+  'org-odt-format-inlinetask-default-function
   "Function called to format an inlinetask in ODT code.
 
 The function must accept six parameters:
@@ -698,8 +694,8 @@ The function must accept six parameters:
 
 The function should return the string to be exported."
   :group 'org-export-odt
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type 'function)
 
 
@@ -750,15 +746,15 @@ link's path."
                :value-type (regexp :tag "Path")))
 
 (defcustom org-odt-inline-image-rules
-  '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\)\\'"))
+  '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'"))
   "Rules characterizing image files that can be inlined into ODT.
 
 A rule consists in an association whose key is the type of link
 to consider, and value is a regexp that will be matched against
 link's path."
   :group 'org-export-odt
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(alist :key-type (string :tag "Type")
                :value-type (regexp :tag "Path")))
 
@@ -787,8 +783,8 @@ Use the latter option if you do not want the custom styles 
to be
 based on your current display settings.  It is necessary that the
 styles.xml already contains needed styles for colorizing to work.
 
-This variable is effective only if
-`org-odt-fontify-srcblocks' is turned on."
+This variable is effective only if `org-odt-fontify-srcblocks' is
+turned on."
   :group 'org-export-odt
   :version "24.1"
   :type 'boolean)
@@ -825,8 +821,7 @@ TABLE-STYLE-NAME is the style associated with the table 
through
 
 TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
 TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
-below) that is included in
-`org-odt-content-template-file'.
+below) that is included in `org-odt-content-template-file'.
 
 TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
                          \"TableCell\"
@@ -977,11 +972,11 @@ See `org-odt--build-date-styles' for implementation 
details."
                             (repeater-unit (org-element-property
                                             :repeater-unit timestamp)))
                         (concat
-                         (case repeater-type
+                         (cl-case repeater-type
                            (catchup "++") (restart ".+") (cumulate "+"))
                          (when repeater-value
                            (number-to-string repeater-value))
-                         (case repeater-unit
+                         (cl-case repeater-unit
                            (hour "h") (day "d") (week "w") (month "m")
                            (year "y"))))))
        (concat
@@ -1020,29 +1015,28 @@ See `org-odt--build-date-styles' for implementation 
details."
 
 (defun org-odt--zip-extract (archive members target)
   (when (atom members) (setq members (list members)))
-  (mapc (lambda (member)
-         (require 'arc-mode)
-         (let* ((--quote-file-name
-                 ;; This is shamelessly stolen from `archive-zip-extract'.
-                 (lambda (name)
-                   (if (or (not (memq system-type '(windows-nt ms-dos)))
-                           (and (boundp 'w32-quote-process-args)
-                                (null w32-quote-process-args)))
-                       (shell-quote-argument name)
-                     name)))
-                (target (funcall --quote-file-name target))
-                (archive (expand-file-name archive))
-                (archive-zip-extract
-                 (list "unzip" "-qq" "-o" "-d" target))
-                exit-code command-output)
-           (setq command-output
-                 (with-temp-buffer
-                   (setq exit-code (archive-zip-extract archive member))
-                   (buffer-string)))
-           (unless (zerop exit-code)
-             (message command-output)
-             (error "Extraction failed"))))
-       members))
+  (require 'arc-mode)
+  (dolist (member members)
+    (let* ((--quote-file-name
+           ;; This is shamelessly stolen from `archive-zip-extract'.
+           (lambda (name)
+             (if (or (not (memq system-type '(windows-nt ms-dos)))
+                     (and (boundp 'w32-quote-process-args)
+                          (null w32-quote-process-args)))
+                 (shell-quote-argument name)
+               name)))
+          (target (funcall --quote-file-name target))
+          (archive (expand-file-name archive))
+          (archive-zip-extract
+           (list "unzip" "-qq" "-o" "-d" target))
+          exit-code command-output)
+      (setq command-output
+           (with-temp-buffer
+             (setq exit-code (archive-zip-extract archive member))
+             (buffer-string)))
+      (unless (zerop exit-code)
+       (message command-output)
+       (error "Extraction failed")))))
 
 ;;;; Target
 
@@ -1069,13 +1063,20 @@ See `org-odt--build-date-styles' for implementation 
details."
 
 ;;;; Table of Contents
 
-(defun org-odt-begin-toc (index-title depth)
+(defun org-odt--format-toc (title entries depth)
+  "Return a table of contents.
+TITLE is the title of the table, as a string, or nil.  ENTRIES is
+the contents of the table, as a string.  DEPTH is an integer
+specifying the depth of the table."
   (concat
-   (format "
-    <text:table-of-content text:style-name=\"OrgIndexSection\" 
text:protected=\"true\" text:name=\"Table of Contents\">
-     <text:table-of-content-source text:outline-level=\"%d\">
-      <text:index-title-template 
text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
-" depth index-title)
+   "
+<text:table-of-content text:style-name=\"OrgIndexSection\" 
text:protected=\"true\" text:name=\"Table of Contents\">\n"
+   (format "  <text:table-of-content-source text:outline-level=\"%d\">" depth)
+   (and title
+       (format "
+    <text:index-title-template 
text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
+"
+               title))
 
    (let ((levels (number-sequence 1 10)))
      (mapconcat
@@ -1087,59 +1088,61 @@ See `org-odt--build-date-styles' for implementation 
details."
        <text:index-entry-chapter/>
        <text:index-entry-text/>
        <text:index-entry-link-end/>
-      </text:table-of-content-entry-template>
-" level level)) levels ""))
-
-   (format  "
-     </text:table-of-content-source>
-
-     <text:index-body>
-      <text:index-title text:style-name=\"Sect1\" text:name=\"Table of 
Contents1_Head\">
-       <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
-      </text:index-title>
- " index-title)))
-
-(defun org-odt-end-toc ()
-  (format "
-     </text:index-body>
-    </text:table-of-content>
-"))
-
-(defun* org-odt-format-toc-headline
-    (todo todo-type priority text tags
-         &key level section-number headline-label &allow-other-keys)
-  (setq text
-       (concat
-        ;; Section number.
-        (when section-number (concat section-number ". "))
-        ;; Todo.
-        (when todo
-          (let ((style (if (member todo org-done-keywords)
-                           "OrgDone" "OrgTodo")))
-            (format "<text:span text:style-name=\"%s\">%s</text:span> "
-                    style todo)))
-        (when priority
-          (let* ((style (format "OrgPriority-%s" priority))
-                 (priority (format "[#%c]" priority)))
-            (format "<text:span text:style-name=\"%s\">%s</text:span> "
-                    style priority)))
-        ;; Title.
-        text
-        ;; Tags.
-        (when tags
-          (concat
-           (format " <text:span text:style-name=\"%s\">[%s]</text:span>"
-                   "OrgTags"
-                   (mapconcat
-                    (lambda (tag)
-                      (format
-                       "<text:span text:style-name=\"%s\">%s</text:span>"
-                       "OrgTag" tag)) tags " : "))))))
+      </text:table-of-content-entry-template>\n"
+        level level)) levels ""))
+   "
+  </text:table-of-content-source>
+  <text:index-body>"
+   (and title
+       (format "
+    <text:index-title text:style-name=\"Sect1\" text:name=\"Table of 
Contents1_Head\">
+      <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
+    </text:index-title>\n"
+               title))
+   entries
+   "
+  </text:index-body>
+</text:table-of-content>"))
+
+(cl-defun org-odt-format-toc-headline
+    (todo _todo-type priority text tags
+         &key _level section-number headline-label &allow-other-keys)
   (format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
-         headline-label text))
-
-(defun org-odt-toc (depth info)
-  (assert (wholenump depth))
+         headline-label
+         (concat
+          ;; Section number.
+          (and section-number (concat section-number ". "))
+          ;; Todo.
+          (when todo
+            (let ((style (if (member todo org-done-keywords)
+                             "OrgDone" "OrgTodo")))
+              (format "<text:span text:style-name=\"%s\">%s</text:span> "
+                      style todo)))
+          (when priority
+            (let* ((style (format "OrgPriority-%s" priority))
+                   (priority (format "[#%c]" priority)))
+              (format "<text:span text:style-name=\"%s\">%s</text:span> "
+                      style priority)))
+          ;; Title.
+          text
+          ;; Tags.
+          (when tags
+            (concat
+             (format " <text:span text:style-name=\"%s\">[%s]</text:span>"
+                     "OrgTags"
+                     (mapconcat
+                      (lambda (tag)
+                        (format
+                         "<text:span text:style-name=\"%s\">%s</text:span>"
+                         "OrgTag" tag)) tags " : ")))))))
+
+(defun org-odt-toc (depth info &optional scope)
+  "Build a table of contents.
+DEPTH is an integer specifying the depth of the table.  INFO is
+a plist containing current export properties.  Optional argument
+SCOPE, when non-nil, defines the scope of the table.  Return the
+table of contents as a string, or nil."
+  (cl-assert (wholenump depth))
   ;; When a headline is marked as a radio target, as in the example below:
   ;;
   ;; ** <<<Some Heading>>>
@@ -1150,24 +1153,18 @@ See `org-odt--build-date-styles' for implementation 
details."
   ;; /TOC/, as otherwise there will be duplicated anchors one in TOC
   ;; and one in the document body.
   ;;
-  ;; FIXME-1: Currently exported headings are memoized.  `org-export.el'
-  ;; doesn't provide a way to disable memoization.  So this doesn't
-  ;; work.
-  ;;
-  ;; FIXME-2: Are there any other objects that need to be suppressed
-  ;; within TOC?
-  (let* ((title (org-export-translate "Table of Contents" :utf-8 info))
-        (headlines (org-export-collect-headlines
-                    info (and (wholenump depth) depth)))
+  ;; Likewise, links, footnote references and regular targets are also
+  ;; suppressed.
+  (let* ((headlines (org-export-collect-headlines info depth scope))
         (backend (org-export-create-backend
-                  :parent (org-export-backend-name
-                           (plist-get info :back-end))
-                  :transcoders (mapcar
-                                (lambda (type) (cons type (lambda (d c i) c)))
-                                (list 'radio-target)))))
+                  :parent (org-export-backend-name (plist-get info :back-end))
+                  :transcoders '((footnote-reference . ignore)
+                                 (link . (lambda (object c i) c))
+                                 (radio-target . (lambda (object c i) c))
+                                 (target . ignore)))))
     (when headlines
-      (concat
-       (org-odt-begin-toc title depth)
+      (org-odt--format-toc
+       (and (not scope) (org-export-translate "Table of Contents" :utf-8 info))
        (mapconcat
        (lambda (headline)
          (let* ((entry (org-odt-format-headline--wrap
@@ -1177,7 +1174,7 @@ See `org-odt--build-date-styles' for implementation 
details."
            (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
                    style entry)))
        headlines "\n")
-       (org-odt-end-toc)))))
+       depth))))
 
 
 ;;;; Document styles
@@ -1192,7 +1189,7 @@ Use `org-odt-object-counters' to generate an automatic
 OBJECT-NAME and STYLE-NAME.  If OBJECT-PROPS is non-nil, add a
 new entry in `org-odt-automatic-styles'.  Return (OBJECT-NAME
 . STYLE-NAME)."
-  (assert (stringp object-type))
+  (cl-assert (stringp object-type))
   (let* ((object (intern object-type))
         (seqvar object)
         (seqno (1+ (or (plist-get org-odt-object-counters seqvar) 0)))
@@ -1214,7 +1211,7 @@ new entry in `org-odt-automatic-styles'.  Return 
(OBJECT-NAME
   (let ((checkbox (org-element-property :checkbox item)))
     (if (not checkbox) ""
       (format "<text:span text:style-name=\"%s\">%s</text:span>"
-             "OrgCode" (case checkbox
+             "OrgCode" (cl-case checkbox
                          (on "[&#x2713;] ") ; CHECK MARK
                          (off "[ ] ")
                          (trans "[-] "))))))
@@ -1258,31 +1255,30 @@ new entry in `org-odt-automatic-styles'.  Return 
(OBJECT-NAME
           (case-fold-search nil)
           (re (mapconcat 'identity (mapcar 'car fmt-alist) "\\|"))
           match rpl (start 0) (filler-beg 0) filler-end filler output)
-      (mapc
-       (lambda (pair)
-        (setq fmt (replace-regexp-in-string (car pair) (cdr pair) fmt t t)))
-       '(("\\(?:%[[:digit:]]*N\\)" . "") ; strip ns, us and ns
-        ("%C" . "Y")                    ; replace century with year
-        ("%D" . "%m/%d/%y")
-        ("%G" . "Y")                 ; year corresponding to iso week
-        ("%I" . "%H")                ; hour on a 12-hour clock
-        ("%R" . "%H:%M")
-        ("%T" . "%H:%M:%S")
-        ("%U\\|%W" . "%V")           ; week no. starting on Sun./Mon.
-        ("%Z" . "")                  ; time zone name
-        ("%c" . "%Y-%M-%d %a %H:%M" ) ; locale's date and time format
-        ("%g" . "%y")
-        ("%X" . "%x" )  ; locale's pref. time format
-        ("%j" . "")     ; day of the year
-        ("%l" . "%k")   ; like %I blank-padded
-        ("%s" . "")     ; no. of secs since 1970-01-01 00:00:00 +0000
-        ("%n" . "<text:line-break/>")
-        ("%r" . "%I:%M:%S %p")
-        ("%t" . "<text:tab/>")
-        ("%u\\|%w" . "")  ; numeric day of week - Mon (1-7), Sun(0-6)
-        ("%x" . "%Y-%M-%d %a")         ; locale's pref. time format
-        ("%z" . "")                    ; time zone in numeric form
-        ))
+      (dolist (pair
+              '(("\\(?:%[[:digit:]]*N\\)" . "") ; strip ns, us and ns
+                ("%C" . "Y")           ; replace century with year
+                ("%D" . "%m/%d/%y")
+                ("%G" . "Y")         ; year corresponding to iso week
+                ("%I" . "%H")        ; hour on a 12-hour clock
+                ("%R" . "%H:%M")
+                ("%T" . "%H:%M:%S")
+                ("%U\\|%W" . "%V")   ; week no. starting on Sun./Mon.
+                ("%Z" . "")          ; time zone name
+                ("%c" . "%Y-%M-%d %a %H:%M" ) ; locale's date and time format
+                ("%g" . "%y")
+                ("%X" . "%x" )         ; locale's pref. time format
+                ("%j" . "")            ; day of the year
+                ("%l" . "%k")          ; like %I blank-padded
+                ("%s" . "") ; no. of secs since 1970-01-01 00:00:00 +0000
+                ("%n" . "<text:line-break/>")
+                ("%r" . "%I:%M:%S %p")
+                ("%t" . "<text:tab/>")
+                ("%u\\|%w" . "") ; numeric day of week - Mon (1-7), Sun(0-6)
+                ("%x" . "%Y-%M-%d %a") ; locale's pref. time format
+                ("%z" . "")            ; time zone in numeric form
+                ))
+       (setq fmt (replace-regexp-in-string (car pair) (cdr pair) fmt t t)))
       (while (string-match re fmt start)
        (setq match (match-string 0 fmt))
        (setq rpl (assoc-default match fmt-alist))
@@ -1312,11 +1308,11 @@ CONTENTS is the transcoded contents string.  RAW-DATA 
is the
 original parsed data.  INFO is a plist holding export options."
   ;; Write meta file.
   (let ((title (org-export-data (plist-get info :title) info))
+       (subtitle (org-export-data (plist-get info :subtitle) info))
        (author (let ((author (plist-get info :author)))
                  (if (not author) "" (org-export-data author info))))
-       (email (plist-get info :email))
-       (keywords (plist-get info :keywords))
-       (description (plist-get info :description)))
+       (keywords (or (plist-get info :keywords) ""))
+       (description (or (plist-get info :description) "")))
     (write-region
      (concat
       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
@@ -1345,12 +1341,14 @@ original parsed data.  INFO is a plist holding export 
options."
             (format "<meta:creation-date>%s</meta:creation-date>\n"
                     iso-date)))))
       (format "<meta:generator>%s</meta:generator>\n"
-             (let ((creator-info (plist-get info :with-creator)))
-               (if (or (not creator-info) (eq creator-info 'comment)) ""
-                 (plist-get info :creator))))
+             (plist-get info :creator))
       (format "<meta:keyword>%s</meta:keyword>\n" keywords)
       (format "<dc:subject>%s</dc:subject>\n" description)
       (format "<dc:title>%s</dc:title>\n" title)
+      (when (org-string-nw-p subtitle)
+       (format
+        "<meta:user-defined meta:name=\"subtitle\">%s</meta:user-defined>\n"
+        subtitle))
       "\n"
       "  </office:meta>\n" "</office:document-meta>")
      nil (concat org-odt-zip-dir "meta.xml"))
@@ -1361,11 +1359,12 @@ original parsed data.  INFO is a plist holding export 
options."
   ;; Copy styles.xml.  Also dump htmlfontify styles, if there is any.
   ;; Write styles file.
   (let* ((styles-file (plist-get info :odt-styles-file))
-        (styles-file (and styles-file (read (org-trim styles-file))))
+        (styles-file (and (org-string-nw-p styles-file)
+                          (read (org-trim styles-file))))
         ;; Non-availability of styles.xml is not a critical
         ;; error. For now, throw an error.
         (styles-file (or styles-file
-                         org-odt-styles-file
+                         (plist-get info :odt-styles-file)
                          (expand-file-name "OrgOdtStyles.xml"
                                            org-odt-styles-dir)
                          (error "org-odt: Missing styles file?"))))
@@ -1374,13 +1373,11 @@ original parsed data.  INFO is a plist holding export 
options."
       (let ((archive (nth 0 styles-file))
            (members (nth 1 styles-file)))
        (org-odt--zip-extract archive members org-odt-zip-dir)
-       (mapc
-        (lambda (member)
-          (when (org-file-image-p member)
-            (let* ((image-type (file-name-extension member))
-                   (media-type (format "image/%s" image-type)))
-              (org-odt-create-manifest-file-entry media-type member))))
-        members)))
+       (dolist (member members)
+         (when (org-file-image-p member)
+           (let* ((image-type (file-name-extension member))
+                  (media-type (format "image/%s" image-type)))
+             (org-odt-create-manifest-file-entry media-type member))))))
      ((and (stringp styles-file) (file-exists-p styles-file))
       (let ((styles-file-type (file-name-extension styles-file)))
        (cond
@@ -1390,7 +1387,7 @@ original parsed data.  INFO is a plist holding export 
options."
          (org-odt--zip-extract styles-file "styles.xml" org-odt-zip-dir)))))
      (t
       (error "Invalid specification of styles.xml file: %S"
-             org-odt-styles-file)))
+            (plist-get info :odt-styles-file))))
 
     ;; create a manifest entry for styles.xml
     (org-odt-create-manifest-file-entry "text/xml" "styles.xml")
@@ -1423,7 +1420,7 @@ original parsed data.  INFO is a plist holding export 
options."
       ;; currently the zip command zips up the entire temp directory so
       ;; that any auto-generated files created under the hood ends up in
       ;; the resulting odt file.
-      (set (make-local-variable 'backup-inhibited) t)
+      (setq-local backup-inhibited t)
 
       ;; Outline numbering is retained only upto LEVEL.
       ;; To disable outline numbering pass a LEVEL of 0.
@@ -1451,7 +1448,7 @@ original parsed data.  INFO is a plist holding export 
options."
            '("%Y-%M-%d %a" . "%Y-%M-%d %a %H:%M"))))
     (with-temp-buffer
       (insert-file-contents
-       (or org-odt-content-template-file
+       (or (plist-get info :odt-content-template-file)
           (expand-file-name "OrgOdtContentTemplate.xml"
                             org-odt-styles-dir)))
       ;; Write automatic styles.
@@ -1460,16 +1457,16 @@ original parsed data.  INFO is a plist holding export 
options."
       (re-search-forward "  </office:automatic-styles>" nil t)
       (goto-char (match-beginning 0))
       ;; - Dump automatic table styles.
-      (loop for (style-name props) in
-           (plist-get org-odt-automatic-styles 'Table) do
-           (when (setq props (or (plist-get props :rel-width) "96"))
-             (insert (format org-odt-table-style-format style-name props))))
+      (cl-loop for (style-name props) in
+              (plist-get org-odt-automatic-styles 'Table) do
+              (when (setq props (or (plist-get props :rel-width) "96"))
+                (insert (format org-odt-table-style-format style-name props))))
       ;; - Dump date-styles.
-      (when org-odt-use-date-fields
+      (when (plist-get info :odt-use-date-fields)
        (insert (org-odt--build-date-styles (car custom-time-fmts)
-                                             "OrgDate1")
+                                           "OrgDate1")
                (org-odt--build-date-styles (cdr custom-time-fmts)
-                                             "OrgDate2")))
+                                           "OrgDate2")))
       ;; Update display level.
       ;; - Remove existing sequence decls.  Also position the cursor.
       (goto-char (point-min))
@@ -1484,7 +1481,8 @@ original parsed data.  INFO is a plist holding export 
options."
         (lambda (x)
           (format
            "<text:sequence-decl text:display-outline-level=\"%d\" 
text:name=\"%s\"/>"
-           org-odt-display-outline-level (nth 1 x)))
+           (plist-get info :odt-display-outline-level)
+           (nth 1 x)))
         org-odt-category-map-alist "\n")))
       ;; Position the cursor to document body.
       (goto-char (point-min))
@@ -1493,7 +1491,10 @@ original parsed data.  INFO is a plist holding export 
options."
 
       ;; Preamble - Title, Author, Date etc.
       (insert
-       (let* ((title (org-export-data (plist-get info :title) info))
+       (let* ((title (and (plist-get info :with-title)
+                         (org-export-data (plist-get info :title) info)))
+             (subtitle (when title
+                         (org-export-data (plist-get info :subtitle) info)))
              (author (and (plist-get info :with-author)
                           (let ((auth (plist-get info :author)))
                             (and auth (org-export-data auth info)))))
@@ -1505,10 +1506,20 @@ original parsed data.  INFO is a plist holding export 
options."
          ;; Title.
          (when (org-string-nw-p title)
            (concat
-            (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
+            (format "\n<text:p text:style-name=\"%s\">%s</text:p>\n"
                     "OrgTitle" (format "\n<text:title>%s</text:title>" title))
             ;; Separator.
-            "\n<text:p text:style-name=\"OrgTitle\"/>"))
+            "\n<text:p text:style-name=\"OrgTitle\"/>\n"
+            ;; Subtitle.
+            (when (org-string-nw-p subtitle)
+              (concat
+               (format "<text:p 
text:style-name=\"OrgSubtitle\">\n%s\n</text:p>\n"
+                       (concat
+                        "<text:user-defined style:data-style-name=\"N0\" 
text:name=\"subtitle\">\n"
+                        subtitle
+                        "</text:user-defined>\n"))
+               ;; Separator.
+               "<text:p text:style-name=\"OrgSubtitle\"/>\n"))))
          (cond
           ((and author (not email))
            ;; Author only.
@@ -1537,14 +1548,15 @@ original parsed data.  INFO is a plist holding export 
options."
                   (timestamp (and (not (cdr date))
                                   (eq (org-element-type (car date)) 'timestamp)
                                   (car date))))
-             (concat
-              (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-                      "OrgSubtitle"
-                      (if (and org-odt-use-date-fields timestamp)
-                          (org-odt--format-timestamp (car date))
-                        (org-export-data (plist-get info :date) info)))
-              ;; Separator
-              "<text:p text:style-name=\"OrgSubtitle\"/>"))))))
+             (when date
+               (concat
+                (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
+                        "OrgSubtitle"
+                        (if (and (plist-get info :odt-use-date-fields) 
timestamp)
+                            (org-odt--format-timestamp (car date))
+                          (org-export-data date info)))
+                ;; Separator
+                "<text:p text:style-name=\"OrgSubtitle\"/>")))))))
       ;; Table of Contents
       (let* ((with-toc (plist-get info :with-toc))
             (depth (and with-toc (if (wholenump with-toc)
@@ -1562,7 +1574,7 @@ original parsed data.  INFO is a plist holding export 
options."
 
 ;;;; Bold
 
-(defun org-odt-bold (bold contents info)
+(defun org-odt-bold (_bold contents _info)
   "Transcode BOLD from Org to ODT.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
@@ -1572,7 +1584,7 @@ contextual information."
 
 ;;;; Center Block
 
-(defun org-odt-center-block (center-block contents info)
+(defun org-odt-center-block (_center-block contents _info)
   "Transcode a CENTER-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the center block.  INFO is a plist
 holding contextual information."
@@ -1599,7 +1611,7 @@ channel."
 
 ;;;; Code
 
-(defun org-odt-code (code contents info)
+(defun org-odt-code (code _contents _info)
   "Transcode a CODE object from Org to ODT.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -1608,16 +1620,6 @@ channel."
                     (org-element-property :value code))))
 
 
-;;;; Comment
-
-;; Comments are ignored.
-
-
-;;;; Comment Block
-
-;; Comment Blocks are ignored.
-
-
 ;;;; Drawer
 
 (defun org-odt-drawer (drawer contents info)
@@ -1625,14 +1627,14 @@ channel."
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   (let* ((name (org-element-property :drawer-name drawer))
-        (output (funcall org-odt-format-drawer-function
+        (output (funcall (plist-get info :odt-format-drawer-function)
                          name contents)))
     output))
 
 
 ;;;; Dynamic Block
 
-(defun org-odt-dynamic-block (dynamic-block contents info)
+(defun org-odt-dynamic-block (_dynamic-block contents _info)
   "Transcode a DYNAMIC-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information.  See `org-export-data'."
@@ -1641,7 +1643,7 @@ holding contextual information.  See `org-export-data'."
 
 ;;;; Entity
 
-(defun org-odt-entity (entity contents info)
+(defun org-odt-entity (entity _contents _info)
   "Transcode an ENTITY object from Org to ODT.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
@@ -1650,7 +1652,7 @@ contextual information."
 
 ;;;; Example Block
 
-(defun org-odt-example-block (example-block contents info)
+(defun org-odt-example-block (example-block _contents info)
   "Transcode a EXAMPLE-BLOCK element from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-odt-format-code example-block info))
@@ -1658,7 +1660,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Export Snippet
 
-(defun org-odt-export-snippet (export-snippet contents info)
+(defun org-odt-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (eq (org-export-snippet-backend export-snippet) 'odt)
@@ -1667,7 +1669,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Export Block
 
-(defun org-odt-export-block (export-block contents info)
+(defun org-odt-export-block (export-block _contents _info)
   "Transcode a EXPORT-BLOCK element from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (string= (org-element-property :type export-block) "ODT")
@@ -1676,10 +1678,10 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Fixed Width
 
-(defun org-odt-fixed-width (fixed-width contents info)
+(defun org-odt-fixed-width (fixed-width _contents info)
   "Transcode a FIXED-WIDTH element from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (org-odt-do-format-code (org-element-property :value fixed-width)))
+  (org-odt-do-format-code (org-element-property :value fixed-width) info))
 
 
 ;;;; Footnote Definition
@@ -1689,34 +1691,31 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Footnote Reference
 
-(defun org-odt-footnote-reference (footnote-reference contents info)
+(defun org-odt-footnote-reference (footnote-reference _contents info)
   "Transcode a FOOTNOTE-REFERENCE element from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((--format-footnote-definition
-        (function
-         (lambda (n def)
-           (setq n (format "%d" n))
-           (let ((id (concat  "fn" n))
-                 (note-class "footnote")
-                 (par-style "Footnote"))
-             (format
-              "<text:note text:id=\"%s\" text:note-class=\"%s\">%s</text:note>"
-              id note-class
-              (concat
-               (format "<text:note-citation>%s</text:note-citation>" n)
-               (format "<text:note-body>%s</text:note-body>" def)))))))
+        (lambda (n def)
+          (setq n (format "%d" n))
+          (let ((id (concat  "fn" n))
+                (note-class "footnote"))
+            (format
+             "<text:note text:id=\"%s\" text:note-class=\"%s\">%s</text:note>"
+             id note-class
+             (concat
+              (format "<text:note-citation>%s</text:note-citation>" n)
+              (format "<text:note-body>%s</text:note-body>" def))))))
        (--format-footnote-reference
-        (function
-         (lambda (n)
-           (setq n (format "%d" n))
-           (let ((note-class "footnote")
-                 (ref-format "text")
-                 (ref-name (concat "fn" n)))
-             (format
-              "<text:span text:style-name=\"%s\">%s</text:span>"
-              "OrgSuperscript"
-              (format "<text:note-ref text:note-class=\"%s\" 
text:reference-format=\"%s\" text:ref-name=\"%s\">%s</text:note-ref>"
-                      note-class ref-format ref-name n)))))))
+        (lambda (n)
+          (setq n (format "%d" n))
+          (let ((note-class "footnote")
+                (ref-format "text")
+                (ref-name (concat "fn" n)))
+            (format
+             "<text:span text:style-name=\"%s\">%s</text:span>"
+             "OrgSuperscript"
+             (format "<text:note-ref text:note-class=\"%s\" 
text:reference-format=\"%s\" text:ref-name=\"%s\">%s</text:note-ref>"
+                     note-class ref-format ref-name n))))))
     (concat
      ;; Insert separator between two footnotes in a row.
      (let ((prev (org-export-get-previous-element footnote-reference info)))
@@ -1724,12 +1723,11 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
            (format "<text:span text:style-name=\"%s\">%s</text:span>"
                    "OrgSuperscript" ",")))
      ;; Transcode footnote reference.
-     (let ((n (org-export-get-footnote-number footnote-reference info)))
+     (let ((n (org-export-get-footnote-number footnote-reference info nil t)))
        (cond
-       ((not (org-export-footnote-first-reference-p footnote-reference info))
+       ((not
+         (org-export-footnote-first-reference-p footnote-reference info nil t))
         (funcall --format-footnote-reference n))
-       ;; Inline definitions are secondary strings.
-       ;; Non-inline footnotes definitions are full Org data.
        (t
         (let* ((raw (org-export-get-footnote-definition
                      footnote-reference info))
@@ -1747,41 +1745,19 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
                                                 "OrgFootnoteCenter"
                                                 "OrgFootnoteQuotations")))))
                              info))))
-                  (if (eq (org-element-type raw) 'org-data) def
-                    (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-                            "Footnote" def)))))
+                  ;; Inline definitions are secondary strings.  We
+                  ;; need to wrap them within a paragraph.
+                  (if (eq (org-element-class (car (org-element-contents raw)))
+                          'element)
+                      def
+                    (format
+                     "\n<text:p text:style-name=\"Footnote\">%s</text:p>"
+                     def)))))
           (funcall --format-footnote-definition n def))))))))
 
 
 ;;;; Headline
 
-(defun* org-odt-format-headline
-    (todo todo-type priority text tags
-         &key level section-number headline-label &allow-other-keys)
-  (concat
-   ;; Todo.
-   (when todo
-     (let ((style (if (member todo org-done-keywords) "OrgDone" "OrgTodo")))
-       (format "<text:span text:style-name=\"%s\">%s</text:span> "
-              style todo)))
-   (when priority
-     (let* ((style (format "OrgPriority-%s" priority))
-           (priority (format "[#%c]" priority)))
-       (format "<text:span text:style-name=\"%s\">%s</text:span> "
-              style priority)))
-   ;; Title.
-   text
-   ;; Tags.
-   (when tags
-     (concat
-      "<text:tab/>"
-      (format "<text:span text:style-name=\"%s\">[%s]</text:span>"
-             "OrgTags" (mapconcat
-                        (lambda (tag)
-                          (format
-                           "<text:span text:style-name=\"%s\">%s</text:span>"
-                           "OrgTag" tag)) tags " : "))))))
-
 (defun org-odt-format-headline--wrap (headline backend info
                                               &optional format-function
                                               &rest extra-keys)
@@ -1804,20 +1780,19 @@ INFO is a plist holding contextual information."
                (org-element-property :title headline) backend info))
         (tags (and (plist-get info :with-tags)
                    (org-export-get-tags headline info)))
-        (headline-label (concat "sec-" (mapconcat 'number-to-string
-                                                  headline-number "-")))
-        (format-function (cond
-                          ((functionp format-function) format-function)
-                          ((not (eq org-odt-format-headline-function 'ignore))
-                           (function*
-                            (lambda (todo todo-type priority text tags
-                                          &allow-other-keys)
-                              (funcall org-odt-format-headline-function
-                                       todo todo-type priority text tags))))
-                          (t 'org-odt-format-headline))))
+        (headline-label (org-export-get-reference headline info))
+        (format-function
+         (if (functionp format-function) format-function
+           (cl-function
+            (lambda (todo todo-type priority text tags
+                     &key _level _section-number _headline-label
+                     &allow-other-keys)
+              (funcall (plist-get info :odt-format-headline-function)
+                       todo todo-type priority text tags))))))
     (apply format-function
-          todo todo-type  priority text tags
-          :headline-label headline-label :level level
+          todo todo-type priority text tags
+          :headline-label headline-label
+          :level level
           :section-number section-number extra-keys)))
 
 (defun org-odt-headline (headline contents info)
@@ -1826,26 +1801,16 @@ CONTENTS holds the contents of the headline.  INFO is a 
plist
 holding contextual information."
   ;; Case 1: This is a footnote section: ignore it.
   (unless (org-element-property :footnote-section-p headline)
-    (let* ((text (org-export-data (org-element-property :title headline) info))
-          ;; Create the headline text.
-          (full-text (org-odt-format-headline--wrap headline nil info))
+    (let* ((full-text (org-odt-format-headline--wrap headline nil info))
           ;; Get level relative to current parsed data.
           (level (org-export-get-relative-level headline info))
+          (numbered (org-export-numbered-headline-p headline info))
           ;; Get canonical label for the headline.
-          (id (concat "sec-" (mapconcat 'number-to-string
-                                        (org-export-get-headline-number
-                                         headline info) "-")))
-          ;; Get user-specified labels for the headline.
-          (extra-ids (list (org-element-property :CUSTOM_ID headline)
-                           (org-element-property :ID headline)))
+          (id (org-export-get-reference headline info))
           ;; Extra targets.
           (extra-targets
-           (mapconcat (lambda (x)
-                        (when x
-                          (let ((x (if (org-uuidgen-p x) (concat "ID-" x) x)))
-                            (org-odt--target
-                             "" (org-export-solidify-link-text x)))))
-                      extra-ids ""))
+           (let ((id (org-element-property :ID headline)))
+             (if id (org-odt--target "" (concat "ID-" id)) "")))
           ;; Title.
           (anchored-title (org-odt--target full-text id)))
       (cond
@@ -1858,8 +1823,7 @@ holding contextual information."
         (and (org-export-first-sibling-p headline info)
              (format "\n<text:list text:style-name=\"%s\" %s>"
                      ;; Choose style based on list type.
-                     (if (org-export-numbered-headline-p headline info)
-                         "OrgNumberedList" "OrgBulletedList")
+                     (if numbered "OrgNumberedList" "OrgBulletedList")
                      ;; If top-level list, re-start numbering.  Otherwise,
                      ;; continue numbering.
                      (format "text:continue-numbering=\"%s\""
@@ -1886,16 +1850,45 @@ holding contextual information."
        (t
        (concat
         (format
-         "\n<text:h text:style-name=\"%s\" 
text:outline-level=\"%s\">%s</text:h>"
-         (format "Heading_20_%s" level)
+         "\n<text:h text:style-name=\"%s\" text:outline-level=\"%s\" 
text:is-list-header=\"%s\">%s</text:h>"
+         (format "Heading_20_%s%s"
+                 level (if numbered "" "_unnumbered"))
          level
+         (if numbered "false" "true")
          (concat extra-targets anchored-title))
         contents))))))
 
+(defun org-odt-format-headline-default-function
+  (todo todo-type priority text tags)
+  "Default format function for a headline.
+See `org-odt-format-headline-function' for details."
+  (concat
+   ;; Todo.
+   (when todo
+     (let ((style (if (eq todo-type 'done) "OrgDone" "OrgTodo")))
+       (format "<text:span text:style-name=\"%s\">%s</text:span> " style 
todo)))
+   (when priority
+     (let* ((style (format "OrgPriority-%s" priority))
+           (priority (format "[#%c]" priority)))
+       (format "<text:span text:style-name=\"%s\">%s</text:span> "
+              style priority)))
+   ;; Title.
+   text
+   ;; Tags.
+   (when tags
+     (concat
+      "<text:tab/>"
+      (format "<text:span text:style-name=\"%s\">[%s]</text:span>"
+             "OrgTags" (mapconcat
+                        (lambda (tag)
+                          (format
+                           "<text:span text:style-name=\"%s\">%s</text:span>"
+                           "OrgTag" tag)) tags " : "))))))
+
 
 ;;;; Horizontal Rule
 
-(defun org-odt-horizontal-rule (horizontal-rule contents info)
+(defun org-odt-horizontal-rule (_horizontal-rule _contents _info)
   "Transcode an HORIZONTAL-RULE  object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
@@ -1913,18 +1906,15 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
   "Return a character not used in string S.
 This is used to choose a separator for constructs like \\verb."
   (let ((ll 
"~,./?;':\"|address@hidden&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
-    (loop for c across ll
-         when (not (string-match (regexp-quote (char-to-string c)) s))
-         return (char-to-string c))))
+    (cl-loop for c across ll
+            when (not (string-match (regexp-quote (char-to-string c)) s))
+            return (char-to-string c))))
 
-(defun org-odt-inline-src-block (inline-src-block contents info)
+(defun org-odt-inline-src-block (_inline-src-block _contents _info)
   "Transcode an INLINE-SRC-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let* ((org-lang (org-element-property :language inline-src-block))
-        (code (org-element-property :value inline-src-block))
-        (separator (org-odt--find-verb-separator code)))
-    (error "FIXME")))
+  (error "FIXME"))
 
 
 ;;;; Inlinetask
@@ -1933,33 +1923,37 @@ contextual information."
   "Transcode an INLINETASK element from Org to ODT.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (cond
-   ;; If `org-odt-format-inlinetask-function' is not 'ignore, call it
-   ;; with appropriate arguments.
-   ((not (eq org-odt-format-inlinetask-function 'ignore))
-    (let ((format-function
-          (function*
-           (lambda (todo todo-type priority text tags
-                    &key contents &allow-other-keys)
-             (funcall org-odt-format-inlinetask-function
-                      todo todo-type priority text tags contents)))))
-      (org-odt-format-headline--wrap
-       inlinetask nil info format-function :contents contents)))
-   ;; Otherwise, use a default template.
-   (t
-    (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-           "Text_20_body"
-           (org-odt--textbox
-            (concat
-             (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-                     "OrgInlineTaskHeading"
-                     (org-odt-format-headline--wrap inlinetask nil info))
-             contents)
-            nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\"")))))
+  (let* ((todo
+         (and (plist-get info :with-todo-keywords)
+              (let ((todo (org-element-property :todo-keyword inlinetask)))
+                (and todo (org-export-data todo info)))))
+        (todo-type (and todo (org-element-property :todo-type inlinetask)))
+        (priority (and (plist-get info :with-priority)
+                       (org-element-property :priority inlinetask)))
+        (text (org-export-data (org-element-property :title inlinetask) info))
+        (tags (and (plist-get info :with-tags)
+                   (org-export-get-tags inlinetask info))))
+    (funcall (plist-get info :odt-format-inlinetask-function)
+            todo todo-type priority text tags contents)))
+
+(defun org-odt-format-inlinetask-default-function
+  (todo todo-type priority name tags contents)
+  "Default format function for a inlinetasks.
+See `org-odt-format-inlinetask-function' for details."
+  (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
+         "Text_20_body"
+         (org-odt--textbox
+          (concat
+           (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
+                   "OrgInlineTaskHeading"
+                   (org-odt-format-headline-default-function
+                    todo todo-type priority name tags))
+           contents)
+          nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\"")))
 
 ;;;; Italic
 
-(defun org-odt-italic (italic contents info)
+(defun org-odt-italic (_italic contents _info)
   "Transcode ITALIC from Org to ODT.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
@@ -1974,32 +1968,21 @@ contextual information."
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
   (let* ((plain-list (org-export-get-parent item))
-        (type (org-element-property :type plain-list))
-        (counter (org-element-property :counter item))
-        (tag (let ((tag (org-element-property :tag item)))
-               (and tag
-                    (concat (org-odt--checkbox item)
-                            (org-export-data tag info))))))
-    (case type
-      ((ordered unordered descriptive-1 descriptive-2)
-       (format "\n<text:list-item>\n%s\n%s"
-              contents
-              (let* ((--element-has-a-table-p
-                      (function
-                       (lambda (element info)
-                         (loop for el in (org-element-contents element)
-                               thereis (eq (org-element-type el) 'table))))))
-                (cond
-                 ((funcall --element-has-a-table-p item info)
-                  "</text:list-header>")
-                 (t "</text:list-item>")))))
-      (t (error "Unknown list type: %S" type)))))
+        (type (org-element-property :type plain-list)))
+    (unless (memq type '(ordered unordered descriptive-1 descriptive-2))
+      (error "Unknown list type: %S" type))
+    (format "\n<text:list-item>\n%s\n%s"
+           contents
+           (if (org-element-map item 'table #'identity info 'first-match)
+               "</text:list-header>"
+             "</text:list-item>"))))
 
 ;;;; Keyword
 
-(defun org-odt-keyword (keyword contents info)
+(defun org-odt-keyword (keyword _contents info)
   "Transcode a KEYWORD element from Org to ODT.
-CONTENTS is nil.  INFO is a plist holding contextual information."
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
   (let ((key (org-element-property :key keyword))
        (value (org-element-property :value keyword)))
     (cond
@@ -2008,14 +1991,15 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
       ;; FIXME
       (ignore))
      ((string= key "TOC")
-      (let ((value (downcase value)))
+      (let ((case-fold-search t))
        (cond
-        ((string-match "\\<headlines\\>" value)
-         (let ((depth (or (and (string-match "[0-9]+" value)
+        ((string-match-p "\\<headlines\\>" value)
+         (let ((depth (or (and (string-match "\\<[0-9]+\\>" value)
                                (string-to-number (match-string 0 value)))
-                          (plist-get info :with-toc))))
-           (when (wholenump depth) (org-odt-toc depth info))))
-        ((member value '("tables" "figures" "listings"))
+                          (plist-get info :headline-levels)))
+               (localp (string-match-p "\\<local\\>" value)))
+           (org-odt-toc depth info (and localp keyword))))
+        ((string-match-p "tables\\|figures\\|listings" value)
          ;; FIXME
          (ignore))))))))
 
@@ -2031,34 +2015,33 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 ;;   (unless (> (length ad-return-value) 0)
 ;;     (setq ad-return-value (org-odt--encode-plain-text (ad-get-arg 0)))))
 
-(defun org-odt-latex-environment (latex-environment contents info)
+(defun org-odt-latex-environment (latex-environment _contents info)
   "Transcode a LATEX-ENVIRONMENT element from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let* ((latex-frag (org-remove-indentation
                      (org-element-property :value latex-environment))))
-    (org-odt-do-format-code latex-frag)))
+    (org-odt-do-format-code latex-frag info)))
 
 
 ;;;; Latex Fragment
 
 ;; (when latex-frag                    ; FIXME
-;;     (setq href (org-propertize href :title "LaTeX Fragment"
+;;     (setq href (propertize href :title "LaTeX Fragment"
 ;;                                :description latex-frag)))
 ;; handle verbatim
 ;; provide descriptions
 
-(defun org-odt-latex-fragment (latex-fragment contents info)
+(defun org-odt-latex-fragment (latex-fragment _contents _info)
   "Transcode a LATEX-FRAGMENT object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let* ((latex-frag (org-element-property :value latex-fragment))
-        (processing-type (plist-get info :with-latex)))
+  (let ((latex-frag (org-element-property :value latex-fragment)))
     (format "<text:span text:style-name=\"%s\">%s</text:span>"
            "OrgCode" (org-odt--encode-plain-text latex-frag t))))
 
 
 ;;;; Line Break
 
-(defun org-odt-line-break (line-break contents info)
+(defun org-odt-line-break (_line-break _contents _info)
   "Transcode a LINE-BREAK object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   "<text:line-break/>")
@@ -2069,29 +2052,29 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 ;;;; Links :: Label references
 
 (defun org-odt--enumerate (element info &optional predicate n)
-  (when predicate (assert (funcall predicate element info)))
+  (when predicate (cl-assert (funcall predicate element info)))
   (let* ((--numbered-parent-headline-at-<=-n
-         (function
-          (lambda (element n info)
-            (loop for x in (org-export-get-genealogy element)
-                  thereis (and (eq (org-element-type x) 'headline)
-                               (<= (org-export-get-relative-level x info) n)
-                               (org-export-numbered-headline-p x info)
-                               x)))))
+         (lambda (element n info)
+           (cl-loop for x in (org-element-lineage element)
+                    thereis (and (eq (org-element-type x) 'headline)
+                                 (<= (org-export-get-relative-level x info) n)
+                                 (org-export-numbered-headline-p x info)
+                                 x))))
         (--enumerate
-         (function
-          (lambda (element scope info &optional predicate)
-            (let ((counter 0))
-              (org-element-map (or scope (plist-get info :parse-tree))
-                  (org-element-type element)
-                (lambda (el)
-                  (and (or (not predicate) (funcall predicate el info))
-                       (incf counter)
-                       (eq element el)
-                       counter))
-                info 'first-match)))))
+         (lambda (element scope info &optional predicate)
+           (let ((counter 0))
+             (org-element-map (or scope (plist-get info :parse-tree))
+                 (org-element-type element)
+               (lambda (el)
+                 (and (or (not predicate) (funcall predicate el info))
+                      (cl-incf counter)
+                      (eq element el)
+                      counter))
+               info 'first-match))))
         (scope (funcall --numbered-parent-headline-at-<=-n
-                        element (or n org-odt-display-outline-level) info))
+                        element
+                        (or n (plist-get info :odt-display-outline-level))
+                        info))
         (ordinal (funcall --enumerate element scope info predicate))
         (tag
          (concat
@@ -2116,20 +2099,22 @@ the generated string.
 Return value is a string if OP is set to `reference' or a cons
 cell like CAPTION . SHORT-CAPTION) where CAPTION and
 SHORT-CAPTION are strings."
-  (assert (memq (org-element-type element) '(link table src-block paragraph)))
-  (let* ((caption-from
-         (case (org-element-type element)
+  (cl-assert (memq (org-element-type element) '(link table src-block 
paragraph)))
+  (let* ((element-or-parent
+         (cl-case (org-element-type element)
            (link (org-export-get-parent-element element))
            (t element)))
         ;; Get label and caption.
-        (label (org-element-property :name caption-from))
-        (caption (org-export-get-caption caption-from))
-        (caption (and caption (org-export-data caption info)))
+        (label (and (or (org-element-property :name element)
+                        (org-element-property :name element-or-parent))
+                    (org-export-get-reference element-or-parent info)))
+        (caption (let ((c (org-export-get-caption element-or-parent)))
+                   (and c (org-export-data c info))))
         ;; FIXME: We don't use short-caption for now
         (short-caption nil))
     (when (or label caption)
       (let* ((default-category
-              (case (org-element-type element)
+              (cl-case (org-element-type element)
                 (table "__Table__")
                 (src-block "__Listing__")
                 ((link paragraph)
@@ -2145,19 +2130,17 @@ SHORT-CAPTION are strings."
                 (t (error "Don't know how to format label for element type: %s"
                           (org-element-type element)))))
             seqno)
-       (assert default-category)
-       (destructuring-bind (counter label-style category predicate)
-           (assoc-default default-category org-odt-category-map-alist)
+       (cl-assert default-category)
+       (pcase-let
+           ((`(,counter ,label-style ,category ,predicate)
+             (assoc-default default-category org-odt-category-map-alist)))
          ;; Compute sequence number of the element.
          (setq seqno (org-odt--enumerate element info predicate))
          ;; Localize category string.
          (setq category (org-export-translate category :utf-8 info))
-         (case op
+         (cl-case op
            ;; Case 1: Handle Label definition.
            (definition
-             ;; Assign an internal label, if user has not provided one
-             (setq label (org-export-solidify-link-text
-                          (or label (format  "%s-%s" default-category seqno))))
              (cons
               (concat
                ;; Sneak in a bookmark.  The bookmark is used when the
@@ -2179,14 +2162,13 @@ SHORT-CAPTION are strings."
               short-caption))
            ;; Case 2: Handle Label reference.
            (reference
-            (assert label)
-            (setq label (org-export-solidify-link-text label))
             (let* ((fmt (cddr (assoc-string label-style org-odt-label-styles 
t)))
                    (fmt1 (car fmt))
                    (fmt2 (cadr fmt)))
               (format "<text:sequence-ref text:reference-format=\"%s\" 
text:ref-name=\"%s\">%s</text:sequence-ref>"
-                      fmt1 label (format-spec fmt2 `((?e . ,category)
-                                                     (?n . ,seqno))))))
+                      fmt1
+                      label
+                      (format-spec fmt2 `((?e . ,category) (?n . ,seqno))))))
            (t (error "Unknown %S on label" op))))))))
 
 
@@ -2199,7 +2181,7 @@ SHORT-CAPTION are strings."
         (target-dir "Images/")
         (target-file
          (format "%s%04d.%s" target-dir
-                 (incf org-odt-embedded-images-count) image-type)))
+                 (cl-incf org-odt-embedded-images-count) image-type)))
     (message "Embedding %s as %s..."
             (substring-no-properties path) target-file)
 
@@ -2211,8 +2193,8 @@ SHORT-CAPTION are strings."
     (org-odt-create-manifest-file-entry media-type target-file)
     target-file))
 
-(defun org-odt--image-size (file &optional user-width
-                                  user-height scale dpi embed-as)
+(defun org-odt--image-size
+  (file info &optional user-width user-height scale dpi embed-as)
   (let* ((--pixels-to-cms
          (function (lambda (pixels dpi)
                      (let ((cms-per-inch 2.54)
@@ -2224,7 +2206,7 @@ SHORT-CAPTION are strings."
             (and size-in-pixels
                  (cons (funcall --pixels-to-cms (car size-in-pixels) dpi)
                        (funcall --pixels-to-cms (cdr size-in-pixels) dpi))))))
-        (dpi (or dpi org-odt-pixels-per-inch))
+        (dpi (or dpi (plist-get info :odt-pixels-per-inch)))
         (anchor-type (or embed-as "paragraph"))
         (user-width (and (not scale) user-width))
         (user-height (and (not scale) user-height))
@@ -2278,7 +2260,7 @@ SHORT-CAPTION are strings."
   "Return ODT code for an inline image.
 LINK is the link pointing to the inline image.  INFO is a plist
 used as a communication channel."
-  (assert (eq (org-element-type element) 'link))
+  (cl-assert (eq (org-element-type element) 'link))
   (let* ((src (let* ((type (org-element-property :type element))
                     (raw-path (org-element-property :path element)))
                (cond ((member type '("http" "https"))
@@ -2293,7 +2275,7 @@ used as a communication channel."
                "\n<draw:image xlink:href=\"%s\" xlink:type=\"simple\" 
xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>"
                (org-odt--copy-image-file src-expanded)))
         ;; Extract attributes from #+ATTR_ODT line.
-        (attr-from (case (org-element-type element)
+        (attr-from (cl-case (org-element-type element)
                      (link (org-export-get-parent-element element))
                      (t element)))
         ;; Convert attributes to a plist.
@@ -2313,7 +2295,7 @@ used as a communication channel."
         ;; Handle `:width', `:height' and `:scale' properties.  Read
         ;; them as numbers since we need them for computations.
         (size (org-odt--image-size
-               src-expanded
+               src-expanded info
                (let ((width (plist-get attr-plist :width)))
                  (and width (read width)))
                (let ((length (plist-get attr-plist :length)))
@@ -2327,7 +2309,7 @@ used as a communication channel."
         (standalone-link-p (org-odt--standalone-link-p element info))
         (embed-as (if standalone-link-p "paragraph" "as-char"))
         (captions (org-odt-format-label element info 'definition))
-        (caption (car captions)) (short-caption (cdr captions))
+        (caption (car captions))
         (entity (concat (and caption "Captioned") embed-as "Image"))
         ;; Check if this link was created by LaTeX-to-PNG converter.
         (replaces (org-element-property
@@ -2342,14 +2324,13 @@ used as a communication channel."
         ;; description.  This quite useful for debugging.
         (desc (and replaces (org-element-property :value replaces))))
     (org-odt--render-image/formula entity href width height
-                                    captions user-frame-params title desc)))
+                                  captions user-frame-params title desc)))
 
 
 ;;;; Links :: Math formula
 
 (defun org-odt-link--inline-formula (element info)
-  (let* ((src (let* ((type (org-element-property :type element))
-                    (raw-path (org-element-property :path element)))
+  (let* ((src (let ((raw-path (org-element-property :path element)))
                (cond
                 ((file-name-absolute-p raw-path)
                  (expand-file-name raw-path))
@@ -2365,7 +2346,6 @@ used as a communication channel."
         (standalone-link-p (org-odt--standalone-link-p element info))
         (embed-as (if standalone-link-p 'paragraph 'character))
         (captions (org-odt-format-label element info 'definition))
-        (caption (car captions)) (short-caption (cdr captions))
         ;; Check if this link was created by LaTeX-to-MathML
         ;; converter.
         (replaces (org-element-property
@@ -2383,7 +2363,7 @@ used as a communication channel."
     (cond
      ((eq embed-as 'character)
       (org-odt--render-image/formula "InlineFormula" href width height
-                                      nil nil title desc))
+                                    nil nil title desc))
      (t
       (let* ((equation (org-odt--render-image/formula
                        "CaptionedDisplayFormula" href width height
@@ -2398,7 +2378,7 @@ used as a communication channel."
 (defun org-odt--copy-formula-file (src-file)
   "Returns the internal name of the file"
   (let* ((target-dir (format "Formula-%04d/"
-                            (incf org-odt-embedded-formulas-count)))
+                            (cl-incf org-odt-embedded-formulas-count)))
         (target-file (concat target-dir "content.xml")))
     ;; Create a directory for holding formula file.  Also enter it in
     ;; to manifest.
@@ -2408,13 +2388,13 @@ used as a communication channel."
     ;; Copy over the formula file from user directory to zip
     ;; directory.
     (message "Embedding %s as %s..." src-file target-file)
-    (let ((case-fold-search nil))
+    (let ((ext (file-name-extension src-file)))
       (cond
        ;; Case 1: Mathml.
-       ((string-match "\\.\\(mathml\\|mml\\)\\'" src-file)
+       ((member ext '("mathml" "mml"))
        (copy-file src-file (concat org-odt-zip-dir target-file) 'overwrite))
        ;; Case 2: OpenDocument formula.
-       ((string-match "\\.odf\\'" src-file)
+       ((string= ext "odf")
        (org-odt--zip-extract src-file "content.xml"
                                (concat org-odt-zip-dir target-dir)))
        (t (error "%s is not a formula file" src-file))))
@@ -2425,8 +2405,8 @@ used as a communication channel."
 ;;;; Targets
 
 (defun org-odt--render-image/formula (cfg-key href width height &optional
-                                               captions user-frame-params
-                                               &rest title-and-desc)
+                                             captions user-frame-params
+                                             &rest title-and-desc)
   (let* ((frame-cfg-alist
          ;; Each element of this alist is of the form (CFG-HANDLE
          ;; INNER-FRAME-PARAMS OUTER-FRAME-PARAMS).
@@ -2488,11 +2468,11 @@ used as a communication channel."
                                (lambda (default user)
                                  "Merge default and user frame params."
                                  (if (not user) default
-                                   (assert (= (length default) 3))
-                                   (assert (= (length user) 3))
-                                   (loop for u in user
-                                         for d in default
-                                         collect (or u d)))))))
+                                   (cl-assert (= (length default) 3))
+                                   (cl-assert (= (length user) 3))
+                                   (cl-loop for u in user
+                                            for d in default
+                                            collect (or u d)))))))
     (cond
      ;; Case 1: Image/Formula has no caption.
      ;;         There is only one frame, one that surrounds the image
@@ -2526,7 +2506,7 @@ used as a communication channel."
                      caption))
             width height outer)))))
 
-(defun org-odt--enumerable-p (element info)
+(defun org-odt--enumerable-p (element _info)
   ;; Element should have a caption or label.
   (or (org-element-property :caption element)
       (org-element-property :name element)))
@@ -2543,8 +2523,8 @@ used as a communication channel."
              (org-element-property :name p))))
    ;; Link should point to an image file.
    (lambda (l)
-     (assert (eq (org-element-type l) 'link))
-     (org-export-inline-image-p l org-odt-inline-image-rules))))
+     (cl-assert (eq (org-element-type l) 'link))
+     (org-export-inline-image-p l (plist-get info :odt-inline-image-rules)))))
 
 (defun org-odt--enumerable-latex-image-p (element info)
   (org-odt--standalone-link-p
@@ -2558,8 +2538,8 @@ used as a communication channel."
              (org-element-property :name p))))
    ;; Link should point to an image file.
    (lambda (l)
-     (assert (eq (org-element-type l) 'link))
-     (org-export-inline-image-p l org-odt-inline-image-rules))))
+     (cl-assert (eq (org-element-type l) 'link))
+     (org-export-inline-image-p l (plist-get info :odt-inline-image-rules)))))
 
 (defun org-odt--enumerable-formula-p (element info)
   (org-odt--standalone-link-p
@@ -2570,12 +2550,12 @@ used as a communication channel."
         (org-element-property :name p)))
    ;; Link should point to a MathML or ODF file.
    (lambda (l)
-     (assert (eq (org-element-type l) 'link))
-     (org-export-inline-image-p l org-odt-inline-formula-rules))))
+     (cl-assert (eq (org-element-type l) 'link))
+     (org-export-inline-image-p l (plist-get info 
:odt-inline-formula-rules)))))
 
-(defun org-odt--standalone-link-p (element info &optional
-                                            paragraph-predicate
-                                            link-predicate)
+(defun org-odt--standalone-link-p (element _info &optional
+                                          paragraph-predicate
+                                          link-predicate)
   "Test if ELEMENT is a standalone link for the purpose ODT export.
 INFO is a plist holding contextual information.
 
@@ -2589,7 +2569,7 @@ PARAGRAPH-PREDICATE in addition to having no other 
content save for
 leading and trailing whitespaces.
 
 Return nil, otherwise."
-  (let ((p (case (org-element-type element)
+  (let ((p (cl-case (org-element-type element)
             (paragraph element)
             (link (and (or (not link-predicate)
                            (funcall link-predicate element))
@@ -2599,23 +2579,24 @@ Return nil, otherwise."
       (when (or (not paragraph-predicate)
                (funcall paragraph-predicate p))
        (let ((contents (org-element-contents p)))
-         (loop for x in contents
-               with inline-image-count = 0
-               always (case (org-element-type x)
-                        (plain-text
-                         (not (org-string-nw-p x)))
-                        (link
-                         (and (or (not link-predicate)
-                                  (funcall link-predicate x))
-                              (= (incf inline-image-count) 1)))
-                        (t nil))))))))
+         (cl-loop for x in contents
+                  with inline-image-count = 0
+                  always (cl-case (org-element-type x)
+                           (plain-text
+                            (not (org-string-nw-p x)))
+                           (link
+                            (and (or (not link-predicate)
+                                     (funcall link-predicate x))
+                                 (= (cl-incf inline-image-count) 1)))
+                           (t nil))))))))
 
 (defun org-odt-link--infer-description (destination info)
-  ;; DESTINATION is a HEADLINE, a "<<target>>" or an element (like
-  ;; paragraph, verse-block etc) to which a "#+NAME: label" can be
-  ;; attached.  Note that labels that are attached to captioned
-  ;; entities - inline images, math formulae and tables - get resolved
-  ;; as part of `org-odt-format-label' and `org-odt--enumerate'.
+  ;; DESTINATION is a headline or an element (like paragraph,
+  ;; verse-block etc) to which a "#+NAME: label" can be attached.
+
+  ;; Note that labels that are attached to captioned entities - inline
+  ;; images, math formulae and tables - get resolved as part of
+  ;; `org-odt-format-label' and `org-odt--enumerate'.
 
   ;; Create a cross-reference to DESTINATION but make best-efforts to
   ;; create a *meaningful* description.  Check item numbers, section
@@ -2623,44 +2604,40 @@ Return nil, otherwise."
 
   ;; NOTE: Counterpart of `org-export-get-ordinal'.
   ;; FIXME: Handle footnote-definition footnote-reference?
-  (let* ((genealogy (org-export-get-genealogy destination))
+  (let* ((genealogy (org-element-lineage destination))
         (data (reverse genealogy))
-        (label (case (org-element-type destination)
-                 (headline
-                  (format "sec-%s" (mapconcat 'number-to-string
-                                              (org-export-get-headline-number
-                                               destination info) "-")))
-                 (target
-                  (org-element-property :value destination))
-                 (t (error "FIXME: Resolve %S" destination)))))
+        (label (let ((type (org-element-type destination)))
+                 (if (memq type '(headline target))
+                     (org-export-get-reference destination info)
+                   (error "FIXME: Unable to resolve %S" destination)))))
     (or
      (let* ( ;; Locate top-level list.
            (top-level-list
-            (loop for x on data
-                  when (eq (org-element-type (car x)) 'plain-list)
-                  return x))
+            (cl-loop for x on data
+                     when (eq (org-element-type (car x)) 'plain-list)
+                     return x))
            ;; Get list item nos.
            (item-numbers
-            (loop for (plain-list item . rest) on top-level-list by #'cddr
-                  until (not (eq (org-element-type plain-list) 'plain-list))
-                  collect (when (eq (org-element-property :type
-                                                          plain-list)
-                                    'ordered)
-                            (1+ (length (org-export-get-previous-element
-                                         item info t))))))
+            (cl-loop for (plain-list item . rest) on top-level-list by #'cddr
+                     until (not (eq (org-element-type plain-list) 'plain-list))
+                     collect (when (eq (org-element-property :type
+                                                             plain-list)
+                                       'ordered)
+                               (1+ (length (org-export-get-previous-element
+                                            item info t))))))
            ;; Locate top-most listified headline.
            (listified-headlines
-            (loop for x on data
-                  when (and (eq (org-element-type (car x)) 'headline)
-                            (org-export-low-level-p (car x) info))
-                  return x))
+            (cl-loop for x on data
+                     when (and (eq (org-element-type (car x)) 'headline)
+                               (org-export-low-level-p (car x) info))
+                     return x))
            ;; Get listified headline numbers.
            (listified-headline-nos
-            (loop for el in listified-headlines
-                  when (eq (org-element-type el) 'headline)
-                  collect (when (org-export-numbered-headline-p el info)
-                            (1+ (length (org-export-get-previous-element
-                                         el info t)))))))
+            (cl-loop for el in listified-headlines
+                     when (eq (org-element-type el) 'headline)
+                     collect (when (org-export-numbered-headline-p el info)
+                               (1+ (length (org-export-get-previous-element
+                                            el info t)))))))
        ;; Combine item numbers from both the listified headlines and
        ;; regular list items.
 
@@ -2669,33 +2646,37 @@ Return nil, otherwise."
        (let ((item-numbers (append listified-headline-nos item-numbers)))
         (when (and item-numbers (not (memq nil item-numbers)))
           (format "<text:bookmark-ref 
text:reference-format=\"number-all-superior\" 
text:ref-name=\"%s\">%s</text:bookmark-ref>"
-                  (org-export-solidify-link-text label)
+                  label
                   (mapconcat (lambda (n) (if (not n) " "
-                                           (concat (number-to-string n) ".")))
+                                      (concat (number-to-string n) ".")))
                              item-numbers "")))))
      ;; Case 2: Locate a regular and numbered headline in the
      ;; hierarchy.  Display its section number.
-     (let ((headline (loop for el in (cons destination genealogy)
-                          when (and (eq (org-element-type el) 'headline)
-                                    (not (org-export-low-level-p el info))
-                                    (org-export-numbered-headline-p el info))
-                          return el)))
+     (let ((headline
+           (and
+            ;; Test if destination is a numbered headline.
+            (org-export-numbered-headline-p destination info)
+            (cl-loop for el in (cons destination genealogy)
+                     when (and (eq (org-element-type el) 'headline)
+                               (not (org-export-low-level-p el info))
+                               (org-export-numbered-headline-p el info))
+                     return el))))
        ;; We found one.
        (when headline
         (format "<text:bookmark-ref text:reference-format=\"chapter\" 
text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
-                (org-export-solidify-link-text label)
+                label
                 (mapconcat 'number-to-string (org-export-get-headline-number
                                               headline info) "."))))
      ;; Case 4: Locate a regular headline in the hierarchy.  Display
      ;; its title.
-     (let ((headline (loop for el in (cons destination genealogy)
-                          when (and (eq (org-element-type el) 'headline)
-                                    (not (org-export-low-level-p el info)))
-                          return el)))
+     (let ((headline (cl-loop for el in (cons destination genealogy)
+                             when (and (eq (org-element-type el) 'headline)
+                                       (not (org-export-low-level-p el info)))
+                             return el)))
        ;; We found one.
        (when headline
         (format "<text:bookmark-ref text:reference-format=\"text\" 
text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
-                (org-export-solidify-link-text label)
+                label
                 (let ((title (org-element-property :title headline)))
                   (org-export-data title info)))))
      (error "FIXME?"))))
@@ -2711,24 +2692,23 @@ INFO is a plist holding contextual information.  See
         ;; Ensure DESC really exists, or set it to nil.
         (desc (and (not (string= desc "")) desc))
         (imagep (org-export-inline-image-p
-                 link org-odt-inline-image-rules))
+                 link (plist-get info :odt-inline-image-rules)))
         (path (cond
                ((member type '("http" "https" "ftp" "mailto"))
                 (concat type ":" raw-path))
-               ((and (string= type "file") (file-name-absolute-p raw-path))
-                (concat "file:" raw-path))
+               ((string= type "file") (org-export-file-uri raw-path))
                (t raw-path)))
         ;; Convert & to &amp; for correct XML representation
-        (path (replace-regexp-in-string "&" "&amp;" path))
-        protocol)
+        (path (replace-regexp-in-string "&" "&amp;" path)))
     (cond
+     ;; Link type is handled by a special function.
+     ((org-export-custom-protocol-maybe link desc 'odt))
      ;; Image file.
-     ((and (not desc) (org-export-inline-image-p
-                      link org-odt-inline-image-rules))
-      (org-odt-link--inline-image link info))
+     ((and (not desc) imagep) (org-odt-link--inline-image link info))
      ;; Formula file.
-     ((and (not desc) (org-export-inline-image-p
-                      link org-odt-inline-formula-rules))
+     ((and (not desc)
+          (org-export-inline-image-p
+           link (plist-get info :odt-inline-formula-rules)))
       (org-odt-link--inline-formula link info))
      ;; Radio target: Transcode target's contents and use them as
      ;; link's description.
@@ -2737,8 +2717,7 @@ INFO is a plist holding contextual information.  See
        (if (not destination) desc
          (format
           "<text:bookmark-ref text:reference-format=\"text\" 
text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
-          (org-export-solidify-link-text
-           (org-element-property :value destination))
+          (org-export-get-reference destination info)
           desc))))
      ;; Links pointing to a headline: Find destination and build
      ;; appropriate referencing command.
@@ -2746,55 +2725,46 @@ INFO is a plist holding contextual information.  See
       (let ((destination (if (string= type "fuzzy")
                             (org-export-resolve-fuzzy-link link info)
                           (org-export-resolve-id-link link info))))
-       (case (org-element-type destination)
-         ;; Case 1: Fuzzy link points nowhere.
-         ('nil
-          (format "<text:span text:style-name=\"%s\">%s</text:span>"
-                  "Emphasis"
-                  (or desc
-                      (org-export-data (org-element-property :raw-link link)
-                                       info))))
-         ;; Case 2: Fuzzy link points to a headline.
+       (cl-case (org-element-type destination)
+         ;; Fuzzy link points to a headline.  If there's
+         ;; a description, create a hyperlink.  Otherwise, try to
+         ;; provide a meaningful description.
          (headline
-          ;; If there's a description, create a hyperlink.
-          ;; Otherwise, try to provide a meaningful description.
           (if (not desc) (org-odt-link--infer-description destination info)
-            (let* ((headline-no
-                    (org-export-get-headline-number destination info))
-                   (label
-                    (format "sec-%s"
-                            (mapconcat 'number-to-string headline-no "-"))))
+            (let ((label
+                   (or (and (string= type "custom-id")
+                            (org-element-property :CUSTOM_ID destination))
+                       (org-export-get-reference destination info))))
               (format
                "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
                label desc))))
-         ;; Case 3: Fuzzy link points to a target.
+         ;; Fuzzy link points to a target.  If there's a description,
+         ;; create a hyperlink.  Otherwise, try to provide
+         ;; a meaningful description.
          (target
-          ;; If there's a description, create a hyperlink.
-          ;; Otherwise, try to provide a meaningful description.
-          (if (not desc) (org-odt-link--infer-description destination info)
-            (let ((label (org-element-property :value destination)))
-              (format "<text:a xlink:type=\"simple\" 
xlink:href=\"#%s\">%s</text:a>"
-                      (org-export-solidify-link-text label)
-                      desc))))
-         ;; Case 4: Fuzzy link points to some element (e.g., an
-         ;; inline image, a math formula or a table).
+          (format "<text:a xlink:type=\"simple\" 
xlink:href=\"#%s\">%s</text:a>"
+                  (org-export-get-reference destination info)
+                  (or desc (org-export-get-ordinal destination info))))
+         ;; Fuzzy link points to some element (e.g., an inline image,
+         ;; a math formula or a table).
          (otherwise
           (let ((label-reference
-                 (ignore-errors (org-odt-format-label
-                                 destination info 'reference))))
-            (cond ((not label-reference)
-                   (org-odt-link--infer-description destination info))
-                  ;; LINK has no description.  Create
-                  ;; a cross-reference showing entity's sequence
-                  ;; number.
-                  ((not desc) label-reference)
-                  ;; LINK has description.  Insert a hyperlink with
-                  ;; user-provided description.
-                  (t
-                   (let ((label (org-element-property :name destination)))
-                     (format "<text:a xlink:type=\"simple\" 
xlink:href=\"#%s\">%s</text:a>"
-                             (org-export-solidify-link-text label)
-                             desc)))))))))
+                 (ignore-errors
+                   (org-odt-format-label destination info 'reference))))
+            (cond
+             ((not label-reference)
+              (org-odt-link--infer-description destination info))
+             ;; LINK has no description.  Create
+             ;; a cross-reference showing entity's sequence
+             ;; number.
+             ((not desc) label-reference)
+             ;; LINK has description.  Insert a hyperlink with
+             ;; user-provided description.
+             (t
+              (format
+               "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
+               (org-export-get-reference destination info)
+               desc))))))))
      ;; Coderef: replace link with the reference name or the
      ;; equivalent line number.
      ((string= type "coderef")
@@ -2805,9 +2775,6 @@ INFO is a plist holding contextual information.  See
         (format
          "<text:bookmark-ref text:reference-format=\"number\" 
text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
          href line-no))))
-     ;; Link type is handled by a special function.
-     ((functionp (setq protocol (nth 2 (assoc type org-link-protocols))))
-      (funcall protocol (org-link-unescape path) desc 'odt))
      ;; External link with a description part.
      ((and path desc)
       (let ((link-contents (org-element-contents link)))
@@ -2816,7 +2783,8 @@ INFO is a plist holding contextual information.  See
                 (let ((desc-element (car link-contents)))
                   (and (eq (org-element-type desc-element) 'link)
                        (org-export-inline-image-p
-                        desc-element org-odt-inline-image-rules))))
+                        desc-element
+                        (plist-get info :odt-inline-image-rules)))))
            ;; Format link as a clickable image.
            (format "\n<draw:a xlink:type=\"simple\" 
xlink:href=\"%s\">\n%s\n</draw:a>"
                    path desc)
@@ -2832,6 +2800,18 @@ INFO is a plist holding contextual information.  See
                "Emphasis" desc)))))
 
 
+;;;; Node Property
+
+(defun org-odt-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to ODT.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (org-odt--encode-plain-text
+   (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) "")))))
+
 ;;;; Paragraph
 
 (defun org-odt--paragraph-style (paragraph)
@@ -2841,7 +2821,7 @@ Style is a symbol among `quoted', `centered' and nil."
     (while (and (setq up (org-element-property :parent up))
                (not (memq (org-element-type up)
                           '(center-block quote-block section)))))
-    (case (org-element-type up)
+    (cl-case (org-element-type up)
       (center-block 'centered)
       (quote-block 'quoted))))
 
@@ -2853,7 +2833,7 @@ a plist used as a communication channel.  DEFAULT, CENTER 
and
 QUOTE are, respectively, style to use when paragraph belongs to
 no special environment, a center block, or a quote block."
   (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-         (case (org-odt--paragraph-style paragraph)
+         (cl-case (org-odt--paragraph-style paragraph)
            (quoted quote)
            (centered center)
            (otherwise default))
@@ -2879,13 +2859,13 @@ the plist used as a communication channel."
 
 ;;;; Plain List
 
-(defun org-odt-plain-list (plain-list contents info)
+(defun org-odt-plain-list (plain-list contents _info)
   "Transcode a PLAIN-LIST element from Org to ODT.
 CONTENTS is the contents of the list.  INFO is a plist holding
 contextual information."
   (format "\n<text:list text:style-name=\"%s\" %s>\n%s</text:list>"
          ;; Choose style based on list type.
-         (case (org-element-property :type plain-list)
+         (cl-case (org-element-property :type plain-list)
            (ordered "OrgNumberedList")
            (unordered "OrgBulletedList")
            (descriptive-1 "OrgDescriptionList")
@@ -2902,22 +2882,15 @@ contextual information."
 
 (defun org-odt--encode-tabs-and-spaces (line)
   (replace-regexp-in-string
-   "\\([\t]\\|\\([ ]+\\)\\)"
+   "\\(\t\\| \\{2,\\}\\)"
    (lambda (s)
-     (cond
-      ((string= s "\t") "<text:tab/>")
-      (t (let ((n (length s)))
-          (cond
-           ((= n 1) " ")
-           ((> n 1) (concat " " (format "<text:s text:c=\"%d\"/>" (1- n))))
-           (t ""))))))
+     (if (string= s "\t") "<text:tab/>"
+       (format " <text:s text:c=\"%d\"/>" (1- (length s)))))
    line))
 
 (defun org-odt--encode-plain-text (text &optional no-whitespace-filling)
-  (mapc
-   (lambda (pair)
-     (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))
-   '(("&" . "&amp;") ("<" . "&lt;") (">" . "&gt;")))
+  (dolist (pair '(("&" . "&amp;") ("<" . "&lt;") (">" . "&gt;")))
+    (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))
   (if no-whitespace-filling text
     (org-odt--encode-tabs-and-spaces text)))
 
@@ -2934,11 +2907,9 @@ contextual information."
       (setq output (org-export-activate-smart-quotes output :utf-8 info text)))
     ;; Convert special strings.
     (when (plist-get info :with-special-strings)
-      (mapc
-       (lambda (pair)
-        (setq output
-              (replace-regexp-in-string (car pair) (cdr pair) output t nil)))
-       org-odt-special-string-regexps))
+      (dolist (pair org-odt-special-string-regexps)
+       (setq output
+             (replace-regexp-in-string (car pair) (cdr pair) output t nil))))
     ;; Handle break preservation if required.
     (when (plist-get info :preserve-breaks)
       (setq output (replace-regexp-in-string
@@ -2978,34 +2949,24 @@ channel."
 
 ;;;; Property Drawer
 
-(defun org-odt-property-drawer (property-drawer contents info)
+(defun org-odt-property-drawer (_property-drawer contents _info)
   "Transcode a PROPERTY-DRAWER element from Org to ODT.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  ;; The property drawer isn't exported but we want separating blank
-  ;; lines nonetheless.
-  "")
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (format "<text:p text:style-name=\"OrgFixedWidthBlock\">%s</text:p>"
+              contents)))
 
 
 ;;;; Quote Block
 
-(defun org-odt-quote-block (quote-block contents info)
+(defun org-odt-quote-block (_quote-block contents _info)
   "Transcode a QUOTE-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   contents)
 
 
-;;;; Quote Section
-
-(defun org-odt-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to ODT.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((value (org-remove-indentation
-               (org-element-property :value quote-section))))
-    (when value (org-odt-do-format-code value))))
-
-
 ;;;; Section
 
 (defun org-odt-format-section (text style &optional name)
@@ -3016,7 +2977,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
            text)))
 
 
-(defun org-odt-section (section contents info) ; FIXME
+(defun org-odt-section (_section contents _info) ; FIXME
   "Transcode a SECTION element from Org to ODT.
 CONTENTS holds the contents of the section.  INFO is a plist
 holding contextual information."
@@ -3028,9 +2989,7 @@ holding contextual information."
   "Transcode a RADIO-TARGET object from Org to ODT.
 TEXT is the text of the target.  INFO is a plist holding
 contextual information."
-  (org-odt--target
-   text (org-export-solidify-link-text
-        (org-element-property :value radio-target))))
+  (org-odt--target text (org-export-get-reference radio-target info)))
 
 
 ;;;; Special Block
@@ -3039,7 +2998,7 @@ contextual information."
   "Transcode a SPECIAL-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
-  (let ((type (downcase (org-element-property :type special-block)))
+  (let ((type (org-element-property :type special-block))
        (attributes (org-export-read-attribute :attr_odt special-block)))
     (cond
      ;; Annotation.
@@ -3109,31 +3068,30 @@ and prefix with \"OrgSrc\".  For example,
     (cons style-name style)))
 
 (defun org-odt-htmlfontify-string (line)
-  (let* ((hfy-html-quote-regex "\\([<\"&>      ]\\)")
+  (let* ((hfy-html-quote-regex "\\([<\"&> \t]\\)")
         (hfy-html-quote-map '(("\"" "&quot;")
                               ("<" "&lt;")
                               ("&" "&amp;")
                               (">" "&gt;")
                               (" " "<text:s/>")
-                              ("       " "<text:tab/>")))
+                              ("\t" "<text:tab/>")))
         (hfy-face-to-css 'org-odt-hfy-face-to-css)
         (hfy-optimizations-1 (copy-sequence hfy-optimizations))
-        (hfy-optimizations (add-to-list 'hfy-optimizations-1
-                                        'body-text-only))
+        (hfy-optimizations (cl-pushnew 'body-text-only hfy-optimizations-1))
         (hfy-begin-span-handler
-         (lambda (style text-block text-id text-begins-block-p)
+         (lambda (style _text-block _text-id _text-begins-block-p)
            (insert (format "<text:span text:style-name=\"%s\">" style))))
-        (hfy-end-span-handler (lambda nil (insert "</text:span>"))))
-    (org-no-warnings (htmlfontify-string line))))
+        (hfy-end-span-handler (lambda () (insert "</text:span>"))))
+    (with-no-warnings (htmlfontify-string line))))
 
 (defun org-odt-do-format-code
-  (code &optional lang refs retain-labels num-start)
+    (code info &optional lang refs retain-labels num-start)
   (let* ((lang (or (assoc-default lang org-src-lang-modes) lang))
         (lang-mode (and lang (intern (format "%s-mode" lang))))
         (code-lines (org-split-string code "\n"))
         (code-length (length code-lines))
         (use-htmlfontify-p (and (functionp lang-mode)
-                                org-odt-fontify-srcblocks
+                                (plist-get info :odt-fontify-srcblocks)
                                 (require 'htmlfontify nil t)
                                 (fboundp 'htmlfontify-string)))
         (code (if (not use-htmlfontify-p) code
@@ -3147,19 +3105,20 @@ and prefix with \"OrgSrc\".  For example,
         (par-style (if use-htmlfontify-p "OrgSrcBlock"
                      "OrgFixedWidthBlock"))
         (i 0))
-    (assert (= code-length (length (org-split-string code "\n"))))
+    (cl-assert (= code-length (length (org-split-string code "\n"))))
     (setq code
          (org-export-format-code
           code
           (lambda (loc line-num ref)
             (setq par-style
-                  (concat par-style (and (= (incf i) code-length) "LastLine")))
+                  (concat par-style (and (= (cl-incf i) code-length)
+                                         "LastLine")))
 
             (setq loc (concat loc (and ref retain-labels (format " (%s)" 
ref))))
             (setq loc (funcall fontifier loc))
             (when ref
               (setq loc (org-odt--target loc (concat "coderef-" ref))))
-            (assert par-style)
+            (cl-assert par-style)
             (setq loc (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
                               par-style loc))
             (if (not line-num) loc
@@ -3185,19 +3144,15 @@ and prefix with \"OrgSrc\".  For example,
         ;; Does the src block contain labels?
         (retain-labels (org-element-property :retain-labels element))
         ;; Does it have line numbers?
-        (num-start (case (org-element-property :number-lines element)
-                     (continued (org-export-get-loc element info))
-                     (new 0))))
-    (org-odt-do-format-code code lang refs retain-labels num-start)))
+        (num-start (org-export-get-loc element info)))
+    (org-odt-do-format-code code info lang refs retain-labels num-start)))
 
-(defun org-odt-src-block (src-block contents info)
+(defun org-odt-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to ODT.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let* ((lang (org-element-property :language src-block))
-        (attributes (org-export-read-attribute :attr_odt src-block))
-        (captions (org-odt-format-label src-block info 'definition))
-        (caption (car captions)) (short-caption (cdr captions)))
+  (let* ((attributes (org-export-read-attribute :attr_odt src-block))
+        (caption (car (org-odt-format-label src-block info 'definition))))
     (concat
      (and caption
          (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
@@ -3211,7 +3166,7 @@ contextual information."
 
 ;;;; Statistics Cookie
 
-(defun org-odt-statistics-cookie (statistics-cookie contents info)
+(defun org-odt-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((cookie-value (org-element-property :value statistics-cookie)))
@@ -3221,7 +3176,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Strike-Through
 
-(defun org-odt-strike-through (strike-through contents info)
+(defun org-odt-strike-through (_strike-through contents _info)
   "Transcode STRIKE-THROUGH from Org to ODT.
 CONTENTS is the text with strike-through markup.  INFO is a plist
 holding contextual information."
@@ -3231,7 +3186,7 @@ holding contextual information."
 
 ;;;; Subscript
 
-(defun org-odt-subscript (subscript contents info)
+(defun org-odt-subscript (_subscript contents _info)
   "Transcode a SUBSCRIPT object from Org to ODT.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -3241,7 +3196,7 @@ contextual information."
 
 ;;;; Superscript
 
-(defun org-odt-superscript (superscript contents info)
+(defun org-odt-superscript (_superscript contents _info)
   "Transcode a SUPERSCRIPT object from Org to ODT.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -3255,7 +3210,7 @@ contextual information."
   (let* ((table (org-export-get-parent-table element))
         (table-attributes (org-export-read-attribute :attr_odt table))
         (table-style (plist-get table-attributes :style)))
-    (assoc table-style org-odt-table-styles)))
+    (assoc table-style (plist-get info :odt-table-styles))))
 
 (defun org-odt-get-table-cell-styles (table-cell info)
   "Retrieve styles applicable to a table cell.
@@ -3296,23 +3251,23 @@ styles congruent with the ODF-1.2 specification."
             (cell-style-selectors (nth 2 style-spec))
             (cell-type
              (cond
-              ((and (cdr (assoc 'use-first-column-styles cell-style-selectors))
+              ((and (cdr (assq 'use-first-column-styles cell-style-selectors))
                     (= c 0)) "FirstColumn")
-              ((and (cdr (assoc 'use-last-column-styles cell-style-selectors))
+              ((and (cdr (assq 'use-last-column-styles cell-style-selectors))
                     (= (1+ c) (cdr table-dimensions)))
                "LastColumn")
-              ((and (cdr (assoc 'use-first-row-styles cell-style-selectors))
+              ((and (cdr (assq 'use-first-row-styles cell-style-selectors))
                     (= r 0)) "FirstRow")
-              ((and (cdr (assoc 'use-last-row-styles cell-style-selectors))
+              ((and (cdr (assq 'use-last-row-styles cell-style-selectors))
                     (= (1+ r) (car table-dimensions)))
                "LastRow")
-              ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors))
+              ((and (cdr (assq 'use-banding-rows-styles cell-style-selectors))
                     (= (% r 2) 1)) "EvenRow")
-              ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors))
+              ((and (cdr (assq 'use-banding-rows-styles cell-style-selectors))
                     (= (% r 2) 0)) "OddRow")
-              ((and (cdr (assoc 'use-banding-columns-styles 
cell-style-selectors))
+              ((and (cdr (assq 'use-banding-columns-styles 
cell-style-selectors))
                     (= (% c 2) 1)) "EvenColumn")
-              ((and (cdr (assoc 'use-banding-columns-styles 
cell-style-selectors))
+              ((and (cdr (assq 'use-banding-columns-styles 
cell-style-selectors))
                     (= (% c 2) 0)) "OddColumn")
               (t ""))))
        (concat template-name cell-type)))))
@@ -3370,17 +3325,16 @@ channel."
                        (1+ horiz-span))))))
     (unless contents (setq contents ""))
     (concat
-     (assert paragraph-style)
+     (cl-assert paragraph-style)
      (format "\n<table:table-cell%s>\n%s\n</table:table-cell>"
             cell-attributes
             (let ((table-cell-contents (org-element-contents table-cell)))
-              (if (memq (org-element-type (car table-cell-contents))
-                        org-element-all-elements)
+              (if (eq (org-element-class (car table-cell-contents)) 'element)
                   contents
                 (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
                         paragraph-style contents))))
      (let (s)
-       (dotimes (i horiz-span s)
+       (dotimes (_ horiz-span s)
         (setq s (concat s "\n<table:covered-table-cell/>"))))
      "\n")))
 
@@ -3431,7 +3385,7 @@ communication channel."
   "Transcode a TABLE element from Org to ODT.
 CONTENTS is the contents of the table.  INFO is a plist holding
 contextual information."
-  (case (org-element-property :type table)
+  (cl-case (org-element-property :type table)
     ;; Case 1: table.el doesn't support export to OD format.  Strip
     ;; such tables from export.
     (table.el
@@ -3448,20 +3402,19 @@ contextual information."
            (attributes (org-export-read-attribute :attr_odt table))
            (custom-table-style (nth 1 (org-odt-table-style-spec table info)))
            (table-column-specs
-            (function
-             (lambda (table info)
-               (let* ((table-style (or custom-table-style "OrgTable"))
-                      (column-style (format "%sColumn" table-style)))
-                 (mapconcat
-                  (lambda (table-cell)
-                    (let ((width (1+ (or (org-export-table-cell-width
-                                          table-cell info) 0)))
-                          (s (format
-                              "\n<table:table-column table:style-name=\"%s\"/>"
-                              column-style))
-                          out)
-                      (dotimes (i width out) (setq out (concat s out)))))
-                  (org-odt-table-first-row-data-cells table info) "\n"))))))
+            (lambda (table info)
+              (let* ((table-style (or custom-table-style "OrgTable"))
+                     (column-style (format "%sColumn" table-style)))
+                (mapconcat
+                 (lambda (table-cell)
+                   (let ((width (1+ (or (org-export-table-cell-width
+                                         table-cell info) 0)))
+                         (s (format
+                             "\n<table:table-column table:style-name=\"%s\"/>"
+                             column-style))
+                         out)
+                     (dotimes (_ width out) (setq out (concat s out)))))
+                 (org-odt-table-first-row-data-cells table info) "\n")))))
        (concat
        ;; caption.
        (when caption
@@ -3490,84 +3443,84 @@ contextual information.
 Use `org-odt--table' to typeset the table.  Handle details
 pertaining to indentation here."
   (let* ((--element-preceded-by-table-p
-         (function
-          (lambda (element info)
-            (loop for el in (org-export-get-previous-element element info t)
-                  thereis (eq (org-element-type el) 'table)))))
+         (lambda (element info)
+           (cl-loop for el in (org-export-get-previous-element element info t)
+                    thereis (eq (org-element-type el) 'table))))
         (--walk-list-genealogy-and-collect-tags
-         (function
-          (lambda (table info)
-            (let* ((genealogy (org-export-get-genealogy table))
-                   (list-genealogy
-                    (when (eq (org-element-type (car genealogy)) 'item)
-                      (loop for el in genealogy
-                            when (memq (org-element-type el)
-                                       '(item plain-list))
-                            collect el)))
-                   (llh-genealogy
-                    (apply 'nconc
-                           (loop for el in genealogy
-                                 when (and (eq (org-element-type el) 'headline)
-                                           (org-export-low-level-p el info))
-                                 collect
-                                 (list el
-                                       (assq 'headline
-                                             (org-element-contents
-                                              (org-export-get-parent el)))))))
-                   parent-list)
-              (nconc
-               ;; Handle list genealogy.
-               (loop for el in list-genealogy collect
-                     (case (org-element-type el)
-                       (plain-list
-                        (setq parent-list el)
-                        (cons "</text:list>"
-                              (format "\n<text:list text:style-name=\"%s\" %s>"
-                                      (case (org-element-property :type el)
-                                        (ordered "OrgNumberedList")
-                                        (unordered "OrgBulletedList")
-                                        (descriptive-1 "OrgDescriptionList")
-                                        (descriptive-2 "OrgDescriptionList"))
-                                      "text:continue-numbering=\"true\"")))
-                       (item
-                        (cond
-                         ((not parent-list)
-                          (if (funcall --element-preceded-by-table-p table 
info)
-                              '("</text:list-header>" . "<text:list-header>")
-                            '("</text:list-item>" . "<text:list-header>")))
-                         ((funcall --element-preceded-by-table-p
-                                   parent-list info)
-                          '("</text:list-header>" . "<text:list-header>"))
-                         (t '("</text:list-item>" . "<text:list-item>"))))))
-               ;; Handle low-level headlines.
-               (loop for el in llh-genealogy
-                     with step = 'item collect
-                     (case step
-                       (plain-list
-                        (setq step 'item) ; Flip-flop
-                        (setq parent-list el)
-                        (cons "</text:list>"
-                              (format "\n<text:list text:style-name=\"%s\" %s>"
-                                      (if (org-export-numbered-headline-p
-                                           el info)
-                                          "OrgNumberedList"
-                                        "OrgBulletedList")
-                                      "text:continue-numbering=\"true\"")))
-                       (item
-                        (setq step 'plain-list) ; Flip-flop
-                        (cond
-                         ((not parent-list)
-                          (if (funcall --element-preceded-by-table-p table 
info)
-                              '("</text:list-header>" . "<text:list-header>")
-                            '("</text:list-item>" . "<text:list-header>")))
-                         ((let ((section? (org-export-get-previous-element
-                                           parent-list info)))
-                            (and section?
-                                 (eq (org-element-type section?) 'section)
-                                 (assq 'table (org-element-contents 
section?))))
-                          '("</text:list-header>" . "<text:list-header>"))
-                         (t
-                          '("</text:list-item>" . "<text:list-item>")))))))))))
+         (lambda (table info)
+           (let* ((genealogy (org-element-lineage table))
+                  (list-genealogy
+                   (when (eq (org-element-type (car genealogy)) 'item)
+                     (cl-loop for el in genealogy
+                              when (memq (org-element-type el)
+                                         '(item plain-list))
+                              collect el)))
+                  (llh-genealogy
+                   (apply #'nconc
+                          (cl-loop
+                           for el in genealogy
+                           when (and (eq (org-element-type el) 'headline)
+                                     (org-export-low-level-p el info))
+                           collect
+                           (list el
+                                 (assq 'headline
+                                       (org-element-contents
+                                        (org-export-get-parent el)))))))
+                  parent-list)
+             (nconc
+              ;; Handle list genealogy.
+              (cl-loop
+               for el in list-genealogy collect
+               (cl-case (org-element-type el)
+                 (plain-list
+                  (setq parent-list el)
+                  (cons "</text:list>"
+                        (format "\n<text:list text:style-name=\"%s\" %s>"
+                                (cl-case (org-element-property :type el)
+                                  (ordered "OrgNumberedList")
+                                  (unordered "OrgBulletedList")
+                                  (descriptive-1 "OrgDescriptionList")
+                                  (descriptive-2 "OrgDescriptionList"))
+                                "text:continue-numbering=\"true\"")))
+                 (item
+                  (cond
+                   ((not parent-list)
+                    (if (funcall --element-preceded-by-table-p table info)
+                        '("</text:list-header>" . "<text:list-header>")
+                      '("</text:list-item>" . "<text:list-header>")))
+                   ((funcall --element-preceded-by-table-p
+                             parent-list info)
+                    '("</text:list-header>" . "<text:list-header>"))
+                   (t '("</text:list-item>" . "<text:list-item>"))))))
+              ;; Handle low-level headlines.
+              (cl-loop for el in llh-genealogy
+                       with step = 'item collect
+                       (cl-case step
+                         (plain-list
+                          (setq step 'item) ; Flip-flop
+                          (setq parent-list el)
+                          (cons "</text:list>"
+                                (format "\n<text:list text:style-name=\"%s\" 
%s>"
+                                        (if (org-export-numbered-headline-p
+                                             el info)
+                                            "OrgNumberedList"
+                                          "OrgBulletedList")
+                                        "text:continue-numbering=\"true\"")))
+                         (item
+                          (setq step 'plain-list) ; Flip-flop
+                          (cond
+                           ((not parent-list)
+                            (if (funcall --element-preceded-by-table-p table 
info)
+                                '("</text:list-header>" . "<text:list-header>")
+                              '("</text:list-item>" . "<text:list-header>")))
+                           ((let ((section? (org-export-get-previous-element
+                                             parent-list info)))
+                              (and section?
+                                   (eq (org-element-type section?) 'section)
+                                   (assq 'table (org-element-contents 
section?))))
+                            '("</text:list-header>" . "<text:list-header>"))
+                           (t
+                            '("</text:list-item>" . 
"<text:list-item>"))))))))))
         (close-open-tags (funcall --walk-list-genealogy-and-collect-tags
                                   table info)))
     ;; OpenDocument schema does not permit table to occur within a
@@ -3613,7 +3566,7 @@ pertaining to indentation here."
     ;;
     ;; - Description lists are simulated as plain lists.
     ;; - Low-level headlines can be listified.
-    ;; - In Org-mode, a table can occur not only as a regular list
+    ;; - In Org mode, a table can occur not only as a regular list
     ;;   item, but also within description lists and low-level
     ;;   headlines.
 
@@ -3635,26 +3588,24 @@ pertaining to indentation here."
 
 ;;;; Target
 
-(defun org-odt-target (target contents info)
+(defun org-odt-target (target _contents info)
   "Transcode a TARGET object from Org to ODT.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (let ((value (org-element-property :value target)))
-    (org-odt--target "" (org-export-solidify-link-text value))))
+  (org-odt--target "" (org-export-get-reference target info)))
 
 
 ;;;; Timestamp
 
-(defun org-odt-timestamp (timestamp contents info)
+(defun org-odt-timestamp (timestamp _contents info)
   "Transcode a TIMESTAMP object from Org to ODT.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (let* ((raw-value (org-element-property :raw-value timestamp))
-        (type (org-element-property :type timestamp)))
-    (if (not org-odt-use-date-fields)
+  (let ((type (org-element-property :type timestamp)))
+    (if (not (plist-get info :odt-use-date-fields))
        (let ((value (org-odt-plain-text
                      (org-timestamp-translate timestamp) info)))
-         (case (org-element-property :type timestamp)
+         (cl-case (org-element-property :type timestamp)
            ((active active-range)
             (format "<text:span text:style-name=\"%s\">%s</text:span>"
                     "OrgActiveTimestamp" value))
@@ -3662,7 +3613,7 @@ channel."
             (format "<text:span text:style-name=\"%s\">%s</text:span>"
                     "OrgInactiveTimestamp" value))
            (otherwise value)))
-      (case type
+      (cl-case type
        (active
         (format "<text:span text:style-name=\"%s\">%s</text:span>"
                 "OrgActiveTimestamp"
@@ -3687,12 +3638,12 @@ channel."
         (format "<text:span text:style-name=\"%s\">%s</text:span>"
                 "OrgDiaryTimestamp"
                 (org-odt-plain-text (org-timestamp-translate timestamp)
-                                      info)))))))
+                                    info)))))))
 
 
 ;;;; Underline
 
-(defun org-odt-underline (underline contents info)
+(defun org-odt-underline (_underline contents _info)
   "Transcode UNDERLINE from Org to ODT.
 CONTENTS is the text with underline markup.  INFO is a plist
 holding contextual information."
@@ -3702,7 +3653,7 @@ holding contextual information."
 
 ;;;; Verbatim
 
-(defun org-odt-verbatim (verbatim contents info)
+(defun org-odt-verbatim (verbatim _contents _info)
   "Transcode a VERBATIM object from Org to ODT.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
@@ -3713,19 +3664,17 @@ channel."
 
 ;;;; Verse Block
 
-(defun org-odt-verse-block (verse-block contents info)
+(defun org-odt-verse-block (_verse-block contents _info)
   "Transcode a VERSE-BLOCK element from Org to ODT.
 CONTENTS is verse block contents.  INFO is a plist holding
 contextual information."
-  ;; Add line breaks to each line of verse.
-  (setq contents (replace-regexp-in-string
-                 "\\(<text:line-break/>\\)?[ \t]*\n"
-                 "<text:line-break/>" contents))
-  ;; Replace tabs and spaces.
-  (setq contents (org-odt--encode-tabs-and-spaces contents))
-  ;; Surround it in a verse environment.
-  (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
-         "OrgVerse" contents))
+  (format "\n<text:p text:style-name=\"OrgVerse\">%s</text:p>"
+         (replace-regexp-in-string
+          ;; Replace leading tabs and spaces.
+          "^[ \t]+" #'org-odt--encode-tabs-and-spaces
+          ;; Add line breaks to each line of verse.
+          (replace-regexp-in-string
+           "\\(<text:line-break/>\\)?[ \t]*$" "<text:line-break/>" contents))))
 
 
 
@@ -3733,13 +3682,13 @@ contextual information."
 
 ;;;; LaTeX fragments
 
-(defun org-odt--translate-latex-fragments (tree backend info)
+(defun org-odt--translate-latex-fragments (tree _backend info)
   (let ((processing-type (plist-get info :with-latex))
        (count 0))
     ;; Normalize processing-type to one of dvipng, mathml or verbatim.
     ;; If the desired converter is not available, force verbatim
     ;; processing.
-    (case processing-type
+    (cl-case processing-type
       ((t mathml)
        (if (and (fboundp 'org-format-latex-mathml-available-p)
                (org-format-latex-mathml-available-p))
@@ -3765,70 +3714,70 @@ contextual information."
     (when (memq processing-type '(mathml dvipng imagemagick))
       (org-element-map tree '(latex-fragment latex-environment)
        (lambda (latex-*)
-         (incf count)
+         (cl-incf count)
          (let* ((latex-frag (org-element-property :value latex-*))
                 (input-file (plist-get info :input-file))
                 (cache-dir (file-name-directory input-file))
                 (cache-subdir (concat
-                               (case processing-type
+                               (cl-case processing-type
                                  ((dvipng imagemagick) "ltxpng/")
                                  (mathml "ltxmathml/"))
                                (file-name-sans-extension
                                 (file-name-nondirectory input-file))))
                 (display-msg
-                 (case processing-type
-                   ((dvipng imagemagick) (format "Creating LaTeX Image %d..." 
count))
+                 (cl-case processing-type
+                   ((dvipng imagemagick)
+                    (format "Creating LaTeX Image %d..." count))
                    (mathml (format "Creating MathML snippet %d..." count))))
                 ;; Get an Org-style link to PNG image or the MathML
                 ;; file.
                 (org-link
                  (let ((link (with-temp-buffer
                                (insert latex-frag)
-                               (org-format-latex cache-subdir cache-dir
-                                                 nil display-msg
-                                                 nil nil processing-type)
+                               (org-format-latex cache-subdir nil nil cache-dir
+                                                 nil display-msg nil
+                                                 processing-type)
                                (buffer-substring-no-properties
                                 (point-min) (point-max)))))
-                   (if (not (string-match "file:\\([^]]*\\)" link))
-                       (prog1 nil (message "LaTeX Conversion failed."))
-                     link))))
+                   (if (string-match-p "file:\\([^]]*\\)" link) link
+                     (message "LaTeX Conversion failed.")
+                     nil))))
            (when org-link
-             ;; Conversion succeeded.  Parse above Org-style link to a
-             ;; `link' object.
-             (let* ((link (car (org-element-map (with-temp-buffer
-                                                  (org-mode)
-                                                  (insert org-link)
-                                                  (org-element-parse-buffer))
-                                   'link 'identity))))
-               ;; Orphan the link.
-               (org-element-put-property link :parent nil)
-               (let* (
-                      (replacement
-                       (case (org-element-type latex-*)
-                         ;; Case 1: LaTeX environment.
-                         ;; Mimic a "standalone image or formula" by
-                         ;; enclosing the `link' in a `paragraph'.
-                         ;; Copy over original attributes, captions to
-                         ;; the enclosing paragraph.
-                         (latex-environment
-                          (org-element-adopt-elements
-                           (list 'paragraph
-                                 (list :style "OrgFormula"
-                                       :name (org-element-property :name
-                                                                   latex-*)
-                                       :caption (org-element-property :caption
-                                                                      
latex-*)))
-                           link))
-                         ;; Case 2: LaTeX fragment.
-                         ;; No special action.
-                         (latex-fragment link))))
-                 ;; Note down the object that link replaces.
-                 (org-element-put-property replacement :replaces
-                                           (list (org-element-type latex-*)
-                                                 (list :value latex-frag)))
-                 ;; Replace now.
-                 (org-element-set-element latex-* replacement))))))
-       info)))
+             ;; Conversion succeeded.  Parse above Org-style link to
+             ;; a `link' object.
+             (let* ((link
+                     (org-element-map
+                         (org-element-parse-secondary-string org-link '(link))
+                         'link #'identity info t))
+                    (replacement
+                     (cl-case (org-element-type latex-*)
+                       ;; Case 1: LaTeX environment.  Mimic
+                       ;; a "standalone image or formula" by
+                       ;; enclosing the `link' in a `paragraph'.
+                       ;; Copy over original attributes, captions to
+                       ;; the enclosing paragraph.
+                       (latex-environment
+                        (org-element-adopt-elements
+                         (list 'paragraph
+                               (list :style "OrgFormula"
+                                     :name
+                                     (org-element-property :name latex-*)
+                                     :caption
+                                     (org-element-property :caption latex-*)))
+                         link))
+                       ;; Case 2: LaTeX fragment.  No special action.
+                       (latex-fragment link))))
+               ;; Note down the object that link replaces.
+               (org-element-put-property replacement :replaces
+                                         (list (org-element-type latex-*)
+                                               (list :value latex-frag)))
+               ;; Restore blank after initial element or object.
+               (org-element-put-property
+                replacement :post-blank
+                (org-element-property :post-blank latex-*))
+               ;; Replace now.
+               (org-element-set-element latex-* replacement)))))
+       info nil nil t)))
   tree)
 
 
@@ -3837,7 +3786,7 @@ contextual information."
 ;; This translator is necessary to handle indented tables in a uniform
 ;; manner.  See comment in `org-odt--table'.
 
-(defun org-odt--translate-description-lists (tree backend info)
+(defun org-odt--translate-description-lists (tree _backend info)
   ;; OpenDocument has no notion of a description list.  So simulate it
   ;; using plain lists.  Description lists in the exported document
   ;; are typeset in the same manner as they are in a typical HTML
@@ -3870,7 +3819,7 @@ contextual information."
   ;;
   (org-element-map tree 'plain-list
     (lambda (el)
-      (when (equal (org-element-property :type el) 'descriptive)
+      (when (eq (org-element-property :type el) 'descriptive)
        (org-element-set-element
         el
         (apply 'org-element-adopt-elements
@@ -3933,7 +3882,7 @@ contextual information."
 
 ;; Translate lists to tables
 
-(defun org-odt--translate-list-tables (tree backend info)
+(defun org-odt--translate-list-tables (tree _backend info)
   (org-element-map tree 'plain-list
     (lambda (l1-list)
       (when (org-export-read-attribute :attr_odt l1-list :list-table)
@@ -3994,42 +3943,38 @@ contextual information."
       (insert
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
      <manifest:manifest 
xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" 
manifest:version=\"1.2\">\n")
-      (mapc
-       (lambda (file-entry)
-        (let* ((version (nth 2 file-entry))
-               (extra (if (not version) ""
-                        (format " manifest:version=\"%s\"" version))))
-          (insert
-           (format org-odt-manifest-file-entry-tag
-                   (nth 0 file-entry) (nth 1 file-entry) extra))))
-       org-odt-manifest-file-entries)
+      (dolist (file-entry org-odt-manifest-file-entries)
+       (let* ((version (nth 2 file-entry))
+              (extra (if (not version) ""
+                       (format " manifest:version=\"%s\"" version))))
+         (insert
+          (format org-odt-manifest-file-entry-tag
+                  (nth 0 file-entry) (nth 1 file-entry) extra))))
       (insert "\n</manifest:manifest>"))))
 
 (defmacro org-odt--export-wrap (out-file &rest body)
   `(let* ((--out-file ,out-file)
          (out-file-type (file-name-extension --out-file))
          (org-odt-xml-files '("META-INF/manifest.xml" "content.xml"
-                                "meta.xml" "styles.xml"))
+                              "meta.xml" "styles.xml"))
          ;; Initialize temporary workarea.  All files that end up in
          ;; the exported document get parked/created here.
          (org-odt-zip-dir (file-name-as-directory
-                             (make-temp-file (format "%s-" out-file-type) t)))
+                           (make-temp-file (format "%s-" out-file-type) t)))
          (org-odt-manifest-file-entries nil)
          (--cleanup-xml-buffers
-          (function
-           (lambda nil
-             ;; Kill all XML buffers.
-             (mapc (lambda (file)
-                     (let ((buf (find-buffer-visiting
-                                 (concat org-odt-zip-dir file))))
-                       (when buf
-                         (with-current-buffer buf
-                           (set-buffer-modified-p nil)
-                           (kill-buffer buf)))))
-                   org-odt-xml-files)
-             ;; Delete temporary directory and also other embedded
-             ;; files that get copied there.
-             (delete-directory org-odt-zip-dir t)))))
+          (lambda ()
+            ;; Kill all XML buffers.
+            (dolist (file org-odt-xml-files)
+              (let ((buf (find-buffer-visiting
+                          (concat org-odt-zip-dir file))))
+                (when buf
+                  (with-current-buffer buf
+                    (set-buffer-modified-p nil)
+                    (kill-buffer buf)))))
+            ;; Delete temporary directory and also other embedded
+            ;; files that get copied there.
+            (delete-directory org-odt-zip-dir t))))
      (condition-case err
         (progn
           (unless (executable-find "zip")
@@ -4052,16 +3997,15 @@ contextual information."
           ;; Write out the manifest entries before zipping
           (org-odt-write-manifest-file)
           ;; Save all XML files.
-          (mapc (lambda (file)
-                  (let ((buf (find-buffer-visiting
-                              (concat org-odt-zip-dir file))))
-                    (when buf
-                      (with-current-buffer buf
-                        ;; Prettify output if needed.
-                        (when org-odt-prettify-xml
-                          (indent-region (point-min) (point-max)))
-                        (save-buffer 0)))))
-                org-odt-xml-files)
+          (dolist (file org-odt-xml-files)
+            (let ((buf (find-buffer-visiting
+                        (concat org-odt-zip-dir file))))
+              (when buf
+                (with-current-buffer buf
+                  ;; Prettify output if needed.
+                  (when org-odt-prettify-xml
+                    (indent-region (point-min) (point-max)))
+                  (save-buffer 0)))))
           ;; Run zip.
           (let* ((target --out-file)
                  (target-name (file-name-nondirectory target))
@@ -4079,19 +4023,17 @@ contextual information."
               ;; directory.
               (with-current-buffer
                   (find-file-noselect (concat org-odt-zip-dir "content.xml") t)
-                (mapc
-                 (lambda (cmd)
-                   (message "Running %s" (mapconcat 'identity cmd " "))
-                   (setq err-string
-                         (with-output-to-string
-                           (setq exitcode
-                                 (apply 'call-process (car cmd)
-                                        nil standard-output nil (cdr cmd)))))
-                   (or (zerop exitcode)
-                       (error (concat "Unable to create OpenDocument file."
-                                      "  Zip failed with error (%s)")
-                              err-string)))
-                 cmds)))
+                (dolist (cmd cmds)
+                  (message "Running %s" (mapconcat 'identity cmd " "))
+                  (setq err-string
+                        (with-output-to-string
+                          (setq exitcode
+                                (apply 'call-process (car cmd)
+                                       nil standard-output nil (cdr cmd)))))
+                  (or (zerop exitcode)
+                      (error (concat "Unable to create OpenDocument file."
+                                     "  Zip failed with error (%s)")
+                             err-string)))))
             ;; Move the zip file from temporary work directory to
             ;; user-mandated location.
             (rename-file (concat org-odt-zip-dir target-name) target)
@@ -4135,9 +4077,9 @@ MathML source to kill ring depending on the value of
        (setq frag (and (setq frag (and (region-active-p)
                                        (buffer-substring (region-beginning)
                                                          (region-end))))
-                       (loop for e in org-latex-regexps
-                             thereis (when (string-match (nth 1 e) frag)
-                                       (match-string (nth 2 e) frag)))))
+                       (cl-loop for e in org-latex-regexps
+                                thereis (when (string-match (nth 1 e) frag)
+                                          (match-string (nth 2 e) frag)))))
        (read-string "LaTeX Fragment: " frag nil frag))
      ,(let ((odf-filename (expand-file-name
                           (concat
@@ -4265,12 +4207,12 @@ Return output file's name."
          (when out-fmt-spec
            (throw 'done (cons (car e) out-fmt-spec))))))))
 
-(defun org-odt-do-convert (in-file out-fmt &optional prefix-arg)
+(defun org-odt-do-convert (in-file out-fmt &optional open)
   "Workhorse routine for `org-odt-convert'."
   (require 'browse-url)
-  (let* ((in-file (expand-file-name (or in-file buffer-file-name)))
-        (dummy (or (file-readable-p in-file)
-                   (error "Cannot read %s" in-file)))
+  (let* ((in-file (let ((f (expand-file-name (or in-file buffer-file-name))))
+                   (if (file-readable-p f) f
+                     (error "Cannot read %s" in-file))))
         (in-fmt (file-name-extension in-file))
         (out-fmt (or out-fmt (error "Output format unspecified")))
         (how (or (org-odt-reachable-p in-fmt out-fmt)
@@ -4300,7 +4242,7 @@ Return output file's name."
     (cond
      ((file-exists-p out-file)
       (message "Exported to %s" out-file)
-      (when prefix-arg
+      (when open
        (message "Opening %s..."  out-file)
        (org-open-file out-file 'system))
       out-file)
@@ -4333,12 +4275,10 @@ form (CONVERTER-PROCESS . OUTPUT-FMT-ALIST).  See
 (defun org-odt-reachable-formats (in-fmt)
   "Return list of formats to which IN-FMT can be converted.
 The list of the form (OUTPUT-FMT-1 OUTPUT-FMT-2 ...)."
-  (let (l)
-    (mapc (lambda (e) (add-to-list 'l e))
-         (apply 'append (mapcar
-                         (lambda (e) (mapcar 'car (cdr e)))
-                         (org-odt-do-reachable-formats in-fmt))))
-    l))
+  (copy-sequence
+   (apply #'append (mapcar
+                   (lambda (e) (mapcar #'car (cdr e)))
+                   (org-odt-do-reachable-formats in-fmt)))))
 
 (defun org-odt-convert-read-params ()
   "Return IN-FILE and OUT-FMT params for `org-odt-do-convert'.
@@ -4358,25 +4298,23 @@ This is a helper routine for interactive use."
     (list in-file out-fmt)))
 
 ;;;###autoload
-(defun org-odt-convert (&optional in-file out-fmt prefix-arg)
+(defun org-odt-convert (&optional in-file out-fmt open)
   "Convert IN-FILE to format OUT-FMT using a command line converter.
 IN-FILE is the file to be converted.  If unspecified, it defaults
 to variable `buffer-file-name'.  OUT-FMT is the desired output
-format.  Use `org-odt-convert-process' as the converter.
-If PREFIX-ARG is non-nil then the newly converted file is opened
-using `org-open-file'."
+format.  Use `org-odt-convert-process' as the converter.  If OPEN
+is non-nil then the newly converted file is opened using
+`org-open-file'."
   (interactive
    (append (org-odt-convert-read-params) current-prefix-arg))
-  (org-odt-do-convert in-file out-fmt prefix-arg))
+  (org-odt-do-convert in-file out-fmt open))
 
 ;;; Library Initializations
 
-(mapc
- (lambda (desc)
-   ;; Let Emacs open all OpenDocument files in archive mode
-   (add-to-list 'auto-mode-alist
-               (cons (concat  "\\." (car desc) "\\'") 'archive-mode)))
- org-odt-file-extensions)
+(dolist (desc org-odt-file-extensions)
+  ;; Let Emacs open all OpenDocument files in archive mode.
+  (add-to-list 'auto-mode-alist
+              (cons (concat  "\\." (car desc) "\\'") 'archive-mode)))
 
 (provide 'ox-odt)
 
diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el
index 312221d..a52ecc8 100644
--- a/lisp/org/ox-org.el
+++ b/lisp/org/ox-org.el
@@ -1,4 +1,4 @@
-;;; ox-org.el --- Org Back-End for Org Export Engine
+;;; ox-org.el --- Org Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
 
@@ -26,6 +26,7 @@
 
 (require 'ox)
 (declare-function htmlize-buffer "ext:htmlize" (&optional buffer))
+(defvar htmlize-output-type)
 
 (defgroup org-export-org nil
   "Options for exporting Org mode files to Org."
@@ -34,8 +35,6 @@
   :version "24.4"
   :package-version '(Org . "8.0"))
 
-(define-obsolete-variable-alias
-  'org-export-htmlized-org-css-url 'org-org-htmlized-css-url "24.4")
 (defcustom org-org-htmlized-css-url nil
   "URL pointing to the CSS defining colors for htmlized Emacs buffers.
 Normally when creating an htmlized version of an Org buffer,
@@ -45,7 +44,7 @@ look bad if different people with different fontification 
setup
 work on the same website.  When this variable is non-nil,
 creating an htmlized version of an Org buffer using
 `org-org-export-as-org' will include a link to this URL if the
-setting of `org-html-htmlize-output-type' is 'css."
+setting of `org-html-htmlize-output-type' is `css'."
   :group 'org-export-org
   :type '(choice
          (const :tag "Don't include external stylesheet link" nil)
@@ -57,13 +56,12 @@ setting of `org-html-htmlize-output-type' is 'css."
     (center-block . org-org-identity)
     (clock . org-org-identity)
     (code . org-org-identity)
-    (comment . (lambda (&rest args) ""))
-    (comment-block . (lambda (&rest args) ""))
     (diary-sexp . org-org-identity)
     (drawer . org-org-identity)
     (dynamic-block . org-org-identity)
     (entity . org-org-identity)
     (example-block . org-org-identity)
+    (export-block . org-org-export-block)
     (fixed-width . org-org-identity)
     (footnote-definition . ignore)
     (footnote-reference . org-org-identity)
@@ -78,14 +76,14 @@ setting of `org-html-htmlize-output-type' is 'css."
     (latex-environment . org-org-identity)
     (latex-fragment . org-org-identity)
     (line-break . org-org-identity)
-    (link . org-org-identity)
+    (link . org-org-link)
     (node-property . org-org-identity)
+    (template . org-org-template)
     (paragraph . org-org-identity)
     (plain-list . org-org-identity)
     (planning . org-org-identity)
     (property-drawer . org-org-identity)
     (quote-block . org-org-identity)
-    (quote-section . org-org-identity)
     (radio-target . org-org-identity)
     (section . org-org-section)
     (special-block . org-org-identity)
@@ -109,9 +107,35 @@ setting of `org-html-htmlize-output-type' is 'css."
        (?v "As Org file and open"
            (lambda (a s v b)
              (if a (org-org-export-to-org t s v b)
-               (org-open-file (org-org-export-to-org nil s v b))))))))
-
-(defun org-org-identity (blob contents info)
+               (org-open-file (org-org-export-to-org nil s v b)))))))
+  :filters-alist '((:filter-parse-tree . org-org--add-missing-sections)))
+
+(defun org-org--add-missing-sections (tree _backend _info)
+  "Ensure each headline has an associated section.
+
+TREE is the parse tree being exported.
+
+Footnotes relative to the headline are inserted in the section,
+using `org-org-section'.  However, this function is not called if
+the headline doesn't contain any section in the first place, so
+we make sure it is always called."
+  (org-element-map tree 'headline
+    (lambda (h)
+      (let ((first-child (car (org-element-contents h)))
+           (new-section (org-element-create 'section)))
+       (pcase (org-element-type first-child)
+         (`section nil)
+         (`nil (org-element-adopt-elements h new-section))
+         (_ (org-element-insert-before new-section first-child))))))
+  tree)
+
+(defun org-org-export-block (export-block _contents _info)
+  "Transcode a EXPORT-BLOCK element from Org to LaTeX.
+CONTENTS and INFO are ignored."
+  (and (equal (org-element-property :type export-block) "ORG")
+       (org-element-property :value export-block)))
+
+(defun org-org-identity (blob contents _info)
   "Transcode BLOB element or object back into Org syntax.
 CONTENTS is its contents, as a string or nil.  INFO is ignored."
   (let ((case-fold-search t))
@@ -133,17 +157,54 @@ CONTENTS is its contents, as a string or nil.  INFO is 
ignored."
                              (org-export-get-relative-level headline info))
     (org-element-headline-interpreter headline contents)))
 
-(defun org-org-keyword (keyword contents info)
+(defun org-org-keyword (keyword _contents _info)
   "Transcode KEYWORD element back into Org syntax.
-CONTENTS is nil.  INFO is ignored.  This function ignores
-keywords targeted at other export back-ends."
-  (unless (member (org-element-property :key keyword)
-                 (mapcar
-                  (lambda (block-cons)
-                    (and (eq (cdr block-cons) 'org-element-export-block-parser)
-                         (car block-cons)))
-                  org-element-block-name-alist))
-    (org-element-keyword-interpreter keyword nil)))
+CONTENTS is nil.  INFO is ignored."
+  (let ((key (org-element-property :key keyword)))
+    (unless (member key
+                   '("AUTHOR" "CREATOR" "DATE" "EMAIL" "OPTIONS" "TITLE"))
+      (org-element-keyword-interpreter keyword nil))))
+
+(defun org-org-link (link contents _info)
+  "Transcode LINK object back into Org syntax.
+CONTENTS is the description of the link, as a string, or nil.
+INFO is a plist containing current export state."
+  (or (org-export-custom-protocol-maybe link contents 'org)
+      (org-element-link-interpreter link contents)))
+
+(defun org-org-template (contents info)
+  "Return Org document template with document keywords.
+CONTENTS is the transcoded contents string.  INFO is a plist used
+as a communication channel."
+  (concat
+   (and (plist-get info :time-stamp-file)
+       (format-time-string "# Created %Y-%m-%d %a %H:%M\n"))
+   (org-element-normalize-string
+    (mapconcat #'identity
+              (org-element-map (plist-get info :parse-tree) 'keyword
+                (lambda (k)
+                  (and (string-equal (org-element-property :key k) "OPTIONS")
+                       (concat "#+OPTIONS: "
+                               (org-element-property :value k)))))
+              "\n"))
+   (and (plist-get info :with-title)
+       (format "#+TITLE: %s\n" (org-export-data (plist-get info :title) info)))
+   (and (plist-get info :with-date)
+       (let ((date (org-export-data (org-export-get-date info) info)))
+         (and (org-string-nw-p date)
+              (format "#+DATE: %s\n" date))))
+   (and (plist-get info :with-author)
+       (let ((author (org-export-data (plist-get info :author) info)))
+         (and (org-string-nw-p author)
+              (format "#+AUTHOR: %s\n" author))))
+   (and (plist-get info :with-email)
+       (let ((email (org-export-data (plist-get info :email) info)))
+         (and (org-string-nw-p email)
+              (format "#+EMAIL: %s\n" email))))
+   (and (plist-get info :with-creator)
+       (org-string-nw-p (plist-get info :creator))
+       (format "#+CREATOR: %s\n" (plist-get info :creator)))
+   contents))
 
 (defun org-org-section (section contents info)
   "Transcode SECTION element back into Org syntax.
@@ -152,28 +213,28 @@ a communication channel."
   (concat
    (org-element-normalize-string contents)
    ;; Insert footnote definitions appearing for the first time in this
-   ;; section.  Indeed, some of them may not be available to narrowing
-   ;; so we make sure all of them are included in the result.
-   (let ((footnotes-alist
-         (org-element-map section 'footnote-reference
+   ;; section, or in the relative headline title.  Indeed, some of
+   ;; them may not be available to narrowing so we make sure all of
+   ;; them are included in the result.
+   (let ((footnotes
+         (org-element-map
+             (list (org-export-get-parent-headline section) section)
+             'footnote-reference
            (lambda (fn)
              (and (eq (org-element-property :type fn) 'standard)
                   (org-export-footnote-first-reference-p fn info)
-                  (cons (org-element-property :label fn)
-                        (org-export-get-footnote-definition fn info))))
-           info)))
-     (and footnotes-alist
-         (concat "\n"
-                 (mapconcat
-                  (lambda (d)
-                    (org-element-normalize-string
-                     (concat (format "[%s] "(car d))
-                             (org-export-data (cdr d) info))))
-                  footnotes-alist "\n"))))
-   (make-string (or (org-element-property :post-blank section) 0) ?\n)))
+                  (org-element-normalize-string
+                   (format "[fn:%s] %s"
+                           (org-element-property :label fn)
+                           (org-export-data
+                            (org-export-get-footnote-definition fn info)
+                            info)))))
+           info nil 'headline t)))
+     (and footnotes (concat "\n" (mapconcat #'identity footnotes "\n"))))))
 
 ;;;###autoload
-(defun org-org-export-as-org (&optional async subtreep visible-only ext-plist)
+(defun org-org-export-as-org
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to an Org buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -192,6 +253,9 @@ first.
 When optional argument VISIBLE-ONLY is non-nil, don't export
 contents of hidden elements.
 
+When optional argument BODY-ONLY is non-nil, strip document
+keywords from output.
+
 EXT-PLIST, when provided, is a property list with external
 parameters overriding Org default settings, but still inferior to
 file-local settings.
@@ -201,10 +265,11 @@ be displayed when 
`org-export-show-temporary-export-buffer' is
 non-nil."
   (interactive)
   (org-export-to-buffer 'org "*Org ORG Export*"
-    async subtreep visible-only nil ext-plist (lambda () (org-mode))))
+    async subtreep visible-only body-only ext-plist (lambda () (org-mode))))
 
 ;;;###autoload
-(defun org-org-export-to-org (&optional async subtreep visible-only ext-plist)
+(defun org-org-export-to-org
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to an org file.
 
 If narrowing is active in the current buffer, only export its
@@ -223,6 +288,9 @@ first.
 When optional argument VISIBLE-ONLY is non-nil, don't export
 contents of hidden elements.
 
+When optional argument BODY-ONLY is non-nil, strip document
+keywords from output.
+
 EXT-PLIST, when provided, is a property list with external
 parameters overriding Org default settings, but still inferior to
 file-local settings.
@@ -231,7 +299,7 @@ Return output file name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".org" subtreep)))
     (org-export-to-file 'org outfile
-      async subtreep visible-only nil ext-plist)))
+      async subtreep visible-only body-only ext-plist)))
 
 ;;;###autoload
 (defun org-org-publish-to-org (plist filename pub-dir)
@@ -255,7 +323,7 @@ Return output file name."
           newbuf)
       (with-current-buffer work-buffer
         (org-font-lock-ensure)
-        (show-all)
+        (outline-show-all)
         (org-show-block-all)
         (setq newbuf (htmlize-buffer)))
       (with-current-buffer newbuf
diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el
index 4ebc073..884d6bf 100644
--- a/lisp/org/ox-publish.el
+++ b/lisp/org/ox-publish.el
@@ -1,4 +1,4 @@
-;;; ox-publish.el --- Publish Related Org Mode Files as a Website
+;;; ox-publish.el --- Publish Related Org Mode Files as a Website -*- 
lexical-binding: t; -*-
 ;; Copyright (C) 2006-2017 Free Software Foundation, Inc.
 
 ;; Author: David O'Toole <address@hidden>
@@ -38,7 +38,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'format-spec)
 (require 'ox)
 
@@ -54,16 +54,23 @@
   "This will cache timestamps and titles for files in publishing projects.
 Blocks could hash sha1 values here.")
 
+(defvar org-publish-after-publishing-hook nil
+  "Hook run each time a file is published.
+Every function in this hook will be called with two arguments:
+the name of the original file and the name of the file
+produced.")
+
 (defgroup org-publish nil
-  "Options for publishing a set of Org-mode and related files."
+  "Options for publishing a set of files."
   :tag "Org Publishing"
   :group 'org)
 
 (defcustom org-publish-project-alist nil
   "Association list to control publishing behavior.
-Each element of the alist is a publishing “project”.  The CAR of
+\\<org-mode-map>
+Each element of the alist is a publishing project.  The car of
 each element is a string, uniquely identifying the project.  The
-CDR of each element is in one of the following forms:
+cdr of each element is in one of the following forms:
 
 1. A well-formed property list with an even number of elements,
    alternating keys and values, specifying parameters for the
@@ -80,7 +87,7 @@ When the CDR of an element of org-publish-project-alist is in
 this second form, the elements of the list after `:components'
 are taken to be components of the project, which group together
 files requiring different publishing options.  When you publish
-such a project with \\[org-publish], the components all publish.
+such a project with `\\[org-publish]', the components all publish.
 
 When a property is given a value in `org-publish-project-alist',
 its setting overrides the value of the corresponding user
@@ -97,13 +104,17 @@ Most properties are optional, but some should always be 
set:
 
     Extension (without the dot!) of source files.  This can be
     a regular expression.  If not given, \"org\" will be used as
-    default extension.
+    default extension.  If it is `any', include all the files,
+    even without extension.
 
   `:publishing-directory'
 
     Directory (possibly remote) where output files will be
     published.
 
+If `:recursive' is non-nil files in sub-directories of
+`:base-directory' are considered.
+
 The `:exclude' property may be used to prevent certain files from
 being published.  Its value may be a string or regexp matching
 file names you don't want to be published.
@@ -135,12 +146,16 @@ date.
   `:preparation-function'
 
     Function to be called before publishing this project.  This
-    may also be a list of functions.
+    may also be a list of functions.  Preparation functions are
+    called with the project properties list as their sole
+    argument.
 
   `:completion-function'
 
     Function to be called after publishing this project.  This
-    may also be a list of functions.
+    may also be a list of functions.  Completion functions are
+    called with the project properties list as their sole
+    argument.
 
 Some properties control details of the Org publishing process,
 and are equivalent to the corresponding user variables listed in
@@ -169,7 +184,9 @@ included.  See the back-end documentation for more 
information.
   :with-footnotes           `org-export-with-footnotes'
   :with-inlinetasks         `org-export-with-inlinetasks'
   :with-latex               `org-export-with-latex'
+  :with-planning            `org-export-with-planning'
   :with-priority            `org-export-with-priority'
+  :with-properties          `org-export-with-properties'
   :with-smart-quotes        `org-export-with-smart-quotes'
   :with-special-strings     `org-export-with-special-strings'
   :with-statistics-cookies' `org-export-with-statistics-cookies'
@@ -179,7 +196,7 @@ included.  See the back-end documentation for more 
information.
   :with-tags                `org-export-with-tags'
   :with-tasks               `org-export-with-tasks'
   :with-timestamps          `org-export-with-timestamps'
-  :with-planning            `org-export-with-planning'
+  :with-title               `org-export-with-title'
   :with-todo-keywords       `org-export-with-todo-keywords'
 
 The following properties may be used to control publishing of
@@ -333,7 +350,7 @@ You could use brackets to delimit on what part the link 
will be.
   (concat "X" (if (fboundp 'sha1) (sha1 filename) (md5 filename))))
 
 (defun org-publish-needed-p
-  (filename &optional pub-dir pub-func true-pub-dir base-dir)
+  (filename &optional pub-dir pub-func _true-pub-dir base-dir)
   "Non-nil if FILENAME should be published in PUB-DIR using PUB-FUNC.
 TRUE-PUB-DIR is where the file will truly end up.  Currently we
 are not using this - maybe it can eventually be used to check if
@@ -346,11 +363,11 @@ still decide about that independently."
                filename pub-dir pub-func base-dir))))
     (if rtn (message "Publishing file %s using `%s'" filename pub-func)
       (when org-publish-list-skipped-files
-       (message   "Skipping unmodified file %s" filename)))
+       (message "Skipping unmodified file %s" filename)))
     rtn))
 
 (defun org-publish-update-timestamp
-  (filename &optional pub-dir pub-func base-dir)
+  (filename &optional pub-dir pub-func _base-dir)
   "Update publishing timestamp for file FILENAME.
 If there is no timestamp, create one."
   (let ((key (org-publish-timestamp-filename filename pub-dir pub-func))
@@ -359,10 +376,9 @@ If there is no timestamp, create one."
 
 (defun org-publish-remove-all-timestamps ()
   "Remove all files in the timestamp directory."
-  (let ((dir org-publish-timestamp-directory)
-       files)
+  (let ((dir org-publish-timestamp-directory))
     (when (and (file-exists-p dir) (file-directory-p dir))
-      (mapc 'delete-file (directory-files dir 'full "[^.]\\'"))
+      (mapc #'delete-file (directory-files dir 'full "[^.]\\'"))
       (org-publish-reset-cache))))
 
 
@@ -370,6 +386,15 @@ If there is no timestamp, create one."
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Getting project information out of `org-publish-project-alist'
 
+(defun org-publish-property (property project &optional default)
+  "Return value PROPERTY, as a symbol, in PROJECT.
+DEFAULT is returned when PROPERTY is not actually set in PROJECT
+definition."
+  (let ((properties (cdr project)))
+    (if (plist-member properties property)
+       (plist-get properties property)
+      default)))
+
 (defun org-publish-expand-projects (projects-alist)
   "Expand projects in PROJECTS-ALIST.
 This splices all the components into the list."
@@ -395,12 +420,12 @@ This splices all the components into the list."
     (when (or org-publish-sitemap-sort-files org-publish-sitemap-sort-folders)
       ;; First we sort files:
       (when org-publish-sitemap-sort-files
-       (case org-publish-sitemap-sort-files
-         (alphabetically
+       (pcase org-publish-sitemap-sort-files
+         (`alphabetically
           (let* ((adir (file-directory-p a))
-                 (aorg (and (string-match "\\.org$" a) (not adir)))
+                 (aorg (and (string-suffix-p ".org" a) (not adir)))
                  (bdir (file-directory-p b))
-                 (borg (and (string-match "\\.org$" b) (not bdir)))
+                 (borg (and (string-suffix-p ".org" b) (not bdir)))
                  (A (if aorg (concat (file-name-directory a)
                                      (org-publish-find-title a)) a))
                  (B (if borg (concat (file-name-directory b)
@@ -408,57 +433,56 @@ This splices all the components into the list."
             (setq retval (if org-publish-sitemap-ignore-case
                              (not (string-lessp (upcase B) (upcase A)))
                            (not (string-lessp B A))))))
-         ((anti-chronologically chronologically)
+         ((or `anti-chronologically `chronologically)
           (let* ((adate (org-publish-find-date a))
                  (bdate (org-publish-find-date b))
                  (A (+ (lsh (car adate) 16) (cadr adate)))
                  (B (+ (lsh (car bdate) 16) (cadr bdate))))
             (setq retval
-                  (if (eq org-publish-sitemap-sort-files 'chronologically) (<= 
A B)
+                  (if (eq org-publish-sitemap-sort-files 'chronologically)
+                      (<= A B)
                     (>= A B)))))))
       ;; Directory-wise wins:
       (when org-publish-sitemap-sort-folders
         ;; a is directory, b not:
         (cond
          ((and (file-directory-p a) (not (file-directory-p b)))
-          (setq retval (equal org-publish-sitemap-sort-folders 'first)))
+          (setq retval (eq org-publish-sitemap-sort-folders 'first)))
         ;; a is not a directory, but b is:
          ((and (not (file-directory-p a)) (file-directory-p b))
-          (setq retval (equal org-publish-sitemap-sort-folders 'last))))))
+          (setq retval (eq org-publish-sitemap-sort-folders 'last))))))
     retval))
 
 (defun org-publish-get-base-files-1
-  (base-dir &optional recurse match skip-file skip-dir)
+    (base-dir &optional recurse match skip-file skip-dir)
   "Set `org-publish-temp-files' with files from BASE-DIR directory.
 If RECURSE is non-nil, check BASE-DIR recursively.  If MATCH is
 non-nil, restrict this list to the files matching the regexp
 MATCH.  If SKIP-FILE is non-nil, skip file matching the regexp
 SKIP-FILE.  If SKIP-DIR is non-nil, don't check directories
 matching the regexp SKIP-DIR when recursing through BASE-DIR."
-  (mapc (lambda (f)
-         (let ((fd-p (file-directory-p f))
-               (fnd (file-name-nondirectory f)))
-           (if (and fd-p recurse
-                    (not (string-match "^\\.+$" fnd))
-                    (if skip-dir (not (string-match skip-dir fnd)) t))
-               (org-publish-get-base-files-1
-                f recurse match skip-file skip-dir)
-             (unless (or fd-p ;; this is a directory
-                         (and skip-file (string-match skip-file fnd))
-                         (not (file-exists-p (file-truename f)))
-                         (not (string-match match fnd)))
-
-               (pushnew f org-publish-temp-files)))))
-       (let ((all-files (if (not recurse) (directory-files base-dir t match)
-                          ;; If RECURSE is non-nil, we want all files
-                          ;; matching MATCH and sub-directories.
-                          (org-remove-if-not
-                           (lambda (file)
-                             (or (file-directory-p file)
-                                 (and match (string-match match file))))
-                           (directory-files base-dir t)))))
-         (if (not org-publish-sitemap-requested) all-files
-           (sort all-files 'org-publish-compare-directory-files)))))
+  (let ((all-files (if (not recurse) (directory-files base-dir t match)
+                    ;; If RECURSE is non-nil, we want all files
+                    ;; matching MATCH and sub-directories.
+                    (cl-remove-if-not
+                     (lambda (file)
+                       (or (file-directory-p file)
+                           (and match (string-match match file))))
+                     (directory-files base-dir t)))))
+    (dolist (f (if (not org-publish-sitemap-requested) all-files
+                (sort all-files #'org-publish-compare-directory-files)))
+      (let ((fd-p (file-directory-p f))
+           (fnd (file-name-nondirectory f)))
+       (if (and fd-p recurse
+                (not (string-match "^\\.+$" fnd))
+                (if skip-dir (not (string-match skip-dir fnd)) t))
+           (org-publish-get-base-files-1
+            f recurse match skip-file skip-dir)
+         (unless (or fd-p              ; This is a directory.
+                     (and skip-file (string-match skip-file fnd))
+                     (not (file-exists-p (file-truename f)))
+                     (not (string-match match fnd)))
+           (cl-pushnew f org-publish-temp-files)))))))
 
 (defun org-publish-get-base-files (project &optional exclude-regexp)
   "Return a list of all files in PROJECT.
@@ -500,51 +524,73 @@ matching filenames."
       (setq org-publish-sitemap-sort-folders nil))
 
     (setq org-publish-temp-files nil)
-    (if org-publish-sitemap-requested
-       (pushnew (expand-file-name (concat base-dir sitemap-filename))
+    (when org-publish-sitemap-requested
+      (cl-pushnew (expand-file-name (concat base-dir sitemap-filename))
                  org-publish-temp-files))
     (org-publish-get-base-files-1 base-dir recurse match
                                  ;; FIXME distinguish exclude regexp
                                  ;; for skip-file and skip-dir?
                                  exclude-regexp exclude-regexp)
-    (mapc (lambda (f)
-           (pushnew
-            (expand-file-name (concat base-dir f))
-            org-publish-temp-files))
-         include-list)
-    org-publish-temp-files))
+    (dolist (f include-list org-publish-temp-files)
+      (cl-pushnew (expand-file-name (concat base-dir f))
+                 org-publish-temp-files))))
 
 (defun org-publish-get-project-from-filename (filename &optional up)
-  "Return the project that FILENAME belongs to."
+  "Return a project that FILENAME belongs to.
+When UP is non-nil, return a meta-project (i.e., with a :components part)
+publishing FILENAME."
   (let* ((filename (expand-file-name filename))
-        project-name)
-
-    (catch 'p-found
-      (dolist (prj org-publish-project-alist)
-       (unless (plist-get (cdr prj) :components)
-         ;; [[info:org:Selecting%20files]] shows how this is supposed to work:
-         (let* ((r (plist-get (cdr prj) :recursive))
-                (b (expand-file-name (file-name-as-directory
-                                      (plist-get (cdr prj) :base-directory))))
-                (x (or (plist-get (cdr prj) :base-extension) "org"))
-                (e (plist-get (cdr prj) :exclude))
-                (i (plist-get (cdr prj) :include))
-                (xm (concat "^" b (if r ".+" "[^/]+") "\\.\\(" x "\\)$")))
-           (when
-               (or (and i
-                        (member filename
-                                (mapcar (lambda (file)
-                                          (expand-file-name file b))
-                                        i)))
-                   (and (not (and e (string-match e filename)))
-                        (string-match xm filename)))
-             (setq project-name (car prj))
-             (throw 'p-found project-name))))))
-    (when up
-      (dolist (prj org-publish-project-alist)
-       (if (member project-name (plist-get (cdr prj) :components))
-           (setq project-name (car prj)))))
-    (assoc project-name org-publish-project-alist)))
+        (project
+         (cl-some
+          (lambda (p)
+            ;; Ignore meta-projects.
+            (unless (org-publish-property :components p)
+              (let ((base (file-truename
+                           (org-publish-property :base-directory p))))
+                (cond
+                 ;; Check if FILENAME is explicitly included in one
+                 ;; project.
+                 ((cl-some (lambda (f) (file-equal-p f filename))
+                           (mapcar (lambda (f) (expand-file-name f base))
+                                   (org-publish-property :include p)))
+                  p)
+                 ;; Exclude file names matching :exclude property.
+                 ((let ((exclude-re (org-publish-property :exclude p)))
+                    (and exclude-re
+                         (string-match-p exclude-re
+                                         (file-relative-name filename base))))
+                  nil)
+                 ;; Check :extension.  Handle special `any'
+                 ;; extension.
+                 ((let ((extension (org-publish-property :base-extension p)))
+                    (not (or (eq extension 'any)
+                             (string= (or extension "org")
+                                      (file-name-extension filename)))))
+                  nil)
+                 ;; Check if FILENAME belong to project's base
+                 ;; directory, or some of its sub-directories
+                 ;; if :recursive in non-nil.
+                 ((org-publish-property :recursive p)
+                  (and (file-in-directory-p filename base) p))
+                 ((file-equal-p base (file-name-directory filename)) p)
+                 (t nil)))))
+          org-publish-project-alist)))
+    (cond
+     ((not project) nil)
+     ((not up) project)
+     ;; When optional argument UP is non-nil, return the top-most
+     ;; meta-project effectively publishing FILENAME.
+     (t
+      (letrec ((find-parent-project
+               (lambda (project)
+                 (or (cl-some
+                      (lambda (p)
+                        (and (member (car project)
+                                     (org-publish-property :components p))
+                             (funcall find-parent-project p)))
+                      org-publish-project-alist)
+                     project))))
+       (funcall find-parent-project project))))))
 
 
 
@@ -567,29 +613,31 @@ Return output file name."
   (unless (or (not pub-dir) (file-exists-p pub-dir)) (make-directory pub-dir 
t))
   ;; Check if a buffer visiting FILENAME is already open.
   (let* ((org-inhibit-startup t)
-        (visitingp (find-buffer-visiting filename))
-        (work-buffer (or visitingp (find-file-noselect filename))))
-    (prog1 (with-current-buffer work-buffer
-            (let ((output-file
-                   (org-export-output-file-name extension nil pub-dir))
-                  (body-p (plist-get plist :body-only)))
-              (org-export-to-file backend output-file
-                nil nil nil body-p
-                ;; Add `org-publish-collect-numbering' and
-                ;; `org-publish-collect-index' to final output
-                ;; filters.  The latter isn't dependent on
-                ;; `:makeindex', since we want to keep it up-to-date
-                ;; in cache anyway.
-                (org-combine-plists
-                 plist
-                 `(:filter-final-output
-                   ,(cons 'org-publish-collect-numbering
-                          (cons 'org-publish-collect-index
-                                (plist-get plist :filter-final-output))))))))
+        (visiting (find-buffer-visiting filename))
+        (work-buffer (or visiting (find-file-noselect filename))))
+    (unwind-protect
+       (with-current-buffer work-buffer
+         (let ((output (org-export-output-file-name extension nil pub-dir)))
+           (org-export-to-file backend output
+             nil nil nil (plist-get plist :body-only)
+             ;; Add `org-publish--store-crossrefs' and
+             ;; `org-publish-collect-index' to final output filters.
+             ;; The latter isn't dependent on `:makeindex', since we
+             ;; want to keep it up-to-date in cache anyway.
+             (org-combine-plists
+              plist
+              `(:crossrefs
+                ,(org-publish-cache-get-file-property
+                  ;; Normalize file names in cache.
+                  (file-truename filename) :crossrefs nil t)
+                :filter-final-output
+                (org-publish--store-crossrefs
+                 org-publish-collect-index
+                 ,@(plist-get plist :filter-final-output)))))))
       ;; Remove opened buffer in the process.
-      (unless visitingp (kill-buffer work-buffer)))))
+      (unless visiting (kill-buffer work-buffer)))))
 
-(defun org-publish-attachment (plist filename pub-dir)
+(defun org-publish-attachment (_plist filename pub-dir)
   "Publish a file with no transformation of any kind.
 
 FILENAME is the filename of the Org file to be published.  PLIST
@@ -599,11 +647,12 @@ publishing directory.
 Return output file name."
   (unless (file-directory-p pub-dir)
     (make-directory pub-dir t))
-  (or (equal (expand-file-name (file-name-directory filename))
-            (file-name-as-directory (expand-file-name pub-dir)))
-      (copy-file filename
-                (expand-file-name (file-name-nondirectory filename) pub-dir)
-                t)))
+  (let ((output (expand-file-name (file-name-nondirectory filename) pub-dir)))
+    (unless (file-equal-p (expand-file-name (file-name-directory filename))
+                         (file-name-as-directory (expand-file-name pub-dir)))
+      (copy-file filename output t))
+    ;; Return file name.
+    output))
 
 
 
@@ -612,108 +661,96 @@ Return output file name."
 
 (defun org-publish-file (filename &optional project no-cache)
   "Publish file FILENAME from PROJECT.
-If NO-CACHE is not nil, do not initialize org-publish-cache and
-write it to disk.  This is needed, since this function is used to
-publish single files, when entire projects are published.
-See `org-publish-projects'."
+If NO-CACHE is not nil, do not initialize `org-publish-cache'.
+This is needed, since this function is used to publish single
+files, when entire projects are published (see
+`org-publish-projects')."
   (let* ((project
          (or project
-             (or (org-publish-get-project-from-filename filename)
-                 (error "File %s not part of any known project"
-                        (abbreviate-file-name filename)))))
+             (org-publish-get-project-from-filename filename)
+             (user-error "File %S is not part of any known project"
+                         (abbreviate-file-name filename))))
         (project-plist (cdr project))
-        (ftname (expand-file-name filename))
         (publishing-function
-         (or (plist-get project-plist :publishing-function)
-             (error "No publishing function chosen")))
+         (pcase (plist-get project-plist :publishing-function)
+           (`nil (user-error "No publishing function chosen"))
+           ((and f (pred listp)) f)
+           (f (list f))))
         (base-dir
          (file-name-as-directory
-          (expand-file-name
-           (or (plist-get project-plist :base-directory)
-               (error "Project %s does not have :base-directory defined"
-                      (car project))))))
-        (pub-dir
+          (or (org-publish-property :base-directory project)
+              (user-error "Project %S does not have :base-directory defined"
+                          (car project)))))
+        (pub-base-dir
          (file-name-as-directory
-          (file-truename
-           (or (eval (plist-get project-plist :publishing-directory))
-               (error "Project %s does not have :publishing-directory defined"
-                      (car project))))))
-        tmp-pub-dir)
+          (or (org-publish-property :publishing-directory project)
+              (user-error
+               "Project %S does not have :publishing-directory defined"
+               (car project)))))
+        (pub-dir
+         (file-name-directory
+          (expand-file-name (file-relative-name filename base-dir)
+                            pub-base-dir))))
 
     (unless no-cache (org-publish-initialize-cache (car project)))
 
-    (setq tmp-pub-dir
-         (file-name-directory
-          (concat pub-dir
-                  (and (string-match (regexp-quote base-dir) ftname)
-                       (substring ftname (match-end 0))))))
-    (if (listp publishing-function)
-       ;; allow chain of publishing functions
-       (mapc (lambda (f)
-               (when (org-publish-needed-p
-                      filename pub-dir f tmp-pub-dir base-dir)
-                 (funcall f project-plist filename tmp-pub-dir)
-                 (org-publish-update-timestamp filename pub-dir f base-dir)))
-             publishing-function)
-      (when (org-publish-needed-p
-            filename pub-dir publishing-function tmp-pub-dir base-dir)
-       (funcall publishing-function project-plist filename tmp-pub-dir)
-       (org-publish-update-timestamp
-        filename pub-dir publishing-function base-dir)))
-    (unless no-cache (org-publish-write-cache-file))))
-
-(defun org-publish--run-functions (functions)
-  (cond
-   ((null functions) nil)
-   ((functionp functions) (funcall functions))
-   ((consp functions) (mapc #'funcall functions))
-   (t (error "Neither a function nor a list: %S" functions))))
+    ;; Allow chain of publishing functions.
+    (dolist (f publishing-function)
+      (when (org-publish-needed-p filename pub-base-dir f pub-dir base-dir)
+       (let ((output (funcall f project-plist filename pub-dir)))
+         (org-publish-update-timestamp filename pub-base-dir f base-dir)
+         (run-hook-with-args 'org-publish-after-publishing-hook
+                             filename
+                             output))))
+    ;; Make sure to write cache to file after successfully publishing
+    ;; a file, so as to minimize impact of a publishing failure.
+    (org-publish-write-cache-file)))
 
 (defun org-publish-projects (projects)
   "Publish all files belonging to the PROJECTS alist.
 If `:auto-sitemap' is set, publish the sitemap too.  If
-`:makeindex' is set, also produce a file theindex.org."
-  (mapc
-   (lambda (project)
-     ;; Each project uses its own cache file:
-     (org-publish-initialize-cache (car project))
-     (let* ((project-plist (cdr project))
-           (exclude-regexp (plist-get project-plist :exclude))
-           (sitemap-p (plist-get project-plist :auto-sitemap))
-           (sitemap-filename (or (plist-get project-plist :sitemap-filename)
-                                 "sitemap.org"))
-           (sitemap-function (or (plist-get project-plist :sitemap-function)
-                                 'org-publish-org-sitemap))
-           (org-publish-sitemap-date-format
-            (or (plist-get project-plist :sitemap-date-format)
-                org-publish-sitemap-date-format))
-           (org-publish-sitemap-file-entry-format
-            (or (plist-get project-plist :sitemap-file-entry-format)
-                org-publish-sitemap-file-entry-format))
-           (preparation-function
-            (plist-get project-plist :preparation-function))
-           (completion-function (plist-get project-plist :completion-function))
-           (files (org-publish-get-base-files project exclude-regexp))
-           (theindex
+`:makeindex' is set, also produce a file \"theindex.org\"."
+  (dolist (project (org-publish-expand-projects projects))
+    (let ((project-plist (cdr project)))
+      (let ((fun (plist-get project-plist :preparation-function)))
+       (cond ((consp fun) (dolist (f fun) (funcall f project-plist)))
+             ((functionp fun) (funcall fun project-plist))))
+      ;; Each project uses its own cache file.
+      (org-publish-initialize-cache (car project))
+      (when  (plist-get project-plist :auto-sitemap)
+       (let ((sitemap-filename
+              (or (plist-get project-plist :sitemap-filename)
+                  "sitemap.org"))
+             (sitemap-function
+              (or (plist-get project-plist :sitemap-function)
+                  #'org-publish-org-sitemap))
+             (org-publish-sitemap-date-format
+              (or (plist-get project-plist :sitemap-date-format)
+                  org-publish-sitemap-date-format))
+             (org-publish-sitemap-file-entry-format
+              (or (plist-get project-plist :sitemap-file-entry-format)
+                  org-publish-sitemap-file-entry-format)))
+         (funcall sitemap-function project sitemap-filename)))
+      ;; Publish all files from PROJECT except "theindex.org".  Its
+      ;; publishing will be deferred until "theindex.inc" is
+      ;; populated.
+      (let ((theindex
             (expand-file-name "theindex.org"
-                              (plist-get project-plist :base-directory))))
-       (org-publish--run-functions preparation-function)
-       (if sitemap-p (funcall sitemap-function project sitemap-filename))
-       ;; Publish all files from PROJECT excepted "theindex.org".  Its
-       ;; publishing will be deferred until "theindex.inc" is
-       ;; populated.
-       (dolist (file files)
-        (unless (equal file theindex)
-          (org-publish-file file project t)))
-       ;; Populate "theindex.inc", if needed, and publish
-       ;; "theindex.org".
-       (when (plist-get project-plist :makeindex)
-        (org-publish-index-generate-theindex
-         project (plist-get project-plist :base-directory))
-        (org-publish-file theindex project t))
-       (org-publish--run-functions completion-function)
-       (org-publish-write-cache-file)))
-   (org-publish-expand-projects projects)))
+                              (plist-get project-plist :base-directory)))
+           (exclude-regexp (plist-get project-plist :exclude)))
+       (dolist (file (org-publish-get-base-files project exclude-regexp))
+         (unless (file-equal-p file theindex)
+           (org-publish-file file project t)))
+       ;; Populate "theindex.inc", if needed, and publish
+       ;; "theindex.org".
+       (when (plist-get project-plist :makeindex)
+         (org-publish-index-generate-theindex
+          project (plist-get project-plist :base-directory))
+         (org-publish-file theindex project t)))
+      (let ((fun (plist-get project-plist :completion-function)))
+       (cond ((consp fun) (dolist (f fun) (funcall f project-plist)))
+             ((functionp fun) (funcall fun project-plist))))
+      (org-publish-write-cache-file))))
 
 (defun org-publish-org-sitemap (project &optional sitemap-filename)
   "Create a sitemap of pages in set defined by PROJECT.
@@ -723,19 +760,18 @@ Default for SITEMAP-FILENAME is `sitemap.org'."
         (dir (file-name-as-directory
               (plist-get project-plist :base-directory)))
         (localdir (file-name-directory dir))
-        (indent-str (make-string 2 ?\ ))
+        (indent-str (make-string 2 ?\s))
         (exclude-regexp (plist-get project-plist :exclude))
         (files (nreverse
                 (org-publish-get-base-files project exclude-regexp)))
         (sitemap-filename (concat dir (or sitemap-filename "sitemap.org")))
         (sitemap-title (or (plist-get project-plist :sitemap-title)
-                         (concat "Sitemap for project " (car project))))
+                           (concat "Sitemap for project " (car project))))
         (sitemap-style (or (plist-get project-plist :sitemap-style)
                            'tree))
         (sitemap-sans-extension
          (plist-get project-plist :sitemap-sans-extension))
         (visiting (find-buffer-visiting sitemap-filename))
-        (ifn (file-name-nondirectory sitemap-filename))
         file sitemap-buffer)
     (with-current-buffer
        (let ((org-inhibit-startup t))
@@ -744,14 +780,12 @@ Default for SITEMAP-FILENAME is `sitemap.org'."
       (erase-buffer)
       (insert (concat "#+TITLE: " sitemap-title "\n\n"))
       (while (setq file (pop files))
-       (let ((fn (file-name-nondirectory file))
-             (link (file-relative-name file dir))
+       (let ((link (file-relative-name file dir))
              (oldlocal localdir))
          (when sitemap-sans-extension
            (setq link (file-name-sans-extension link)))
          ;; sitemap shouldn't list itself
-         (unless (equal (file-truename sitemap-filename)
-                        (file-truename file))
+         (unless (file-equal-p sitemap-filename file)
            (if (eq sitemap-style 'list)
                (message "Generating list-style sitemap for %s" sitemap-title)
              (message "Generating tree-style sitemap for %s" sitemap-title)
@@ -840,17 +874,15 @@ time in `current-time' format."
           (date (plist-get
                  (with-current-buffer file-buf
                    (if visiting
-                       (org-export-with-buffer-copy 
(org-export-get-environment))
+                       (org-export-with-buffer-copy
+                        (org-export-get-environment))
                      (org-export-get-environment)))
                  :date)))
       (unless visiting (kill-buffer file-buf))
-      ;; DATE is either a timestamp object or a secondary string.  If it
-      ;; is a timestamp or if the secondary string contains a timestamp,
+      ;; DATE is a secondary string.  If it contains a timestamp,
       ;; convert it to internal format.  Otherwise, use FILE
       ;; modification time.
-      (cond ((eq (org-element-type date) 'timestamp)
-            (org-time-string-to-time (org-element-interpret-data date)))
-           ((let ((ts (and (consp date) (assq 'timestamp date))))
+      (cond ((let ((ts (and (consp date) (assq 'timestamp date))))
               (and ts
                    (let ((value (org-element-interpret-data ts)))
                      (and (org-string-nw-p value)
@@ -877,25 +909,28 @@ When optional argument FORCE is non-nil, force publishing 
all
 files in PROJECT.  With a non-nil optional argument ASYNC,
 publishing will be done asynchronously, in another process."
   (interactive
-   (list
-    (assoc (org-icompleting-read
-           "Publish project: "
-           org-publish-project-alist nil t)
-          org-publish-project-alist)
-    current-prefix-arg))
-  (let ((project-alist  (if (not (stringp project)) (list project)
-                         ;; If this function is called in batch mode,
-                         ;; project is still a string here.
-                         (list (assoc project org-publish-project-alist)))))
-    (if async
-       (org-export-async-start (lambda (results) nil)
-         `(let ((org-publish-use-timestamps-flag
-                 (if ',force nil ,org-publish-use-timestamps-flag)))
-            (org-publish-projects ',project-alist)))
-      (save-window-excursion
-       (let* ((org-publish-use-timestamps-flag
-               (if force nil org-publish-use-timestamps-flag)))
-         (org-publish-projects project-alist))))))
+   (list (assoc (completing-read "Publish project: "
+                                org-publish-project-alist nil t)
+               org-publish-project-alist)
+        current-prefix-arg))
+  (let ((project (if (not (stringp project)) project
+                  ;; If this function is called in batch mode,
+                  ;; PROJECT is still a string here.
+                  (assoc project org-publish-project-alist))))
+    (cond
+     ((not project))
+     (async
+      (org-export-async-start (lambda (_) nil)
+       `(let ((org-publish-use-timestamps-flag
+               ,(and (not force) org-publish-use-timestamps-flag)))
+          ;; Expand components right now as external process may not
+          ;; be aware of complete `org-publish-project-alist'.
+          (org-publish-projects
+           ',(org-publish-expand-projects (list project))))))
+     (t (save-window-excursion
+         (let ((org-publish-use-timestamps-flag
+                (and (not force) org-publish-use-timestamps-flag)))
+           (org-publish-projects (list project))))))))
 
 ;;;###autoload
 (defun org-publish-all (&optional force async)
@@ -906,7 +941,7 @@ optional argument ASYNC, publishing will be done 
asynchronously,
 in another process."
   (interactive "P")
   (if async
-      (org-export-async-start (lambda (results) nil)
+      (org-export-async-start (lambda (_) nil)
        `(progn
           (when ',force (org-publish-remove-all-timestamps))
           (let ((org-publish-use-timestamps-flag
@@ -928,7 +963,7 @@ asynchronously, in another process."
   (interactive "P")
   (let ((file (buffer-file-name (buffer-base-buffer))))
     (if async
-       (org-export-async-start (lambda (results) nil)
+       (org-export-async-start (lambda (_) nil)
          `(let ((org-publish-use-timestamps-flag
                  (if ',force nil ,org-publish-use-timestamps-flag)))
             (org-publish-file ,file)))
@@ -954,7 +989,7 @@ the project."
 
 ;;; Index generation
 
-(defun org-publish-collect-index (output backend info)
+(defun org-publish-collect-index (output _backend info)
   "Update index for a file in cache.
 
 OUTPUT is the output from transcoding current file.  BACKEND is
@@ -969,7 +1004,7 @@ PARENT is a reference to the headline, if any, containing 
the
 original index keyword.  When non-nil, this reference is a cons
 cell.  Its CAR is a symbol among `id', `custom-id' and `name' and
 its CDR is a string."
-  (let ((file (plist-get info :input-file)))
+  (let ((file (file-truename (plist-get info :input-file))))
     (org-publish-cache-set-file-property
      file :index
      (delete-dups
@@ -1027,10 +1062,11 @@ publishing directory."
            ;; Compute the first difference between last entry and
            ;; current one: it tells the level at which new items
            ;; should be added.
-           (let* ((rank (if (equal entry last-entry) (1- (length entry))
-                          (loop for n from 0 to (length entry)
-                                unless (equal (nth n entry) (nth n last-entry))
-                                return n)))
+           (let* ((rank
+                   (if (equal entry last-entry) (1- (length entry))
+                     (cl-loop for n from 0 to (length entry)
+                              unless (equal (nth n entry) (nth n last-entry))
+                              return n)))
                   (len (length (nthcdr rank entry))))
              ;; For each term after the first difference, create
              ;; a new sub-list with the term as body.  Moreover,
@@ -1038,18 +1074,18 @@ publishing directory."
              (dotimes (n len)
                (insert
                 (concat
-                 (make-string (* (+ rank n) 2) ? ) "  - "
+                 (make-string (* (+ rank n) 2) ?\s) "  - "
                  (if (not (= (1- len) n)) (nth (+ rank n) entry)
                    ;; Last term: Link it to TARGET, if possible.
                    (let ((target (nth 2 idx)))
                      (format
                       "[[%s][%s]]"
                       ;; Destination.
-                      (case (car target)
-                        ('nil (format "file:%s" file))
-                        (id (format "id:%s" (cdr target)))
-                        (custom-id (format "file:%s::#%s" file (cdr target)))
-                        (otherwise (format "file:%s::*%s" file (cdr target))))
+                      (pcase (car target)
+                        (`nil (format "file:%s" file))
+                        (`id (format "id:%s" (cdr target)))
+                        (`custom-id (format "file:%s::#%s" file (cdr target)))
+                        (_ (format "file:%s::*%s" file (cdr target))))
                       ;; Description.
                       (car (last entry)))))
                  "\n"))))
@@ -1068,31 +1104,64 @@ publishing directory."
 ;; This part implements tools to resolve [[file.org::*Some headline]]
 ;; links, where "file.org" belongs to the current project.
 
-(defun org-publish-collect-numbering (output backend info)
+(defun org-publish--store-crossrefs (output _backend info)
+  "Store cross-references for current published file.
+
+OUPUT is the produced output, as a string.  BACKEND is the export
+back-end used, as a symbol.  INFO is the final export state, as
+a plist.
+
+This function is meant to be used as a final output filter.  See
+`org-publish-org-to'."
   (org-publish-cache-set-file-property
-   (plist-get info :input-file) :numbering
-   (mapcar (lambda (entry)
-            (cons (org-split-string
-                   (replace-regexp-in-string
-                    "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
-                    (org-element-property :raw-value (car entry))))
-                  (cdr entry)))
-          (plist-get info :headline-numbering)))
+   (file-truename (plist-get info :input-file))
+   :crossrefs
+   ;; Update `:crossrefs' so as to remove unused references and search
+   ;; cells.  Actually used references are extracted from
+   ;; `:internal-references', with references as strings removed.  See
+   ;; `org-export-get-reference' for details.
+   (cl-remove-if (lambda (pair) (stringp (car pair)))
+                (plist-get info :internal-references)))
   ;; Return output unchanged.
   output)
 
-(defun org-publish-resolve-external-fuzzy-link (file fuzzy)
-  "Return numbering for headline matching FUZZY search in FILE.
-
-Return value is a list of numbers, or nil.  This function allows
-the resolution of external fuzzy links like:
-
-  [[file.org::*fuzzy][description]]"
-  (when org-publish-cache
-    (cdr (assoc (org-split-string
-                (if (eq (aref fuzzy 0) ?*) (substring fuzzy 1) fuzzy))
-               (org-publish-cache-get-file-property
-                (expand-file-name file) :numbering nil t)))))
+(defun org-publish-resolve-external-link (search file)
+  "Return reference for element matching string SEARCH in FILE.
+
+Return value is an internal reference, as a string.
+
+This function allows resolving external links with a search
+option, e.g.,
+
+  [[file.org::*heading][description]]
+  [[file.org::#custom-id][description]]
+  [[file.org::fuzzy][description]]
+
+It only makes sense to use this if export back-end builds
+references with `org-export-get-reference'."
+  (if (not org-publish-cache)
+      (progn
+       (message "Reference %S in file %S cannot be resolved without publishing"
+                search
+                file)
+       "MissingReference")
+    (let* ((filename (file-truename file))
+          (crossrefs
+           (org-publish-cache-get-file-property filename :crossrefs nil t))
+          (cells (org-export-string-to-search-cell search)))
+      (or
+       ;; Look for reference associated to search cells triggered by
+       ;; LINK.  It can match when targeted file has been published
+       ;; already.
+       (let ((known (cdr (cl-some (lambda (c) (assoc c crossrefs)) cells))))
+        (and known (org-export-format-reference known)))
+       ;; Search cell is unknown so far.  Generate a new internal
+       ;; reference that will be used when the targeted file will be
+       ;; published.
+       (let ((new (org-export-new-reference crossrefs)))
+        (dolist (cell cells) (push (cons cell new) crossrefs))
+        (org-publish-cache-set-file-property filename :crossrefs crossrefs)
+        (org-export-format-reference new))))))
 
 
 
@@ -1109,13 +1178,12 @@ If FREE-CACHE, empty the cache."
       (error "Cannot find cache-file name in `org-publish-write-cache-file'"))
     (with-temp-file cache-file
       (let (print-level print-length)
-       (insert "(setq org-publish-cache (make-hash-table :test 'equal 
:weakness nil :size 100))\n")
+       (insert "(setq org-publish-cache \
+\(make-hash-table :test 'equal :weakness nil :size 100))\n")
        (maphash (lambda (k v)
                   (insert
-                   (format (concat "(puthash %S "
-                                   (if (or (listp v) (symbolp v))
-                                       "'" "")
-                                   "%S org-publish-cache)\n") k v)))
+                   (format "(puthash %S %s%S org-publish-cache)\n"
+                           k (if (or (listp v) (symbolp v)) "'" "") v)))
                 org-publish-cache)))
     (when free-cache (org-publish-reset-cache))))
 
@@ -1123,7 +1191,8 @@ If FREE-CACHE, empty the cache."
   "Initialize the projects cache if not initialized yet and return it."
 
   (unless project-name
-    (error "Cannot initialize `org-publish-cache' without projects name in 
`org-publish-initialize-cache'"))
+    (error "Cannot initialize `org-publish-cache' without projects name in \
+`org-publish-initialize-cache'"))
 
   (unless (file-exists-p org-publish-timestamp-directory)
     (make-directory org-publish-timestamp-directory t))
@@ -1157,7 +1226,7 @@ If FREE-CACHE, empty the cache."
   (setq org-publish-cache nil))
 
 (defun org-publish-cache-file-needs-publishing
-  (filename &optional pub-dir pub-func base-dir)
+    (filename &optional pub-dir pub-func _base-dir)
   "Check the timestamp of the last publishing of FILENAME.
 Return non-nil if the file needs publishing.  Also check if
 any included files have been more recently published, so that
@@ -1165,33 +1234,42 @@ the file including them will be republished as well."
   (unless org-publish-cache
     (error
      "`org-publish-cache-file-needs-publishing' called, but no cache present"))
-  (let* ((case-fold-search t)
-        (key (org-publish-timestamp-filename filename pub-dir pub-func))
+  (let* ((key (org-publish-timestamp-filename filename pub-dir pub-func))
         (pstamp (org-publish-cache-get key))
         (org-inhibit-startup t)
-        (visiting (find-buffer-visiting filename))
-        included-files-ctime buf)
-
+        included-files-ctime)
     (when (equal (file-name-extension filename) "org")
-      (setq buf (find-file (expand-file-name filename)))
-      (with-current-buffer buf
-       (goto-char (point-min))
-       (while (re-search-forward
-               "^#\\+INCLUDE:[ \t]+\"\\([^\t\n\r\"]*\\)\"[ \t]*.*$" nil t)
-         (let* ((included-file (expand-file-name (match-string 1)))
-                 (ctime (org-publish-cache-ctime-of-src included-file)))
-            (unless (member ctime included-files-ctime)
-              ;; FIXME: The original code insisted on appending this ctime
-              ;; to the end of the list, even tho the order seems irrelevant.
-              (setq included-files-ctime
-                    (append included-files-ctime (list ctime)))))))
-      (unless visiting (kill-buffer buf)))
-    (if (null pstamp) t
-      (let ((ctime (org-publish-cache-ctime-of-src filename)))
-       (or (< pstamp ctime)
-           (when included-files-ctime
-             (not (null (delq nil (mapcar (lambda(ct) (< ctime ct))
-                                          included-files-ctime))))))))))
+      (let ((visiting (find-buffer-visiting filename))
+           (buf (find-file-noselect filename))
+           (case-fold-search t))
+       (unwind-protect
+           (with-current-buffer buf
+             (goto-char (point-min))
+             (while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t)
+               (let* ((element (org-element-at-point))
+                      (included-file
+                       (and (eq (org-element-type element) 'keyword)
+                            (let ((value (org-element-property :value 
element)))
+                              (and value
+                                   (string-match
+                                    "\\`\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)"
+                                    value)
+                                   (let ((m (match-string 1 value)))
+                                     (org-unbracket-string
+                                      "\"" "\""
+                                      ;; Ignore search suffix.
+                                      (if (string-match "::.*?\"?\\'" m)
+                                          (substring m 0 (match-beginning 0))
+                                        m))))))))
+                 (when included-file
+                   (push (org-publish-cache-ctime-of-src
+                          (expand-file-name included-file))
+                         included-files-ctime)))))
+         (unless visiting (kill-buffer buf)))))
+    (or (null pstamp)
+       (let ((ctime (org-publish-cache-ctime-of-src filename)))
+         (or (< pstamp ctime)
+             (cl-some (lambda (ct) (< ctime ct)) included-files-ctime))))))
 
 (defun org-publish-cache-set-file-property
   (filename property value &optional project-name)
@@ -1206,35 +1284,32 @@ will be created.  Return VALUE."
        filename property value nil project-name))))
 
 (defun org-publish-cache-get-file-property
-  (filename property &optional default no-create project-name)
+    (filename property &optional default no-create project-name)
   "Return the value for a PROPERTY of file FILENAME in publishing cache.
-Use cache file of PROJECT-NAME. Return the value of that PROPERTY
-or DEFAULT, if the value does not yet exist.  If the entry will
-be created, unless NO-CREATE is not nil."
-  ;; Evtl. load the requested cache file:
-  (if project-name (org-publish-initialize-cache project-name))
-  (let ((pl (org-publish-cache-get filename)) retval)
-    (if pl
-       (if (plist-member pl property)
-           (setq retval (plist-get pl property))
-         (setq retval default))
-      ;; no pl yet:
-      (unless no-create
-       (org-publish-cache-set filename (list property default)))
-      (setq retval default))
-    retval))
+Use cache file of PROJECT-NAME.  Return the value of that PROPERTY,
+or DEFAULT, if the value does not yet exist.  Create the entry,
+if necessary, unless NO-CREATE is non-nil."
+  (when project-name (org-publish-initialize-cache project-name))
+  (let ((properties (org-publish-cache-get filename)))
+    (cond ((null properties)
+          (unless no-create
+            (org-publish-cache-set filename (list property default)))
+          default)
+         ((plist-member properties property) (plist-get properties property))
+         (t default))))
 
 (defun org-publish-cache-get (key)
   "Return the value stored in `org-publish-cache' for key KEY.
-Returns nil, if no value or nil is found, or the cache does not
-exist."
+Return nil, if no value or nil is found.  Raise an error if the
+cache does not exist."
   (unless org-publish-cache
     (error "`org-publish-cache-get' called, but no cache present"))
   (gethash key org-publish-cache))
 
 (defun org-publish-cache-set (key value)
   "Store KEY VALUE pair in `org-publish-cache'.
-Returns value on success, else nil."
+Returns value on success, else nil.  Raise an error if the cache
+does not exist."
   (unless org-publish-cache
     (error "`org-publish-cache-set' called, but no cache present"))
   (puthash key value org-publish-cache))
diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el
index 31d91eb..35927d9 100644
--- a/lisp/org/ox-texinfo.el
+++ b/lisp/org/ox-texinfo.el
@@ -1,4 +1,4 @@
-;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine
+;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 ;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com>
@@ -25,7 +25,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
 (require 'ox)
 
 (defvar orgtbl-exp-regexp)
@@ -39,8 +39,6 @@
     (center-block . org-texinfo-center-block)
     (clock . org-texinfo-clock)
     (code . org-texinfo-code)
-    (comment . (lambda (&rest args) ""))
-    (comment-block . (lambda (&rest args) ""))
     (drawer . org-texinfo-drawer)
     (dynamic-block . org-texinfo-dynamic-block)
     (entity . org-texinfo-entity)
@@ -58,18 +56,19 @@
     (keyword . org-texinfo-keyword)
     (line-break . org-texinfo-line-break)
     (link . org-texinfo-link)
+    (node-property . org-texinfo-node-property)
     (paragraph . org-texinfo-paragraph)
     (plain-list . org-texinfo-plain-list)
     (plain-text . org-texinfo-plain-text)
     (planning . org-texinfo-planning)
     (property-drawer . org-texinfo-property-drawer)
     (quote-block . org-texinfo-quote-block)
-    (quote-section . org-texinfo-quote-section)
     (radio-target . org-texinfo-radio-target)
     (section . org-texinfo-section)
     (special-block . org-texinfo-special-block)
     (src-block . org-texinfo-src-block)
     (statistics-cookie . org-texinfo-statistics-cookie)
+    (strike-through . org-texinfo-strike-through)
     (subscript . org-texinfo-subscript)
     (superscript . org-texinfo-superscript)
     (table . org-texinfo-table)
@@ -78,28 +77,46 @@
     (target . org-texinfo-target)
     (template . org-texinfo-template)
     (timestamp . org-texinfo-timestamp)
+    (underline . org-texinfo-underline)
     (verbatim . org-texinfo-verbatim)
     (verse-block . org-texinfo-verse-block))
-  :export-block "TEXINFO"
   :filters-alist
-  '((:filter-headline . org-texinfo-filter-section-blank-lines)
+  '((:filter-headline . org-texinfo--filter-section-blank-lines)
     (:filter-parse-tree . org-texinfo--normalize-headlines)
-    (:filter-section . org-texinfo-filter-section-blank-lines))
+    (:filter-section . org-texinfo--filter-section-blank-lines))
   :menu-entry
   '(?i "Export to Texinfo"
        ((?t "As TEXI file" org-texinfo-export-to-texinfo)
-       (?i "As INFO file" org-texinfo-export-to-info)))
+       (?i "As INFO file" org-texinfo-export-to-info)
+       (?o "As INFO file and open"
+           (lambda (a s v b)
+             (if a (org-texinfo-export-to-info t s v b)
+               (org-open-file (org-texinfo-export-to-info nil s v b)))))))
   :options-alist
   '((:texinfo-filename "TEXINFO_FILENAME" nil nil t)
     (:texinfo-class "TEXINFO_CLASS" nil org-texinfo-default-class t)
     (:texinfo-header "TEXINFO_HEADER" nil nil newline)
     (:texinfo-post-header "TEXINFO_POST_HEADER" nil nil newline)
-    (:subtitle "SUBTITLE" nil nil newline)
+    (:subtitle "SUBTITLE" nil nil parse)
     (:subauthor "SUBAUTHOR" nil nil newline)
     (:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t)
     (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t)
     (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t)
-    (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t)))
+    (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t)
+    ;; Other variables.
+    (:texinfo-classes nil nil org-texinfo-classes)
+    (:texinfo-format-headline-function nil nil 
org-texinfo-format-headline-function)
+    (:texinfo-node-description-column nil nil 
org-texinfo-node-description-column)
+    (:texinfo-active-timestamp-format nil nil 
org-texinfo-active-timestamp-format)
+    (:texinfo-inactive-timestamp-format nil nil 
org-texinfo-inactive-timestamp-format)
+    (:texinfo-diary-timestamp-format nil nil 
org-texinfo-diary-timestamp-format)
+    (:texinfo-link-with-unknown-path-format nil nil 
org-texinfo-link-with-unknown-path-format)
+    (:texinfo-tables-verbatim nil nil org-texinfo-tables-verbatim)
+    (:texinfo-table-scientific-notation nil nil 
org-texinfo-table-scientific-notation)
+    (:texinfo-def-table-markup nil nil org-texinfo-def-table-markup)
+    (:texinfo-text-markup-alist nil nil org-texinfo-text-markup-alist)
+    (:texinfo-format-drawer-function nil nil 
org-texinfo-format-drawer-function)
+    (:texinfo-format-inlinetask-function nil nil 
org-texinfo-format-inlinetask-function)))
 
 
 
@@ -193,7 +210,8 @@ a format string in which the section title will be added."
 
 ;;;; Headline
 
-(defcustom org-texinfo-format-headline-function 'ignore
+(defcustom org-texinfo-format-headline-function
+  'org-texinfo-format-headline-default-function
   "Function to format headline text.
 
 This function will be called with 5 arguments:
@@ -203,23 +221,11 @@ PRIORITY  the priority of the headline (integer or nil)
 TEXT      the main headline text (string).
 TAGS      the tags as a list of strings (list of strings or nil).
 
-The function result will be used in the section format string.
-
-As an example, one could set the variable to the following, in
-order to reproduce the default set-up:
-
-\(defun org-texinfo-format-headline (todo todo-type priority text tags)
-  \"Default format function for a headline.\"
-  (concat (when todo
-            (format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo))
-         (when priority
-            (format \"\\\\framebox{\\\\#%c} \" priority))
-         text
-         (when tags
-            (format \"\\\\hfill{}\\\\textsc{%s}\"
-              (mapconcat \\='identity tags \":\"))))"
+The function result will be used in the section format string."
   :group 'org-export-texinfo
-  :type 'function)
+  :type 'function
+  :version "26.1"
+  :package-version '(Org . "8.3"))
 
 ;;;; Node listing (menu)
 
@@ -263,6 +269,7 @@ be placed after the end of the title."
 
 (defcustom org-texinfo-table-scientific-notation "%s\\,(%s)"
   "Format string to display numbers in scientific notation.
+
 The format should have \"%s\" twice, for mantissa and exponent
 \(i.e. \"%s\\\\times10^{%s}\").
 
@@ -273,7 +280,12 @@ When nil, no transformation is made."
          (const :tag "No formatting" nil)))
 
 (defcustom org-texinfo-def-table-markup "@samp"
-  "Default setting for @table environments."
+  "Default markup for first column in two-column tables.
+
+This should an indicating command, e.g., \"@code\", \"@kbd\" or
+\"@asis\".
+
+It can be overridden locally using the \":indic\" attribute."
   :group 'org-export-texinfo
   :type 'string)
 
@@ -282,29 +294,28 @@ When nil, no transformation is made."
 (defcustom org-texinfo-text-markup-alist '((bold . "@strong{%s}")
                                           (code . code)
                                           (italic . "@emph{%s}")
-                                          (verbatim . verb)
-                                          (comment . "@c %s"))
+                                          (verbatim . verb))
   "Alist of Texinfo expressions to convert text markup.
 
-The key must be a symbol among `bold', `italic' and `comment'.
-The value is a formatting string to wrap fontified text with.
+The key must be a symbol among `bold', `code', `italic',
+`strike-through', `underscore' and `verbatim'.  The value is
+a formatting string to wrap fontified text with.
 
 Value can also be set to the following symbols: `verb' and
-`code'.  For the former, Org will use \"@verb\" to
-create a format string and select a delimiter character that
-isn't in the string.  For the latter, Org will use \"@code\"
-to typeset and try to protect special characters.
+`code'.  For the former, Org will use \"@verb\" to create
+a format string and select a delimiter character that isn't in
+the string.  For the latter, Org will use \"@code\" to typeset
+and try to protect special characters.
 
 If no association can be found for a given markup, text will be
 returned as-is."
   :group 'org-export-texinfo
   :type 'alist
-  :options '(bold code italic verbatim comment))
+  :options '(bold code italic strike-through underscore verbatim))
 
 ;;;; Drawers
 
-(defcustom org-texinfo-format-drawer-function
-  (lambda (name contents) contents)
+(defcustom org-texinfo-format-drawer-function (lambda (_name contents) 
contents)
   "Function called to format a drawer in Texinfo code.
 
 The function must accept two parameters:
@@ -321,7 +332,8 @@ The default function simply returns the value of CONTENTS."
 
 ;;;; Inlinetasks
 
-(defcustom org-texinfo-format-inlinetask-function 'ignore
+(defcustom org-texinfo-format-inlinetask-function
+  'org-texinfo-format-inlinetask-default-function
   "Function called to format an inlinetask in Texinfo code.
 
 The function must accept six parameters:
@@ -332,26 +344,7 @@ The function must accept six parameters:
   TAGS      the inlinetask tags, as a list of strings.
   CONTENTS  the contents of the inlinetask, as a string.
 
-The function should return the string to be exported.
-
-For example, the variable could be set to the following function
-in order to mimic default behavior:
-
-\(defun org-texinfo-format-inlinetask (todo type priority name tags contents)
-\"Format an inline task element for Texinfo export.\"
-  (let ((full-title
-        (concat
-         (when todo
-            (format \"@strong{%s} \" todo))
-         (when priority (format \"#%c \" priority))
-         title
-         (when tags
-            (format \":%s:\"
-                    (mapconcat \\='identity tags \":\")))))
-    (format (concat \"@center %s\n\n\"
-                   \"%s\"
-                    \"\n\"))
-           full-title contents))"
+The function should return the string to be exported."
   :group 'org-export-texinfo
   :type 'function)
 
@@ -359,10 +352,13 @@ in order to mimic default behavior:
 
 (defcustom org-texinfo-info-process '("makeinfo %f")
   "Commands to process a Texinfo file to an INFO file.
-This is list of strings, each of them will be given to the shell
-as a command.  %f in the command will be replaced by the full
-file name, %b by the file base name (i.e without extension) and
-%o by the base directory of the file."
+
+This is a list of strings, each of them will be given to the
+shell as a command.  %f in the command will be replaced by the
+relative file name, %F by the absolute file name, %b by the file
+base name (i.e. without directory and extension parts), %o by the
+base directory of the file and %O by the absolute file name of
+the output file."
   :group 'org-export-texinfo
   :type '(repeat :tag "Shell command sequence"
                 (string :tag "Shell command")))
@@ -398,15 +394,19 @@ Specified coding system will be matched against these 
strings.
 If two strings share the same prefix (e.g. \"ISO-8859-1\" and
 \"ISO-8859-15\"), the most specific one has to be listed first.")
 
+(defconst org-texinfo-inline-image-rules
+  (list (cons "file"
+             (regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
+  "Rules characterizing image files that can be inlined.")
+
 
 ;;; Internal Functions
 
-(defun org-texinfo-filter-section-blank-lines (headline back-end info)
+(defun org-texinfo--filter-section-blank-lines (headline _backend _info)
   "Filter controlling number of blank lines after a section."
-  (let ((blanks (make-string 2 ?\n)))
-    (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline)))
+  (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline))
 
-(defun org-texinfo--normalize-headlines (tree back-end info)
+(defun org-texinfo--normalize-headlines (tree _backend info)
   "Normalize headlines in TREE.
 
 BACK-END is the symbol specifying back-end used for export. INFO
@@ -435,76 +435,116 @@ Return new tree."
   "Return a character not used in string S.
 This is used to choose a separator for constructs like \\verb."
   (let ((ll 
"~,./?;':\"|address@hidden&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
-    (loop for c across ll
-         when (not (string-match (regexp-quote (char-to-string c)) s))
-         return (char-to-string c))))
+    (cl-loop for c across ll
+            when (not (string-match (regexp-quote (char-to-string c)) s))
+            return (char-to-string c))))
 
-(defun org-texinfo--text-markup (text markup)
+(defun org-texinfo--text-markup (text markup _info)
   "Format TEXT depending on MARKUP text markup.
-See `org-texinfo-text-markup-alist' for details."
-  (let ((fmt (cdr (assq markup org-texinfo-text-markup-alist))))
-    (cond
-     ;; No format string: Return raw text.
-     ((not fmt) text)
-     ((eq 'verb fmt)
-      (let ((separator (org-texinfo--find-verb-separator text)))
-       (concat "@verb{" separator text separator "}")))
-     ((eq 'code fmt)
-      (let ((start 0)
-           (rtn "")
-           char)
-       (while (string-match "address@hidden" text)
-         (setq char (match-string 0 text))
-         (if (> (match-beginning 0) 0)
-             (setq rtn (concat rtn (substring text 0 (match-beginning 0)))))
-         (setq text (substring text (1+ (match-beginning 0))))
-         (setq char (concat "@" char)
-               rtn (concat rtn char)))
-       (setq text (concat rtn text)
-             fmt "@code{%s}")
-       (format fmt text)))
-     ;; Else use format string.
-     (t (format fmt text)))))
-
-(defun org-texinfo--get-node (blob info)
-  "Return node or anchor associated to BLOB.
-BLOB is an element or object.  INFO is a plist used as
+INFO is a plist used as a communication channel.  See
+`org-texinfo-text-markup-alist' for details."
+  (pcase (cdr (assq markup org-texinfo-text-markup-alist))
+    ;; No format string: Return raw text.
+    (`nil text)
+    (`verb
+     (let ((separator (org-texinfo--find-verb-separator text)))
+       (concat "@verb{" separator text separator "}")))
+    (`code
+     (format "@code{%s}" (replace-regexp-in-string "address@hidden" "@\\&" 
text)))
+    ;; Else use format string.
+    (fmt (format fmt text))))
+
+(defun org-texinfo--get-node (datum info)
+  "Return node or anchor associated to DATUM.
+DATUM is an element or object.  INFO is a plist used as
 a communication channel.  The function guarantees the node or
 anchor name is unique."
   (let ((cache (plist-get info :texinfo-node-cache)))
-    (or (cdr (assq blob cache))
-       (let ((name
-              (org-texinfo--sanitize-node
-               (case (org-element-type blob)
-                 (headline
-                  (org-export-data (org-export-get-alt-title blob info) info))
-                 ((radio-target target) (org-element-property :value blob))
-                 (otherwise (or (org-element-property :name blob) ""))))))
-         ;; Ensure NAME is unique.
-         (while (rassoc name cache) (setq name (concat name "x")))
-         (plist-put info :texinfo-node-cache (cons (cons blob name) cache))
+    (or (cdr (assq datum cache))
+       (let* ((salt 0)
+              (basename
+               (org-texinfo--sanitize-node
+                (if (eq (org-element-type datum) 'headline)
+                    (org-texinfo--sanitize-title
+                     (org-export-get-alt-title datum info) info)
+                  (org-export-get-reference datum info))))
+              (name basename))
+         ;; Ensure NAME is unique and not reserved node name "Top".
+         (while (or (equal name "Top") (rassoc name cache))
+           (setq name (concat basename (format " %d" (cl-incf salt)))))
+         (plist-put info :texinfo-node-cache (cons (cons datum name) cache))
          name))))
 
-;;;; Menu sanitizing
-
 (defun org-texinfo--sanitize-node (title)
   "Bend string TITLE to node line requirements.
 Trim string and collapse multiple whitespace characters as they
-are not significant.  Also remove the following characters: @
-{ } ( ) : . ,"
-  (replace-regexp-in-string
-   "[:,.]" ""
+are not significant.  Replace leading left parenthesis, when
+followed by a right parenthesis, with a square bracket.  Remove
+periods, commas and colons."
+  (org-trim
    (replace-regexp-in-string
-    "\\`(\\(.*)\\)" "[\\1"
-    (org-trim (replace-regexp-in-string "[ \t]\\{2,\\}" " " title)))))
-
-;;;; Content sanitizing
+    "[ \t]+" " "
+    (replace-regexp-in-string
+     "[:,.]" ""
+     (replace-regexp-in-string "\\`(\\(.*?)\\)" "[\\1" title)))))
+
+(defun org-texinfo--sanitize-title (title info)
+  "Make TITLE suitable as a section name.
+TITLE is a string or a secondary string.  INFO is the current
+export state, as a plist."
+  (org-export-data-with-backend
+   title
+   (org-export-create-backend
+    :parent 'texinfo
+    :transcoders '((footnote-reference . ignore)
+                  (link . (lambda (object c i) c))
+                  (radio-target . (lambda (object c i) c))
+                  (target . ignore)))
+   info))
 
 (defun org-texinfo--sanitize-content (text)
   "Escape special characters in string TEXT.
 Special characters are: @ { }"
   (replace-regexp-in-string "address@hidden" "@\\&" text))
 
+(defun org-texinfo--wrap-float (value info &optional type label caption short)
+  "Wrap string VALUE within a @float command.
+INFO is the current export state, as a plist.  TYPE is float
+type, as a string.  LABEL is the cross reference label for the
+float, as a string.  CAPTION and SHORT are, respectively, the
+caption and shortcaption used for the float, as secondary
+strings (e.g., returned by `org-export-get-caption')."
+  (let* ((backend
+         (org-export-create-backend
+          :parent 'texinfo
+          :transcoders '((link . (lambda (object c i) c))
+                         (radio-target . (lambda (object c i) c))
+                         (target . ignore))))
+        (short-backend
+         (org-export-create-backend
+          :parent 'texinfo
+          :transcoders '((footnote-reference . ignore)
+                         (inline-src-block . ignore)
+                         (link . (lambda (object c i) c))
+                         (radio-target . (lambda (object c i) c))
+                         (target . ignore)
+                         (verbatim . ignore))))
+        (short-str
+         (if (and short caption)
+             (format "@shortcaption{%s}\n"
+                     (org-export-data-with-backend short short-backend info))
+           ""))
+        (caption-str
+         (if (or short caption)
+             (format "@caption{%s}\n"
+                     (org-export-data-with-backend
+                      (or caption short)
+                      (if (equal short-str "") short-backend backend)
+                      info))
+           "")))
+    (format "@float address@hidden float"
+           type (if label (concat "," label) "") value caption-str short-str)))
+
 ;;; Template
 
 (defun org-texinfo-template (contents info)
@@ -537,7 +577,7 @@ holding export options."
                     (name (symbol-name (or org-texinfo-coding-system
                                            buffer-file-coding-system))))
                 (dolist (system org-texinfo-supported-coding-systems "UTF-8")
-                  (when (org-string-match-p (regexp-quote system) name)
+                  (when (string-match-p (regexp-quote system) name)
                     (throw 'coding-system system))))))
            (language (plist-get info :language))
            (case-fold-search nil))
@@ -574,7 +614,7 @@ holding export options."
                 (let ((dirdesc
                        (let ((desc (plist-get info :texinfo-dirdesc)))
                          (cond ((not desc) nil)
-                               ((org-string-match-p "\\.$" desc) desc)
+                               ((string-suffix-p "." desc) desc)
                                (t (concat desc "."))))))
                   (if dirdesc (format "%-23s %s" dirtitle dirdesc) dirtitle))
                 "\n"
@@ -582,11 +622,14 @@ holding export options."
      ;; Title
      "@finalout\n"
      "@titlepage\n"
-     (format "@title %s\n" (or (plist-get info :texinfo-printed-title) title))
-     (let ((subtitle (plist-get info :subtitle)))
-       (and subtitle
-           (org-element-normalize-string
-            (replace-regexp-in-string "^" "@subtitle " subtitle))))
+     (when (plist-get info :with-title)
+       (concat
+       (format "@title %s\n"
+               (or (plist-get info :texinfo-printed-title) title ""))
+       (let ((subtitle (plist-get info :subtitle)))
+         (when subtitle
+           (format "@subtitle %s\n"
+                   (org-export-data subtitle info))))))
      (when (plist-get info :with-author)
        (concat
        ;; Primary author.
@@ -608,11 +651,17 @@ holding export options."
      "@end titlepage\n\n"
      ;; Table of contents.
      (and (plist-get info :with-toc) "@contents\n\n")
-     ;; Configure Top Node when not for Tex
+     ;; Configure Top Node when not for TeX.  Also include contents
+     ;; from the first section of the document.
      "@ifnottex\n"
      "@node Top\n"
      (format "@top %s\n" title)
-     (and copying "@insertcopying\n")
+     (let* ((first-section
+            (org-element-map (plist-get info :parse-tree) 'section
+              #'identity info t '(headline)))
+           (top-contents
+            (org-export-data (org-element-contents first-section) info)))
+       (and (org-string-nw-p top-contents) (concat "\n" top-contents)))
      "@end ifnottex\n\n"
      ;; Menu.
      (org-texinfo-make-menu (plist-get info :parse-tree) info 'master)
@@ -620,10 +669,8 @@ holding export options."
      ;; Document's body.
      contents "\n"
      ;; Creator.
-     (case (plist-get info :with-creator)
-       ((nil) nil)
-       (comment (format "@c %s\n" (plist-get info :creator)))
-       (otherwise (concat (plist-get info :creator) "\n")))
+     (and (plist-get info :with-creator)
+         (concat (plist-get info :creator) "\n"))
      ;; Document end.
      "@bye")))
 
@@ -633,15 +680,15 @@ holding export options."
 
 ;;;; Bold
 
-(defun org-texinfo-bold (bold contents info)
+(defun org-texinfo-bold (_bold contents info)
   "Transcode BOLD from Org to Texinfo.
 CONTENTS is the text with bold markup.  INFO is a plist holding
 contextual information."
-  (org-texinfo--text-markup contents 'bold))
+  (org-texinfo--text-markup contents 'bold info))
 
 ;;;; Center Block
 
-(defun org-texinfo-center-block (center-block contents info)
+(defun org-texinfo-center-block (_center-block contents _info)
   "Transcode a CENTER-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the block.  INFO is a plist used
 as a communication channel."
@@ -649,28 +696,26 @@ as a communication channel."
 
 ;;;; Clock
 
-(defun org-texinfo-clock (clock contents info)
+(defun org-texinfo-clock (clock _contents info)
   "Transcode a CLOCK element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (concat
    "@noindent"
    (format "@strong{%s} " org-clock-string)
-   (format org-texinfo-inactive-timestamp-format
-          (concat (org-translate-time
-                   (org-element-property :raw-value
-                                         (org-element-property :value clock)))
+   (format (plist-get info :texinfo-inactive-timestamp-format)
+          (concat (org-timestamp-translate (org-element-property :value clock))
                   (let ((time (org-element-property :duration clock)))
                     (and time (format " (%s)" time)))))
    "@*"))
 
 ;;;; Code
 
-(defun org-texinfo-code (code contents info)
+(defun org-texinfo-code (code _contents info)
   "Transcode a CODE object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (org-texinfo--text-markup (org-element-property :value code) 'code))
+  (org-texinfo--text-markup (org-element-property :value code) 'code info))
 
 ;;;; Drawer
 
@@ -679,13 +724,13 @@ channel."
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
   (let* ((name (org-element-property :drawer-name drawer))
-        (output (funcall org-texinfo-format-drawer-function
+        (output (funcall (plist-get info :texinfo-format-drawer-function)
                          name contents)))
     output))
 
 ;;;; Dynamic Block
 
-(defun org-texinfo-dynamic-block (dynamic-block contents info)
+(defun org-texinfo-dynamic-block (_dynamic-block contents _info)
   "Transcode a DYNAMIC-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
@@ -693,33 +738,68 @@ holding contextual information."
 
 ;;;; Entity
 
-(defun org-texinfo-entity (entity contents info)
-  "Transcode an ENTITY object from Org to Texinfo.
-CONTENTS are the definition itself.  INFO is a plist holding
-contextual information."
-  (let ((ent (org-element-property :latex entity)))
-    (if (org-element-property :latex-math-p entity) (format "@math{%s}" ent) 
ent)))
+(defun org-texinfo-entity (entity _contents _info)
+  "Transcode an ENTITY object from Org to Texinfo."
+  ;; Since there is not specific Texinfo entry in entities, use
+  ;; Texinfo-specific commands whenever possible, and fallback to
+  ;; UTF-8 otherwise.
+  (pcase (org-element-property :name entity)
+    ("AElig"                       "@AE{}")
+    ("aelig"                       "@ae{}")
+    ((or "bull" "bullet")          "@bullet{}")
+    ("copy"                        "@copyright{}")
+    ("deg"                         "@textdegree{}")
+    ((or "dots" "hellip")          "@dots{}")
+    ("equiv"                       "@equiv{}")
+    ((or "euro" "EUR")             "@euro{}")
+    ((or "ge" "geq")               "@geq{}")
+    ("laquo"                       "@guillemetleft{}")
+    ("iexcl"                       "@exclamdown{}")
+    ("imath"                       "@dotless{i}")
+    ("iquest"                      "@questiondown{}")
+    ("jmath"                       "@dotless{j}")
+    ((or "le" "leq")               "@leq{}")
+    ("lsaquo"                      "@guilsinglleft{}")
+    ("mdash"                       "---")
+    ("minus"                       "@minus{}")
+    ("nbsp"                        "@tie{}")
+    ("ndash"                       "--")
+    ("OElig"                       "@OE{}")
+    ("oelig"                       "@oe{}")
+    ("ordf"                        "@ordf{}")
+    ("ordm"                        "@ordm{}")
+    ("pound"                       "@pound{}")
+    ("raquo"                       "@guillemetright{}")
+    ((or "rArr" "Rightarrow")      "@result{}")
+    ("reg"                         "@registeredsymbol{}")
+    ((or "rightarrow" "to" "rarr") "@arrow{}")
+    ("rsaquo"                      "@guilsinglright{}")
+    ("thorn"                       "@th{}")
+    ("THORN"                       "@TH{}")
+    ((and (pred (string-prefix-p "_")) name) ;spacing entities
+     (format "@w{%s}" (substring name 1)))
+    (_ (org-element-property :utf-8 entity))))
 
 ;;;; Example Block
 
-(defun org-texinfo-example-block (example-block contents info)
+(defun org-texinfo-example-block (example-block _contents info)
   "Transcode an EXAMPLE-BLOCK element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (format "@address@hidden verbatim"
          (org-export-format-code-default example-block info)))
 
-;;;; Export Block
+;;; Export Block
 
-(defun org-texinfo-export-block (export-block contents info)
+(defun org-texinfo-export-block (export-block _contents _info)
   "Transcode a EXPORT-BLOCK element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (string= (org-element-property :type export-block) "TEXINFO")
     (org-remove-indentation (org-element-property :value export-block))))
 
-;;;; Export Snippet
+;;; Export Snippet
 
-(defun org-texinfo-export-snippet (export-snippet contents info)
+(defun org-texinfo-export-snippet (export-snippet _contents _info)
   "Transcode a EXPORT-SNIPPET object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (when (eq (org-export-snippet-backend export-snippet) 'texinfo)
@@ -727,17 +807,17 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Fixed Width
 
-(defun org-texinfo-fixed-width (fixed-width contents info)
+(defun org-texinfo-fixed-width (fixed-width _contents _info)
   "Transcode a FIXED-WIDTH element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (format "@address@hidden example"
+  (format "@address@hidden example"
          (org-remove-indentation
           (org-texinfo--sanitize-content
            (org-element-property :value fixed-width)))))
 
 ;;;; Footnote Reference
 
-(defun org-texinfo-footnote-reference (footnote contents info)
+(defun org-texinfo-footnote-reference (footnote _contents info)
   "Create a footnote reference for FOOTNOTE.
 
 FOOTNOTE is the footnote to define.  CONTENTS is nil.  INFO is a
@@ -755,7 +835,7 @@ holding contextual information."
   (let* ((class (plist-get info :texinfo-class))
         (level (org-export-get-relative-level headline info))
         (numberedp (org-export-numbered-headline-p headline info))
-        (class-sectioning (assoc class org-texinfo-classes))
+        (class-sectioning (assoc class (plist-get info :texinfo-classes)))
         ;; Find the index type, if any.
         (index (org-element-property :INDEX headline))
         ;; Create node info, to insert it before section formatting.
@@ -788,20 +868,10 @@ holding contextual information."
                    (org-export-get-tags headline info)))
         (priority (and (plist-get info :with-priority)
                        (org-element-property :priority headline)))
-        (text (org-export-data (org-element-property :title headline) info))
-        (full-text (if (not (eq org-texinfo-format-headline-function 'ignore))
-                       ;; User-defined formatting function.
-                       (funcall org-texinfo-format-headline-function
-                                todo todo-type priority text tags)
-                     ;; Default formatting.
-                     (concat
-                      (when todo
-                        (format "@strong{%s} " todo))
-                      (when priority (format "@emph{#%s} " priority))
-                      text
-                      (when tags
-                        (format " :%s:"
-                                (mapconcat 'identity tags ":"))))))
+        (text (org-texinfo--sanitize-title
+               (org-element-property :title headline) info))
+        (full-text (funcall (plist-get info :texinfo-format-headline-function)
+                            todo todo-type priority text tags))
         (contents (if (org-string-nw-p contents) (concat "\n" contents) "")))
     (cond
      ;; Case 1: This is a footnote section: ignore it.
@@ -835,9 +905,18 @@ holding contextual information."
      ;; Case 5: Standard headline.  Export it as a section.
      (t (concat node (format section-fmt full-text contents))))))
 
+(defun org-texinfo-format-headline-default-function
+  (todo _todo-type priority text tags)
+  "Default format function for a headline.
+See `org-texinfo-format-headline-function' for details."
+  (concat (when todo (format "@strong{%s} " todo))
+         (when priority (format "@emph{#%s} " priority))
+         text
+         (when tags (format " :%s:" (mapconcat 'identity tags ":")))))
+
 ;;;; Inline Src Block
 
-(defun org-texinfo-inline-src-block (inline-src-block contents info)
+(defun org-texinfo-inline-src-block (inline-src-block _contents _info)
   "Transcode an INLINE-SRC-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
@@ -860,31 +939,27 @@ holding contextual information."
                   (org-export-get-tags inlinetask info)))
        (priority (and (plist-get info :with-priority)
                       (org-element-property :priority inlinetask))))
-    ;; If `org-texinfo-format-inlinetask-function' is provided, call it
-    ;; with appropriate arguments.
-    (if (not (eq org-texinfo-format-inlinetask-function 'ignore))
-       (funcall org-texinfo-format-inlinetask-function
-                todo todo-type priority title tags contents)
-      ;; Otherwise, use a default template.
-      (let ((full-title
-            (concat
-             (when todo (format "@strong{%s} " todo))
-             (when priority (format "#%c " priority))
-             title
-             (when tags (format ":%s:"
-                                (mapconcat 'identity tags ":"))))))
-       (format (concat "@center %s\n\n"
-                       "%s"
-                       "\n")
-               full-title contents)))))
+    (funcall (plist-get info :texinfo-format-inlinetask-function)
+            todo todo-type priority title tags contents)))
+
+(defun org-texinfo-format-inlinetask-default-function
+  (todo _todo-type priority title tags contents)
+  "Default format function for a inlinetasks.
+See `org-texinfo-format-inlinetask-function' for details."
+  (let ((full-title
+        (concat (when todo (format "@strong{%s} " todo))
+                (when priority (format "#%c " priority))
+                title
+                (when tags (format ":%s:" (mapconcat #'identity tags ":"))))))
+    (format "@center %s\n\n%s\n" full-title contents)))
 
 ;;;; Italic
 
-(defun org-texinfo-italic (italic contents info)
+(defun org-texinfo-italic (_italic contents info)
   "Transcode ITALIC from Org to Texinfo.
 CONTENTS is the text with italic markup.  INFO is a plist holding
 contextual information."
-  (org-texinfo--text-markup contents 'italic))
+  (org-texinfo--text-markup contents 'italic info))
 
 ;;;; Item
 
@@ -899,32 +974,51 @@ contextual information."
 
 ;;;; Keyword
 
-(defun org-texinfo-keyword (keyword contents info)
+(defun org-texinfo-keyword (keyword _contents info)
   "Transcode a KEYWORD element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((key (org-element-property :key keyword))
-       (value (org-element-property :value keyword)))
-    (cond
-     ((string= key "TEXINFO") value)
-     ((string= key "CINDEX") (format "@cindex %s" value))
-     ((string= key "FINDEX") (format "@findex %s" value))
-     ((string= key "KINDEX") (format "@kindex %s" value))
-     ((string= key "PINDEX") (format "@pindex %s" value))
-     ((string= key "TINDEX") (format "@tindex %s" value))
-     ((string= key "VINDEX") (format "@vindex %s" value)))))
+  (let ((value (org-element-property :value keyword)))
+    (pcase (org-element-property :key keyword)
+      ("TEXINFO" value)
+      ("CINDEX" (format "@cindex %s" value))
+      ("FINDEX" (format "@findex %s" value))
+      ("KINDEX" (format "@kindex %s" value))
+      ("PINDEX" (format "@pindex %s" value))
+      ("TINDEX" (format "@tindex %s" value))
+      ("VINDEX" (format "@vindex %s" value))
+      ("TOC"
+       (cond ((string-match-p "\\<tables\\>" value)
+             (concat "@listoffloats "
+                     (org-export-translate "Table" :utf-8 info)))
+            ((string-match-p "\\<listings\\>" value)
+             (concat "@listoffloats "
+                     (org-export-translate "Listing" :utf-8 info))))))))
 
 ;;;; Line Break
 
-(defun org-texinfo-line-break (line-break contents info)
+(defun org-texinfo-line-break (_line-break _contents _info)
   "Transcode a LINE-BREAK object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   "@*\n")
 
 ;;;; Link
 
+(defun address@hidden (datum description info)
+  "Return @ref command for element or object DATUM.
+DESCRIPTION is the name of the section to print, as a string."
+  (let ((node-name (org-texinfo--get-node datum info))
+       ;; Sanitize DESCRIPTION for cross-reference use.  In
+       ;; particular, remove colons as they seem to cause (even
+       ;; within @asis{...} to the Texinfo reader.
+       (title (replace-regexp-in-string
+               "[ \t]*:+" ""
+               (replace-regexp-in-string "," "@comma{}" description))))
+    (if (equal title node-name)
+       (format "@ref{%s}" node-name)
+      (format "@ref{%s, , %s}" node-name title))))
+
 (defun org-texinfo-link (link desc info)
   "Transcode a LINK object from Org to Texinfo.
-
 DESC is the description part of the link, or the empty string.
 INFO is a plist holding contextual information.  See
 `org-export-data'."
@@ -935,78 +1029,99 @@ INFO is a plist holding contextual information.  See
         (path (cond
                ((member type '("http" "https" "ftp"))
                 (concat type ":" raw-path))
-               ((and (string= type "file") (file-name-absolute-p raw-path))
-                (concat "file:" raw-path))
-               (t raw-path)))
-        protocol)
+               ((string= type "file") (org-export-file-uri raw-path))
+               (t raw-path))))
     (cond
+     ((org-export-custom-protocol-maybe link desc 'texinfo))
+     ((org-export-inline-image-p link org-texinfo-inline-image-rules)
+      (org-texinfo--inline-image link info))
      ((equal type "radio")
       (let ((destination (org-export-resolve-radio-link link info)))
        (if (not destination) desc
-         (format "@ref{%s,,%s}"
-                 (org-texinfo--get-node destination info)
-                 desc))))
+         (address@hidden destination desc info))))
      ((member type '("custom-id" "id" "fuzzy"))
       (let ((destination
             (if (equal type "fuzzy")
                 (org-export-resolve-fuzzy-link link info)
               (org-export-resolve-id-link link info))))
-       (case (org-element-type destination)
-         ((nil)
+       (pcase (org-element-type destination)
+         (`nil
           (format org-texinfo-link-with-unknown-path-format
                   (org-texinfo--sanitize-content path)))
          ;; Id link points to an external file.
-         (plain-text
+         (`plain-text
           (if desc (format "@uref{file://%s,%s}" destination desc)
             (format "@uref{file://%s}" destination)))
-         (headline
-          (format "@ref{%s,%s}"
-                  (org-texinfo--get-node destination info)
-                  (cond
-                   (desc)
-                   ((org-export-numbered-headline-p destination info)
-                    (org-export-data
-                     (org-element-property :title destination) info))
-                   (t
-                    (mapconcat
-                     #'number-to-string
-                     (org-export-get-headline-number destination info) ".")))))
-         (otherwise
-          (let ((topic
-                 (or desc
-                     (if (and (eq (org-element-type destination) 'headline)
-                              (not (org-export-numbered-headline-p
-                                    destination info)))
-                         (org-export-data
-                          (org-element-property :title destination) info))
-                     (let ((n (org-export-get-ordinal destination info)))
-                       (cond
-                        ((not n) nil)
-                        ((integerp n) n)
-                        (t (mapconcat #'number-to-string n ".")))))))
-            (when topic
-              (format "@ref{%s,,%s}"
-                      (org-texinfo--get-node destination info)
-                      topic)))))))
+         ((or `headline
+              ;; Targets within headlines cannot be turned into
+              ;; @anchor{}, so we refer to the headline parent
+              ;; directly.
+              (and `target
+                   (guard (eq 'headline
+                              (org-element-type
+                               (org-element-property :parent destination))))))
+          (let ((headline (org-element-lineage destination '(headline) t)))
+            (address@hidden
+             headline
+             (or desc (org-texinfo--sanitize-title
+                       (org-element-property :title headline) info))
+             info)))
+         (_
+          (address@hidden
+           destination
+           (or desc
+               (pcase (org-export-get-ordinal destination info)
+                 ((and (pred integerp) n) (number-to-string n))
+                 ((and (pred consp) n) (mapconcat #'number-to-string n "."))
+                 (_ "???")))
+           info)))))                   ;cannot guess the description
      ((equal type "info")
       (let* ((info-path (split-string path "[:#]"))
             (info-manual (car info-path))
-            (info-node (or (cadr info-path) "top"))
+            (info-node (or (cadr info-path) "Top"))
             (title (or desc "")))
        (format "@ref{%s,%s,,%s,}" info-node title info-manual)))
      ((string= type "mailto")
       (format "@email{%s}"
              (concat (org-texinfo--sanitize-content path)
-                     (and desc (concat "," desc)))))
-     ((let ((protocol (nth 2 (assoc type org-link-protocols))))
-       (and (functionp protocol)
-            (funcall protocol (org-link-unescape path) desc 'texinfo))))
+                     (and desc (concat ", " desc)))))
      ;; External link with a description part.
-     ((and path desc) (format "@uref{%s,%s}" path desc))
+     ((and path desc) (format "@uref{%s, %s}" path desc))
      ;; External link without a description part.
      (path (format "@uref{%s}" path))
      ;; No path, only description.  Try to do something useful.
-     (t (format org-texinfo-link-with-unknown-path-format desc)))))
+     (t
+      (format (plist-get info :texinfo-link-with-unknown-path-format) desc)))))
+
+(defun org-texinfo--inline-image (link info)
+  "Return Texinfo code for an inline image.
+LINK is the link pointing to the inline image.  INFO is the
+current state of the export, as a plist."
+  (let* ((parent (org-export-get-parent-element link))
+        (label (and (org-element-property :name parent)
+                    (org-texinfo--get-node parent info)))
+        (caption (org-export-get-caption parent))
+        (shortcaption (org-export-get-caption parent t))
+        (path  (org-element-property :path link))
+        (filename
+         (file-name-sans-extension
+          (if (file-name-absolute-p path) (expand-file-name path) path)))
+        (extension (file-name-extension path))
+        (attributes (org-export-read-attribute :attr_texinfo parent))
+        (height (or (plist-get attributes :height) ""))
+        (width (or (plist-get attributes :width) ""))
+        (alt (or (plist-get attributes :alt) ""))
+        (image (format "@image{%s,%s,%s,%s,%s}"
+                       filename width height alt extension)))
+    (cond ((or caption shortcaption)
+          (org-texinfo--wrap-float image
+                                   info
+                                   (org-export-translate "Figure" :utf-8 info)
+                                   label
+                                   caption
+                                   shortcaption))
+         (label (concat "@anchor{" label "}\n" image))
+         (t image))))
 
 
 ;;;; Menu
@@ -1058,7 +1173,7 @@ is an integer, build the menu recursively, down to this 
depth."
                     (org-export-data (org-export-get-alt-title h info) info)
                     (org-texinfo--format-entries entries info))
             (org-texinfo--build-menu h info (1- level))))))
-      (org-texinfo--menu-entries scope info) "")))))
+      (org-texinfo--menu-entries scope info) "\n")))))
 
 (defun org-texinfo--format-entries (entries info)
   "Format all direct menu entries in SCOPE, as a string.
@@ -1067,8 +1182,13 @@ a plist containing contextual information."
   (org-element-normalize-string
    (mapconcat
     (lambda (h)
-      (let* ((title (org-export-data
-                    (org-export-get-alt-title h info) info))
+      (let* ((title
+             ;; Colons are used as a separator between title and node
+             ;; name.  Remove them.
+             (replace-regexp-in-string
+              "[ \t]+:+" ""
+              (org-texinfo--sanitize-title
+               (org-export-get-alt-title h info) info)))
             (node (org-texinfo--get-node h info))
             (entry (concat "* " title ":"
                            (if (string= title node) ":"
@@ -1099,9 +1219,20 @@ holding contextual information."
                 info nil 'headline)
               cache))))
 
+;;;; Node Property
+
+(defun org-texinfo-node-property (node-property _contents _info)
+  "Transcode a NODE-PROPERTY element from Org to Texinfo.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "%s:%s"
+          (org-element-property :key node-property)
+          (let ((value (org-element-property :value node-property)))
+            (if value (concat " " value) ""))))
+
 ;;;; Paragraph
 
-(defun org-texinfo-paragraph (paragraph contents info)
+(defun org-texinfo-paragraph (_paragraph contents _info)
   "Transcode a PARAGRAPH element from Org to Texinfo.
 CONTENTS is the contents of the paragraph, as a string.  INFO is
 the plist used as a communication channel."
@@ -1114,7 +1245,10 @@ the plist used as a communication channel."
 CONTENTS is the contents of the list.  INFO is a plist holding
 contextual information."
   (let* ((attr (org-export-read-attribute :attr_texinfo plain-list))
-        (indic (or (plist-get attr :indic) org-texinfo-def-table-markup))
+        (indic (let ((i (or (plist-get attr :indic)
+                            (plist-get info :texinfo-def-table-markup))))
+                 ;; Allow indicating commands with missing @ sign.
+                 (if (string-prefix-p "@" i) i (concat "@" i))))
         (table-type (plist-get attr :table-type))
         (type (org-element-property :type plain-list))
         (list-type (cond
@@ -1141,16 +1275,14 @@ contextual information."
       (setq output
            (org-export-activate-smart-quotes output :texinfo info text)))
     ;; LaTeX into @LaTeX{} and TeX into @TeX{}
-    (let ((case-fold-search nil)
-         (start 0))
-      (while (string-match "\\(\\(?:La\\)?TeX\\)" output start)
-       (setq output (replace-match
-                     (format "@%s{}" (match-string 1 output)) nil t output)
-             start (match-end 0))))
+    (let ((case-fold-search nil))
+      (setq output (replace-regexp-in-string "\\(?:La\\)?TeX" "@\\&{}" 
output)))
     ;; Convert special strings.
     (when (plist-get info :with-special-strings)
-      (while (string-match (regexp-quote "...") output)
-       (setq output (replace-match "@dots{}" nil t output))))
+      (setq output
+           (replace-regexp-in-string
+            "\\.\\.\\." "@dots{}"
+            (replace-regexp-in-string "\\\\-" "@-" output))))
     ;; Handle break preservation if required.
     (when (plist-get info :preserve-breaks)
       (setq output (replace-regexp-in-string
@@ -1160,7 +1292,7 @@ contextual information."
 
 ;;;; Planning
 
-(defun org-texinfo-planning (planning contents info)
+(defun org-texinfo-planning (planning _contents info)
   "Transcode a PLANNING element from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
@@ -1174,39 +1306,35 @@ information."
             (when closed
               (concat
                (format "@strong{%s} " org-closed-string)
-               (format org-texinfo-inactive-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value closed))))))
+               (format (plist-get info :texinfo-inactive-timestamp-format)
+                       (org-timestamp-translate closed)))))
           (let ((deadline (org-element-property :deadline planning)))
             (when deadline
               (concat
                (format "@strong{%s} " org-deadline-string)
-               (format org-texinfo-active-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value deadline))))))
+               (format (plist-get info :texinfo-active-timestamp-format)
+                       (org-timestamp-translate deadline)))))
           (let ((scheduled (org-element-property :scheduled planning)))
             (when scheduled
               (concat
                (format "@strong{%s} " org-scheduled-string)
-               (format org-texinfo-active-timestamp-format
-                       (org-translate-time
-                        (org-element-property :raw-value scheduled))))))))
+               (format (plist-get info :texinfo-active-timestamp-format)
+                       (org-timestamp-translate scheduled)))))))
     " ")
    "@*"))
 
 ;;;; Property Drawer
 
-(defun org-texinfo-property-drawer (property-drawer contents info)
+(defun org-texinfo-property-drawer (_property-drawer contents _info)
   "Transcode a PROPERTY-DRAWER element from Org to Texinfo.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  ;; The property drawer isn't exported but we want separating blank
-  ;; lines nonetheless.
-  "")
+CONTENTS holds the contents of the drawer.  INFO is a plist
+holding contextual information."
+  (and (org-string-nw-p contents)
+       (format "@address@hidden verbatim" contents)))
 
 ;;;; Quote Block
 
-(defun org-texinfo-quote-block (quote-block contents info)
+(defun org-texinfo-quote-block (quote-block contents _info)
   "Transcode a QUOTE-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the block.  INFO is a plist
 holding contextual information."
@@ -1216,15 +1344,6 @@ holding contextual information."
                                  (format " %s" title)))))
     (format "address@hidden quotation" start-quote contents)))
 
-;;;; Quote Section
-
-(defun org-texinfo-quote-section (quote-section contents info)
-  "Transcode a QUOTE-SECTION element from Org to Texinfo.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let ((value (org-remove-indentation
-               (org-element-property :value quote-section))))
-    (when value (format "@address@hidden verbatim" value))))
-
 ;;;; Radio Target
 
 (defun org-texinfo-radio-target (radio-target text info)
@@ -1232,8 +1351,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 TEXT is the text of the target.  INFO is a plist holding
 contextual information."
   (format "@anchor{%s}%s"
-         (org-export-solidify-link-text
-          (org-element-property :value radio-target))
+         (org-texinfo--get-node radio-target info)
          text))
 
 ;;;; Section
@@ -1242,40 +1360,67 @@ contextual information."
   "Transcode a SECTION element from Org to Texinfo.
 CONTENTS holds the contents of the section.  INFO is a plist
 holding contextual information."
-  (concat contents
-         (let ((parent (org-export-get-parent-headline section)))
-           (and parent (org-texinfo-make-menu parent info)))))
+  (let ((parent (org-export-get-parent-headline section)))
+    (when parent                       ;ignore very first section
+      (org-trim
+       (concat contents "\n" (org-texinfo-make-menu parent info))))))
 
 ;;;; Special Block
 
-(defun org-texinfo-special-block (special-block contents info)
+(defun org-texinfo-special-block (special-block contents _info)
   "Transcode a SPECIAL-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the block.  INFO is a plist used
 as a communication channel."
-  contents)
+  (let ((opt (org-export-read-attribute :attr_texinfo special-block :options))
+       (type (org-element-property :type special-block)))
+    (format "@address@hidden %s"
+           type
+           (if opt (concat " " opt) "")
+           (or contents "")
+           type)))
 
 ;;;; Src Block
 
-(defun org-texinfo-src-block (src-block contents info)
+(defun org-texinfo-src-block (src-block _contents info)
   "Transcode a SRC-BLOCK element from Org to Texinfo.
 CONTENTS holds the contents of the item.  INFO is a plist holding
 contextual information."
-  (let ((lispp (org-string-match-p "lisp"
-                                  (org-element-property :language src-block)))
-       (code (org-texinfo--sanitize-content
-              (org-export-format-code-default src-block info))))
-    (format (if lispp "@address@hidden lisp" "@address@hidden example") code)))
+  (let* ((lisp (string-match-p "lisp"
+                              (org-element-property :language src-block)))
+        (code (org-texinfo--sanitize-content
+               (org-export-format-code-default src-block info)))
+        (value (format
+                (if lisp "@address@hidden lisp" "@address@hidden example")
+                code))
+        (caption (org-export-get-caption src-block))
+        (shortcaption (org-export-get-caption src-block t)))
+    (if (not (or caption shortcaption)) value
+      (org-texinfo--wrap-float value
+                              info
+                              (org-export-translate "Listing" :utf-8 info)
+                              (org-texinfo--get-node src-block info)
+                              caption
+                              shortcaption))))
 
 ;;;; Statistics Cookie
 
-(defun org-texinfo-statistics-cookie (statistics-cookie contents info)
+(defun org-texinfo-statistics-cookie (statistics-cookie _contents _info)
   "Transcode a STATISTICS-COOKIE object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-element-property :value statistics-cookie))
 
+
+;;;; Strike-through
+
+(defun org-texinfo-strike-through (_strike-through contents info)
+  "Transcode STRIKE-THROUGH from Org to Texinfo.
+CONTENTS is the text with strike-through markup.  INFO is a plist
+holding contextual information."
+  (org-texinfo--text-markup contents 'strike-through info))
+
 ;;;; Subscript
 
-(defun org-texinfo-subscript (subscript contents info)
+(defun org-texinfo-subscript (_subscript contents _info)
   "Transcode a SUBSCRIPT object from Org to Texinfo.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -1283,7 +1428,7 @@ contextual information."
 
 ;;;; Superscript
 
-(defun org-texinfo-superscript (superscript contents info)
+(defun org-texinfo-superscript (_superscript contents _info)
   "Transcode a SUPERSCRIPT object from Org to Texinfo.
 CONTENTS is the contents of the object.  INFO is a plist holding
 contextual information."
@@ -1302,10 +1447,19 @@ contextual information."
     (let* ((col-width (org-export-read-attribute :attr_texinfo table :columns))
           (columns
            (if col-width (format "@columnfractions %s" col-width)
-             (org-texinfo-table-column-widths table info))))
-      (format "@multitable address@hidden multitable"
-             columns
-             contents))))
+             (org-texinfo-table-column-widths table info)))
+          (caption (org-export-get-caption table))
+          (shortcaption (org-export-get-caption table t))
+          (table-str (format "@multitable address@hidden multitable"
+                             columns
+                             contents)))
+      (if (not (or caption shortcaption)) table-str
+       (org-texinfo--wrap-float table-str
+                                info
+                                (org-export-translate "Table" :utf-8 info)
+                                (org-texinfo--get-node table info)
+                                caption
+                                shortcaption)))))
 
 (defun org-texinfo-table-column-widths (table info)
   "Determine the largest table cell in each column to process alignment.
@@ -1324,7 +1478,7 @@ a communication channel."
              (let ((w (- (org-element-property :contents-end cell)
                          (org-element-property :contents-begin cell))))
                (aset widths idx (max w (aref widths idx))))
-             (incf idx))
+             (cl-incf idx))
            info)))
       info)
     (format "{%s}" (mapconcat (lambda (w) (make-string w ?a)) widths "} {"))))
@@ -1335,16 +1489,18 @@ a communication channel."
   "Transcode a TABLE-CELL element from Org to Texinfo.
 CONTENTS is the cell contents.  INFO is a plist used as
 a communication channel."
-  (concat (if (and contents
-                  org-texinfo-table-scientific-notation
-                  (string-match orgtbl-exp-regexp contents))
-             ;; Use appropriate format string for scientific
-             ;; notation.
-             (format org-texinfo-table-scientific-notation
-                     (match-string 1 contents)
-                     (match-string 2 contents))
-           contents)
-         (when (org-export-get-next-element table-cell info) "address@hidden 
")))
+  (concat
+   (let ((scientific-notation
+         (plist-get info :texinfo-table-scientific-notation)))
+     (if (and contents
+             scientific-notation
+             (string-match orgtbl-exp-regexp contents))
+        ;; Use appropriate format string for scientific notation.
+        (format scientific-notation
+                (match-string 1 contents)
+                (match-string 2 contents))
+       contents))
+   (when (org-export-get-next-element table-cell info) "address@hidden ")))
 
 ;;;; Table Row
 
@@ -1365,39 +1521,47 @@ a communication channel."
 
 ;;;; Target
 
-(defun org-texinfo-target (target contents info)
+(defun org-texinfo-target (target _contents info)
   "Transcode a TARGET object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
-  (format "@anchor{%s}"
-         (org-export-solidify-link-text (org-element-property :value target))))
+  (format "@anchor{%s}" (org-texinfo--get-node target info)))
 
 ;;;; Timestamp
 
-(defun org-texinfo-timestamp (timestamp contents info)
+(defun org-texinfo-timestamp (timestamp _contents info)
   "Transcode a TIMESTAMP object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist holding contextual
 information."
   (let ((value (org-texinfo-plain-text
                (org-timestamp-translate timestamp) info)))
-    (case (org-element-property :type timestamp)
-      ((active active-range)
-       (format org-texinfo-active-timestamp-format value))
-      ((inactive inactive-range)
-       (format org-texinfo-inactive-timestamp-format value))
-      (t (format org-texinfo-diary-timestamp-format value)))))
+    (pcase (org-element-property :type timestamp)
+      ((or `active `active-range)
+       (format (plist-get info :texinfo-active-timestamp-format) value))
+      ((or `inactive `inactive-range)
+       (format (plist-get info :texinfo-inactive-timestamp-format) value))
+      (_ (format (plist-get info :texinfo-diary-timestamp-format) value)))))
+
+;;;; Underline
+
+(defun org-texinfo-underline (_underline contents info)
+  "Transcode UNDERLINE from Org to Texinfo.
+CONTENTS is the text with underline markup.  INFO is a plist
+holding contextual information."
+  (org-texinfo--text-markup contents 'underline info))
 
 ;;;; Verbatim
 
-(defun org-texinfo-verbatim (verbatim contents info)
+(defun org-texinfo-verbatim (verbatim _contents info)
   "Transcode a VERBATIM object from Org to Texinfo.
 CONTENTS is nil.  INFO is a plist used as a communication
 channel."
-  (org-texinfo--text-markup (org-element-property :value verbatim) 'verbatim))
+  (org-texinfo--text-markup
+   (org-element-property :value verbatim) 'verbatim info))
 
 ;;;; Verse Block
 
-(defun org-texinfo-verse-block (verse-block contents info)
+(defun org-texinfo-verse-block (_verse-block contents _info)
   "Transcode a VERSE-BLOCK element from Org to Texinfo.
 CONTENTS is verse block contents. INFO is a plist holding
 contextual information."
@@ -1436,7 +1600,7 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".texi" subtreep))
-       (org-export-coding-system `,org-texinfo-coding-system))
+       (org-export-coding-system org-texinfo-coding-system))
     (org-export-to-file 'texinfo outfile
       async subtreep visible-only body-only ext-plist)))
 
@@ -1473,7 +1637,7 @@ directory.
 Return INFO file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".texi" subtreep))
-       (org-export-coding-system `,org-texinfo-coding-system))
+       (org-export-coding-system org-texinfo-coding-system))
     (org-export-to-file 'texinfo outfile
       async subtreep visible-only body-only ext-plist
       (lambda (file) (org-texinfo-compile file)))))
@@ -1491,99 +1655,36 @@ Return output file name."
 
 ;;;###autoload
 (defun org-texinfo-convert-region-to-texinfo ()
-  "Assume the current region has org-mode syntax, and convert it to Texinfo.
+  "Assume the current region has Org syntax, and convert it to Texinfo.
 This can be used in any buffer.  For example, you can write an
-itemized list in org-mode syntax in an Texinfo buffer and use
-this command to convert it."
+itemized list in Org syntax in an Texinfo buffer and use this
+command to convert it."
   (interactive)
   (org-export-replace-region-by 'texinfo))
 
 (defun org-texinfo-compile (file)
   "Compile a texinfo file.
 
-FILE is the name of the file being compiled.  Processing is
-done through the command specified in `org-texinfo-info-process'.
+FILE is the name of the file being compiled.  Processing is done
+through the command specified in `org-texinfo-info-process',
+which see.  Output is redirected to \"*Org INFO Texinfo Output*\"
+buffer.
 
 Return INFO file name or an error if it couldn't be produced."
-  (let* ((base-name (file-name-sans-extension (file-name-nondirectory file)))
-        (full-name (file-truename file))
-        (out-dir (file-name-directory file))
-        ;; Properly set working directory for compilation.
-        (default-directory (if (file-name-absolute-p file)
-                               (file-name-directory full-name)
-                             default-directory))
-        errors)
-    (message "Processing Texinfo file %s..." file)
-    (save-window-excursion
-      ;; Replace %b, %f and %o with appropriate values in each command
-      ;; before applying it.  Output is redirected to "*Org INFO
-      ;; Texinfo Output*" buffer.
-      (let ((outbuf (get-buffer-create "*Org INFO Texinfo Output*")))
-       (dolist (command org-texinfo-info-process)
-         (shell-command
-          (replace-regexp-in-string
-           "%b" (shell-quote-argument base-name)
-           (replace-regexp-in-string
-            "%f" (shell-quote-argument full-name)
-            (replace-regexp-in-string
-             "%o" (shell-quote-argument out-dir) command t t) t t) t t)
-          outbuf))
-       ;; Collect standard errors from output buffer.
-       (setq errors (org-texinfo-collect-errors outbuf)))
-      (let ((infofile (concat out-dir base-name ".info")))
-       ;; Check for process failure.  Provide collected errors if
-       ;; possible.
-       (if (not (file-exists-p infofile))
-           (error "INFO file %s wasn't produced%s" infofile
-                  (if errors (concat ": " errors) ""))
-         ;; Else remove log files, when specified, and signal end of
-         ;; process to user, along with any error encountered.
-         (when org-texinfo-remove-logfiles
-           (dolist (ext org-texinfo-logfiles-extensions)
-             (let ((file (concat out-dir base-name "." ext)))
-               (when (file-exists-p file) (delete-file file)))))
-         (message (concat "Process completed"
-                          (if (not errors) "."
-                            (concat " with errors: " errors)))))
-       ;; Return output file name.
-       infofile))))
-
-(defun org-texinfo-collect-errors (buffer)
-  "Collect some kind of errors from \"makeinfo\" command output.
-
-BUFFER is the buffer containing output.
-
-Return collected error types as a string, or nil if there was
-none."
-  (with-current-buffer buffer
-    (save-excursion
-      (goto-char (point-min))
-      ;; Find final "makeinfo" run.
-      (when t
-       (let ((case-fold-search t)
-             (errors ""))
-         (when (save-excursion
-                 (re-search-forward "perhaps incorrect sectioning?" nil t))
-           (setq errors (concat errors " [incorrect sectioning]")))
-         (when (save-excursion
-                 (re-search-forward "missing close brace" nil t))
-           (setq errors (concat errors " [syntax error]")))
-         (when (save-excursion
-                 (re-search-forward "Unknown command" nil t))
-           (setq errors (concat errors " [undefined @command]")))
-         (when (save-excursion
-                 (re-search-forward "No matching @end" nil t))
-           (setq errors (concat errors " [block incomplete]")))
-         (when (save-excursion
-                 (re-search-forward "requires a sectioning" nil t))
-           (setq errors (concat errors " [invalid section command]")))
-         (when (save-excursion
-                 (re-search-forward "\\[unexpected\ ]" nil t))
-           (setq errors (concat errors " [unexpected error]")))
-         (when (save-excursion
-                 (re-search-forward "misplaced " nil t))
-           (setq errors (concat errors " [syntax error]")))
-         (and (org-string-nw-p errors) (org-trim errors)))))))
+  (message "Processing Texinfo file %s..." file)
+  (let* ((log-name "*Org INFO Texinfo Output*")
+        (log (get-buffer-create log-name))
+        (output
+         (org-compile-file file org-texinfo-info-process "info"
+                           (format "See %S for details" log-name)
+                           log)))
+    (when org-texinfo-remove-logfiles
+      (let ((base (file-name-sans-extension output)))
+       (dolist (ext org-texinfo-logfiles-extensions)
+         (let ((file (concat base "." ext)))
+           (when (file-exists-p file) (delete-file file))))))
+    (message "Process completed.")
+    output))
 
 
 (provide 'ox-texinfo)
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 59b6671..f39a395 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -1,4 +1,4 @@
-;;; ox.el --- Generic Export Engine for Org Mode
+;;; ox.el --- Export Framework for Org Mode          -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
@@ -28,12 +28,10 @@
 ;; Besides that parser, the generic exporter is made of three distinct
 ;; parts:
 ;;
-;; - The communication channel consists in a property list, which is
+;; - The communication channel consists of a property list, which is
 ;;   created and updated during the process.  Its use is to offer
 ;;   every piece of information, would it be about initial environment
-;;   or contextual data, all in a single place.  The exhaustive list
-;;   of properties is given in "The Communication Channel" section of
-;;   this file.
+;;   or contextual data, all in a single place.
 ;;
 ;; - The transcoder walks the parse tree, ignores or treat as plain
 ;;   text elements and objects according to export options, and
@@ -46,8 +44,9 @@
 ;;   output from back-end transcoders.  See "The Filter System"
 ;;   section for more information.
 ;;
-;; The core function is `org-export-as'.  It returns the transcoded
-;; buffer as a string.
+;; The core functions is `org-export-as'.  It returns the transcoded
+;; buffer as a string.  Its derivatives are `org-export-to-buffer' and
+;; `org-export-to-file'.
 ;;
 ;; An export back-end is defined with `org-export-define-backend'.
 ;; This function can also support specific buffer keywords, OPTION
@@ -64,32 +63,31 @@
 ;; Tools for common tasks across back-ends are implemented in the
 ;; following part of the file.
 ;;
-;; Then, a wrapper macro for asynchronous export,
-;; `org-export-async-start', along with tools to display results. are
-;; given in the penultimate part.
+;; Eventually, a dispatcher (`org-export-dispatch') is provided in the
+;; last one.
 ;;
-;; Eventually, a dispatcher (`org-export-dispatch') for standard
-;; back-ends is provided in the last one.
+;; See <http://orgmode.org/worg/dev/org-export-reference.html> for
+;; more information.
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
+(require 'ob-exp)
 (require 'org-element)
 (require 'org-macro)
-(require 'ob-exp)
+(require 'tabulated-list)
 
+(declare-function org-src-coderef-format "org-src" (&optional element))
+(declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
 (declare-function org-publish "ox-publish" (project &optional force async))
 (declare-function org-publish-all "ox-publish" (&optional force async))
-(declare-function
- org-publish-current-file "ox-publish" (&optional force async))
-(declare-function org-publish-current-project "ox-publish"
-                 (&optional force async))
+(declare-function org-publish-current-file "ox-publish" (&optional force 
async))
+(declare-function org-publish-current-project "ox-publish" (&optional force 
async))
 
 (defvar org-publish-project-alist)
 (defvar org-table-number-fraction)
 (defvar org-table-number-regexp)
 
-
 
 ;;; Internal Variables
 ;;
@@ -101,22 +99,21 @@
   "Maximum nesting depth for headlines, counting from 0.")
 
 (defconst org-export-options-alist
-  '((:author "AUTHOR" nil user-full-name t)
-    (:creator "CREATOR" nil org-export-creator-string)
-    (:date "DATE" nil nil t)
-    (:description "DESCRIPTION" nil nil newline)
+  '((:title "TITLE" nil nil parse)
+    (:date "DATE" nil nil parse)
+    (:author "AUTHOR" nil user-full-name parse)
     (:email "EMAIL" nil user-mail-address t)
+    (:language "LANGUAGE" nil org-export-default-language t)
+    (:select-tags "SELECT_TAGS" nil org-export-select-tags split)
     (:exclude-tags "EXCLUDE_TAGS" nil org-export-exclude-tags split)
+    (:creator "CREATOR" nil org-export-creator-string)
     (:headline-levels nil "H" org-export-headline-levels)
-    (:keywords "KEYWORDS" nil nil space)
-    (:language "LANGUAGE" nil org-export-default-language t)
     (:preserve-breaks nil "\\n" org-export-preserve-breaks)
     (:section-numbers nil "num" org-export-with-section-numbers)
-    (:select-tags "SELECT_TAGS" nil org-export-select-tags split)
     (:time-stamp-file nil "timestamp" org-export-time-stamp-file)
-    (:title "TITLE" nil nil space)
     (:with-archived-trees nil "arch" org-export-with-archived-trees)
     (:with-author nil "author" org-export-with-author)
+    (:with-broken-links nil "broken-links" org-export-with-broken-links)
     (:with-clocks nil "c" org-export-with-clocks)
     (:with-creator nil "creator" org-export-with-creator)
     (:with-date nil "date" org-export-with-date)
@@ -130,6 +127,7 @@
     (:with-latex nil "tex" org-export-with-latex)
     (:with-planning nil "p" org-export-with-planning)
     (:with-priority nil "pri" org-export-with-priority)
+    (:with-properties nil "prop" org-export-with-properties)
     (:with-smart-quotes nil "'" org-export-with-smart-quotes)
     (:with-special-strings nil "-" org-export-with-special-strings)
     (:with-statistics-cookies nil "stat" org-export-with-statistics-cookies)
@@ -139,10 +137,11 @@
     (:with-tags nil "tags" org-export-with-tags)
     (:with-tasks nil "tasks" org-export-with-tasks)
     (:with-timestamps nil "<" org-export-with-timestamps)
+    (:with-title nil "title" org-export-with-title)
     (:with-todo-keywords nil "todo" org-export-with-todo-keywords))
   "Alist between export properties and ways to set them.
 
-The CAR of the alist is the property name, and the CDR is a list
+The key of the alist is the property name, and the value is a list
 like (KEYWORD OPTION DEFAULT BEHAVIOR) where:
 
 KEYWORD is a string representing a buffer keyword, or nil.  Each
@@ -161,6 +160,9 @@ BEHAVIOR determines how Org should handle multiple keywords 
for
            a newline.
   `split'   Split values at white spaces, and cons them to the
            previous list.
+  `parse'   Parse value as a list of strings and Org objects,
+            which can then be transcoded with, e.g.,
+            `org-export-data'.  It implies `space' behavior.
 
 Values set through KEYWORD and OPTION have precedence over
 DEFAULT.
@@ -176,13 +178,12 @@ way they are handled must be hard-coded into
 `org-export--get-inbuffer-options' function.")
 
 (defconst org-export-filters-alist
-  '((:filter-bold . org-export-filter-bold-functions)
+  '((:filter-body . org-export-filter-body-functions)
+    (:filter-bold . org-export-filter-bold-functions)
     (:filter-babel-call . org-export-filter-babel-call-functions)
     (:filter-center-block . org-export-filter-center-block-functions)
     (:filter-clock . org-export-filter-clock-functions)
     (:filter-code . org-export-filter-code-functions)
-    (:filter-comment . org-export-filter-comment-functions)
-    (:filter-comment-block . org-export-filter-comment-block-functions)
     (:filter-diary-sexp . org-export-filter-diary-sexp-functions)
     (:filter-drawer . org-export-filter-drawer-functions)
     (:filter-dynamic-block . org-export-filter-dynamic-block-functions)
@@ -215,7 +216,6 @@ way they are handled must be hard-coded into
     (:filter-planning . org-export-filter-planning-functions)
     (:filter-property-drawer . org-export-filter-property-drawer-functions)
     (:filter-quote-block . org-export-filter-quote-block-functions)
-    (:filter-quote-section . org-export-filter-quote-section-functions)
     (:filter-radio-target . org-export-filter-radio-target-functions)
     (:filter-section . org-export-filter-section-functions)
     (:filter-special-block . org-export-filter-special-block-functions)
@@ -258,6 +258,16 @@ whose extension is either \"png\", \"jpeg\", \"jpg\", 
\"gif\",
 See `org-export-inline-image-p' for more information about
 rules.")
 
+(defconst org-export-ignored-local-variables
+  '(org-font-lock-keywords
+    org-element--cache org-element--cache-objects org-element--cache-sync-keys
+    org-element--cache-sync-requests org-element--cache-sync-timer)
+  "List of variables not copied through upon buffer duplication.
+Export process takes place on a copy of the original buffer.
+When this copy is created, all Org related local variables not in
+this list are copied to the new buffer.  Variables with an
+unreadable value are also ignored.")
+
 (defvar org-export-async-debug nil
   "Non-nil means asynchronous export process should leave data behind.
 
@@ -277,7 +287,7 @@ containing the back-end used, as a symbol, and either a 
process
 or the time at which it finished.  It is used to build the menu
 from `org-export-stack'.")
 
-(defvar org-export--registered-backends nil
+(defvar org-export-registered-backends nil
   "List of backends currently available in the exporter.
 This variable is set with `org-export-define-backend' and
 `org-export-define-derived-backend' functions.")
@@ -303,6 +313,7 @@ there is no export process in progress.
 It can be used to teach Babel blocks how to act differently
 according to the back-end used.")
 
+
 
 ;;; User-configurable Variables
 ;;
@@ -336,41 +347,46 @@ e.g. \"arch:nil\"."
   :type '(choice
          (const :tag "Not at all" nil)
          (const :tag "Headline only" headline)
-         (const :tag "Entirely" t)))
+         (const :tag "Entirely" t))
+  :safe (lambda (x) (memq x '(t nil headline))))
 
 (defcustom org-export-with-author t
   "Non-nil means insert author name into the exported file.
 This option can also be set with the OPTIONS keyword,
 e.g. \"author:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-clocks nil
   "Non-nil means export CLOCK keywords.
 This option can also be set with the OPTIONS keyword,
 e.g. \"c:t\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
-(defcustom org-export-with-creator 'comment
+(defcustom org-export-with-creator nil
   "Non-nil means the postamble should contain a creator sentence.
 
-The sentence can be set in `org-export-creator-string' and
-defaults to \"Generated by Org mode XX in Emacs XXX.\".
+The sentence can be set in `org-export-creator-string', which
+see.
 
-If the value is `comment' insert it as a comment."
+This option can also be set with the OPTIONS keyword, e.g.,
+\"creator:t\"."
   :group 'org-export-general
-  :type '(choice
-         (const :tag "No creator sentence" nil)
-         (const :tag "Sentence as a comment" comment)
-         (const :tag "Insert the sentence" t)))
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-date t
   "Non-nil means insert date in the exported document.
 This option can also be set with the OPTIONS keyword,
 e.g. \"date:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-date-timestamp-format nil
   "Time-stamp format string to use for DATE keyword.
@@ -383,7 +399,8 @@ string."
   :group 'org-export-general
   :type '(choice
          (string :tag "Time-stamp format string")
-         (const :tag "No format string" nil)))
+         (const :tag "No format string" nil))
+  :safe (lambda (x) (or (null x) (stringp x))))
 
 (defcustom org-export-creator-string
   (format "Emacs %s (Org mode %s)"
@@ -392,16 +409,18 @@ string."
   "Information about the creator of the document.
 This option can also be set on with the CREATOR keyword."
   :group 'org-export-general
-  :type '(string :tag "Creator string"))
+  :type '(string :tag "Creator string")
+  :safe #'stringp)
 
 (defcustom org-export-with-drawers '(not "LOGBOOK")
   "Non-nil means export contents of standard drawers.
 
 When t, all drawers are exported.  This may also be a list of
-drawer names to export.  If that list starts with `not', only
-drawers with such names will be ignored.
+drawer names to export, as strings.  If that list starts with
+`not', only drawers with such names will be ignored.
 
-This variable doesn't apply to properties drawers.
+This variable doesn't apply to properties drawers.  See
+`org-export-with-properties' instead.
 
 This option can also be set with the OPTIONS keyword,
 e.g. \"d:nil\"."
@@ -417,14 +436,20 @@ e.g. \"d:nil\"."
                (const :format "" not)
                (repeat :tag "Specify names of drawers to ignore during export"
                        :inline t
-                       (string :tag "Drawer name")))))
+                       (string :tag "Drawer name"))))
+  :safe (lambda (x) (or (booleanp x)
+                       (and (listp x)
+                            (or (cl-every #'stringp x)
+                                (and (eq (nth 0 x) 'not)
+                                     (cl-every #'stringp (cdr x))))))))
 
 (defcustom org-export-with-email nil
   "Non-nil means insert author email into the exported file.
 This option can also be set with the OPTIONS keyword,
 e.g. \"email:t\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-emphasize t
   "Non-nil means interpret *word*, /word/, _word_ and +word+.
@@ -436,7 +461,8 @@ respectively.
 This option can also be set with the OPTIONS keyword,
 e.g. \"*:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-exclude-tags '("noexport")
   "Tags that exclude a tree from export.
@@ -447,30 +473,26 @@ carry one of the `org-export-select-tags' will be removed.
 
 This option can also be set with the EXCLUDE_TAGS keyword."
   :group 'org-export-general
-  :type '(repeat (string :tag "Tag")))
+  :type '(repeat (string :tag "Tag"))
+  :safe (lambda (x) (and (listp x) (cl-every #'stringp x))))
 
 (defcustom org-export-with-fixed-width t
-  "Non-nil means lines starting with \":\" will be in fixed width font.
-
-This can be used to have pre-formatted text, fragments of code
-etc.  For example:
-  : ;; Some Lisp examples
-  : (while (defc cnt)
-  :   (ding))
-will be looking just like this in also HTML.  See also the QUOTE
-keyword.  Not all export backends support this.
-
+  "Non-nil means export lines starting with \":\".
 This option can also be set with the OPTIONS keyword,
 e.g. \"::nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :version "24.4"
+  :package-version '(Org . "8.0")
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-footnotes t
   "Non-nil means Org footnotes should be exported.
 This option can also be set with the OPTIONS keyword,
 e.g. \"f:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-latex t
   "Non-nil means process LaTeX environments and fragments.
@@ -487,7 +509,8 @@ t           Allow export of math snippets."
   :type '(choice
          (const :tag "Do not process math in any way" nil)
          (const :tag "Interpret math snippets" t)
-         (const :tag "Leave math verbatim" verbatim)))
+         (const :tag "Leave math verbatim" verbatim))
+  :safe (lambda (x) (memq x '(t nil verbatim))))
 
 (defcustom org-export-headline-levels 3
   "The last level which is still exported as a headline.
@@ -498,7 +521,8 @@ when exported, but back-end behavior may differ.
 This option can also be set with the OPTIONS keyword,
 e.g. \"H:2\"."
   :group 'org-export-general
-  :type 'integer)
+  :type 'integer
+  :safe #'integerp)
 
 (defcustom org-export-default-language "en"
   "The default language for export and clocktable translations, as a string.
@@ -507,14 +531,16 @@ This may have an association in
 `org-export-smart-quotes-alist' and `org-export-dictionary'.
 This option can also be set with the LANGUAGE keyword."
   :group 'org-export-general
-  :type '(string :tag "Language"))
+  :type '(string :tag "Language")
+  :safe #'stringp)
 
 (defcustom org-export-preserve-breaks nil
   "Non-nil means preserve all line breaks when exporting.
 This option can also be set with the OPTIONS keyword,
 e.g. \"\\n:t\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-entities t
   "Non-nil means interpret entities when exporting.
@@ -528,7 +554,8 @@ and the user option `org-entities-user'.
 This option can also be set with the OPTIONS keyword,
 e.g. \"e:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-inlinetasks t
   "Non-nil means inlinetasks should be exported.
@@ -537,7 +564,8 @@ e.g. \"inline:nil\"."
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-planning nil
   "Non-nil means include planning info in export.
@@ -550,14 +578,35 @@ e.g. \"p:t\"."
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-priority nil
   "Non-nil means include priority cookies in export.
 This option can also be set with the OPTIONS keyword,
 e.g. \"pri:t\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
+
+(defcustom org-export-with-properties nil
+  "Non-nil means export contents of properties drawers.
+
+When t, all properties are exported.  This may also be a list of
+properties to export, as strings.
+
+This option can also be set with the OPTIONS keyword,
+e.g. \"prop:t\"."
+  :group 'org-export-general
+  :version "24.4"
+  :package-version '(Org . "8.3")
+  :type '(choice
+         (const :tag "All properties" t)
+         (const :tag "None" nil)
+         (repeat :tag "Selected properties"
+                 (string :tag "Property name")))
+  :safe (lambda (x) (or (booleanp x)
+                       (and (listp x) (cl-every #'stringp x)))))
 
 (defcustom org-export-with-section-numbers t
   "Non-nil means add section numbers to headlines when exporting.
@@ -568,7 +617,8 @@ headlines whose relative level is higher or equal to n.
 This option can also be set with the OPTIONS keyword,
 e.g. \"num:t\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-select-tags '("export")
   "Tags that select a tree for export.
@@ -580,7 +630,8 @@ tagging it with one of the `org-export-exclude-tags'.
 
 This option can also be set with the SELECT_TAGS keyword."
   :group 'org-export-general
-  :type '(repeat (string :tag "Tag")))
+  :type '(repeat (string :tag "Tag"))
+  :safe (lambda (x) (and (listp x) (cl-every #'stringp x))))
 
 (defcustom org-export-with-smart-quotes nil
   "Non-nil means activate smart quotes during export.
@@ -595,7 +646,8 @@ E.g., you can load Babel for french like this:
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-special-strings t
   "Non-nil means interpret \"\\-\", \"--\" and \"---\" for export.
@@ -612,7 +664,8 @@ When this option is turned on, these strings will be 
exported as:
 This option can also be set with the OPTIONS keyword,
 e.g. \"-:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-statistics-cookies t
   "Non-nil means include statistics cookies in export.
@@ -621,7 +674,8 @@ e.g. \"stat:nil\""
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-sub-superscripts t
   "Non-nil means interpret \"_\" and \"^\" for export.
@@ -658,7 +712,8 @@ frequently in plain text."
   :type '(choice
          (const :tag "Interpret them" t)
          (const :tag "Curly brackets only" {})
-         (const :tag "Do not interpret them" nil)))
+         (const :tag "Do not interpret them" nil))
+  :safe (lambda (x) (memq x '(t nil {}))))
 
 (defcustom org-export-with-toc t
   "Non-nil means create a table of contents in exported files.
@@ -676,20 +731,19 @@ e.g. \"toc:nil\" or \"toc:3\"."
   :type '(choice
          (const :tag "No Table of Contents" nil)
          (const :tag "Full Table of Contents" t)
-         (integer :tag "TOC to level")))
+         (integer :tag "TOC to level"))
+  :safe (lambda (x) (or (booleanp x)
+                       (integerp x))))
 
 (defcustom org-export-with-tables t
-  "If non-nil, lines starting with \"|\" define a table.
-For example:
-
-  | Name        | Address  | Birthday  |
-  |-------------+----------+-----------|
-  | Arthur Dent | England  | 29.2.2100 |
-
+  "Non-nil means export tables.
 This option can also be set with the OPTIONS keyword,
 e.g. \"|:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :version "24.4"
+  :package-version '(Org . "8.0")
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-tags t
   "If nil, do not export tags, just remove them from headlines.
@@ -704,7 +758,8 @@ e.g. \"tags:nil\"."
   :type '(choice
          (const :tag "Off" nil)
          (const :tag "Not in TOC" not-in-toc)
-         (const :tag "On" t)))
+         (const :tag "On" t))
+  :safe (lambda (x) (memq x '(t nil not-in-toc))))
 
 (defcustom org-export-with-tasks t
   "Non-nil means include TODO items for export.
@@ -725,14 +780,28 @@ e.g. \"tasks:nil\"."
          (const :tag "Not-done tasks" todo)
          (const :tag "Only done tasks" done)
          (repeat :tag "Specific TODO keywords"
-                 (string :tag "Keyword"))))
+                 (string :tag "Keyword")))
+  :safe (lambda (x) (or (memq x '(nil t todo done))
+                       (and (listp x)
+                            (cl-every #'stringp x)))))
+
+(defcustom org-export-with-title t
+  "Non-nil means print title into the exported file.
+This option can also be set with the OPTIONS keyword,
+e.g. \"title:nil\"."
+  :group 'org-export-general
+  :version "26.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-time-stamp-file t
   "Non-nil means insert a time stamp into the exported file.
-The time stamp shows when the file was created. This option can
+The time stamp shows when the file was created.  This option can
 also be set with the OPTIONS keyword, e.g. \"timestamp:nil\"."
   :group 'org-export-general
-  :type 'boolean)
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom org-export-with-timestamps t
   "Non nil means allow timestamps in export.
@@ -754,7 +823,8 @@ This option can also be set with the OPTIONS keyword, e.g.
          (const :tag "All timestamps" t)
          (const :tag "Only active timestamps" active)
          (const :tag "Only inactive timestamps" inactive)
-         (const :tag "No timestamp" nil)))
+         (const :tag "No timestamp" nil))
+  :safe (lambda (x) (memq x '(t nil active inactive))))
 
 (defcustom org-export-with-todo-keywords t
   "Non-nil means include TODO keywords in export.
@@ -772,12 +842,33 @@ is nil.  You can also allow them through local buffer 
variables."
   :package-version '(Org . "8.0")
   :type 'boolean)
 
+(defcustom org-export-with-broken-links nil
+  "Non-nil means do not raise an error on broken links.
+
+When this variable is non-nil, broken links are ignored, without
+stopping the export process.  If it is set to `mark', broken
+links are marked as such in the output, with a string like
+
+  [BROKEN LINK: path]
+
+where PATH is the un-resolvable reference.
+
+This option can also be set with the OPTIONS keyword, e.g.,
+\"broken-links:mark\"."
+  :group 'org-export-general
+  :version "26.1"
+  :package-version '(Org . "9.0")
+  :type '(choice
+         (const :tag "Ignore broken links" t)
+         (const :tag "Mark broken links in output" mark)
+         (const :tag "Raise an error" nil)))
+
 (defcustom org-export-snippet-translation-alist nil
   "Alist between export snippets back-ends and exporter back-ends.
 
 This variable allows providing shortcuts for export snippets.
 
-For example, with a value of \((\"h\" . \"html\")), the
+For example, with a value of \\='((\"h\" . \"html\")), the
 HTML back-end will recognize the contents of \"@@h:<b>@@\" as
 HTML code while every other back-end will ignore it."
   :group 'org-export-general
@@ -785,7 +876,12 @@ HTML code while every other back-end will ignore it."
   :package-version '(Org . "8.0")
   :type '(repeat
          (cons (string :tag "Shortcut")
-               (string :tag "Back-end"))))
+               (string :tag "Back-end")))
+  :safe (lambda (x)
+         (and (listp x)
+              (cl-every #'consp x)
+              (cl-every #'stringp (mapcar #'car x))
+              (cl-every #'stringp (mapcar #'cdr x)))))
 
 (defcustom org-export-coding-system nil
   "Coding system for the exported file."
@@ -794,11 +890,12 @@ HTML code while every other back-end will ignore it."
   :package-version '(Org . "8.0")
   :type 'coding-system)
 
-(defcustom org-export-copy-to-kill-ring 'if-interactive
+(defcustom org-export-copy-to-kill-ring nil
   "Non-nil means pushing export output to the kill ring.
 This variable is ignored during asynchronous export."
   :group 'org-export-general
-  :version "24.3"
+  :version "26.1"
+  :package-version '(Org . "8.3")
   :type '(choice
          (const :tag "Always" t)
          (const :tag "When export is done interactively" if-interactive)
@@ -825,21 +922,29 @@ these cases."
 (defcustom org-export-in-background nil
   "Non-nil means export and publishing commands will run in background.
 Results from an asynchronous export are never displayed
-automatically.  But you can retrieve them with \\[org-export-stack]."
+automatically.  But you can retrieve them with `\\[org-export-stack]'."
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
   :type 'boolean)
 
-(defcustom org-export-async-init-file user-init-file
+(defcustom org-export-async-init-file nil
   "File used to initialize external export process.
-Value must be an absolute file name.  It defaults to user's
-initialization file.  Though, a specific configuration makes the
-process faster and the export more portable."
+
+Value must be either nil or an absolute file name.  When nil, the
+external process is launched like a regular Emacs session,
+loading user's initialization file and any site specific
+configuration.  If a file is provided, it, and only it, is loaded
+at start-up.
+
+Therefore, using a specific configuration makes the process to
+load faster and the export more portable."
   :group 'org-export-general
   :version "24.4"
   :package-version '(Org . "8.0")
-  :type '(file :must-match t))
+  :type '(choice
+         (const :tag "Regular startup" nil)
+         (file :tag "Specific start-up file" :must-match t)))
 
 (defcustom org-export-dispatch-use-expert-ui nil
   "Non-nil means using a non-intrusive `org-export-dispatch'.
@@ -887,17 +992,16 @@ mode."
 ;; Eventually `org-export-barf-if-invalid-backend' returns an error
 ;; when a given back-end hasn't been registered yet.
 
-(defstruct (org-export-backend (:constructor org-export-create-backend)
-                              (:copier nil))
+(cl-defstruct (org-export-backend (:constructor org-export-create-backend)
+                                 (:copier nil))
   name parent transcoders options filters blocks menu)
 
+;;;###autoload
 (defun org-export-get-backend (name)
   "Return export back-end named after NAME.
 NAME is a symbol.  Return nil if no such back-end is found."
-  (catch 'found
-    (dolist (b org-export--registered-backends)
-      (when (eq (org-export-backend-name b) name)
-       (throw 'found b)))))
+  (cl-find-if (lambda (b) (and (eq name (org-export-backend-name b))))
+             org-export-registered-backends))
 
 (defun org-export-register-backend (backend)
   "Register BACKEND as a known export back-end.
@@ -909,16 +1013,12 @@ BACKEND is a structure with `org-export-backend' type."
   (let ((parent (org-export-backend-parent backend)))
     (when (and parent (not (org-export-get-backend parent)))
       (error "Cannot use unknown \"%s\" back-end as a parent" parent)))
-  ;; Register dedicated export blocks in the parser.
-  (dolist (name (org-export-backend-blocks backend))
-    (add-to-list 'org-element-block-name-alist
-                (cons name 'org-element-export-block-parser)))
   ;; If a back-end with the same name as BACKEND is already
   ;; registered, replace it with BACKEND.  Otherwise, simply add
   ;; BACKEND to the list of registered back-ends.
   (let ((old (org-export-get-backend (org-export-backend-name backend))))
-    (if old (setcar (memq old org-export--registered-backends) backend)
-      (push backend org-export--registered-backends))))
+    (if old (setcar (memq old org-export-registered-backends) backend)
+      (push backend org-export-registered-backends))))
 
 (defun org-export-barf-if-invalid-backend (backend)
   "Signal an error if BACKEND isn't defined."
@@ -969,7 +1069,9 @@ BACKEND is an export back-end, as return by, e.g,,
 for the shape of the return value.
 
 Unlike to `org-export-backend-options', this function also
-returns options inherited from parent back-ends, if any."
+returns options inherited from parent back-ends, if any.
+
+Return nil if BACKEND is unknown."
   (when (symbolp backend) (setq backend (org-export-get-backend backend)))
   (when backend
     (let ((options (org-export-backend-options backend))
@@ -1039,14 +1141,6 @@ back-end.
 BODY can start with pre-defined keyword arguments.  The following
 keywords are understood:
 
-  :export-block
-
-    String, or list of strings, representing block names that
-    will not be parsed.  This is used to specify blocks that will
-    contain raw code specific to the back-end.  These blocks
-    still have to be handled by the relative `export-block' type
-    translator.
-
   :filters-alist
 
     Alist between filters and function, or list of functions,
@@ -1060,7 +1154,7 @@ keywords are understood:
     Menu entry for the export dispatcher.  It should be a list
     like:
 
-      (KEY DESCRIPTION-OR-ORDINAL ACTION-OR-MENU)
+      \\='(KEY DESCRIPTION-OR-ORDINAL ACTION-OR-MENU)
 
     where :
 
@@ -1084,17 +1178,17 @@ keywords are understood:
       If it is an alist, associations should follow the
       pattern:
 
-        (KEY DESCRIPTION ACTION)
+        \\='(KEY DESCRIPTION ACTION)
 
       where KEY, DESCRIPTION and ACTION are described above.
 
     Valid values include:
 
-       (?m \"My Special Back-end\" my-special-export-function)
+      \\='(?m \"My Special Back-end\" my-special-export-function)
 
       or
 
-       (?l \"Export to LaTeX\"
+      \\='(?l \"Export to LaTeX\"
            (?p \"As PDF file\" org-latex-export-to-pdf)
            (?o \"As PDF file and open\"
                (lambda (a s v b)
@@ -1105,7 +1199,7 @@ keywords are understood:
       or the following, which will be added to the previous
       sub-menu,
 
-       (?l 1
+      \\='(?l 1
           ((?B \"As TEX buffer (Beamer)\" org-beamer-export-as-latex)
            (?P \"As PDF file (Beamer)\" org-beamer-export-to-pdf)))
 
@@ -1116,22 +1210,19 @@ keywords are understood:
     `org-export-options-alist' for more information about
     structure of the values."
   (declare (indent 1))
-  (let (blocks filters menu-entry options contents)
+  (let (filters menu-entry options)
     (while (keywordp (car body))
-      (case (pop body)
-        (:export-block (let ((names (pop body)))
-                        (setq blocks (if (consp names) (mapcar 'upcase names)
-                                       (list (upcase names))))))
-       (:filters-alist (setq filters (pop body)))
-       (:menu-entry (setq menu-entry (pop body)))
-        (:options-alist (setq options (pop body)))
-        (t (pop body))))
+      (let ((keyword (pop body)))
+       (pcase keyword
+         (:filters-alist (setq filters (pop body)))
+         (:menu-entry (setq menu-entry (pop body)))
+         (:options-alist (setq options (pop body)))
+         (_ (error "Unknown keyword: %s" keyword)))))
     (org-export-register-backend
      (org-export-create-backend :name backend
                                :transcoders transcoders
                                :options options
                                :filters filters
-                               :blocks blocks
                                :menu menu-entry))))
 
 (defun org-export-define-derived-backend (child parent &rest body)
@@ -1143,14 +1234,6 @@ the parent back-end.
 BODY can start with pre-defined keyword arguments.  The following
 keywords are understood:
 
-  :export-block
-
-    String, or list of strings, representing block names that
-    will not be parsed.  This is used to specify blocks that will
-    contain raw code specific to the back-end.  These blocks
-    still have to be handled by the relative `export-block' type
-    translator.
-
   :filters-alist
 
     Alist of filters that will overwrite or complete filters
@@ -1187,24 +1270,21 @@ The back-end could then be called with, for example:
 
   (org-export-to-buffer \\='my-latex \"*Test my-latex*\")"
   (declare (indent 2))
-  (let (blocks filters menu-entry options transcoders contents)
+  (let (filters menu-entry options transcoders)
     (while (keywordp (car body))
-      (case (pop body)
-       (:export-block (let ((names (pop body)))
-                        (setq blocks (if (consp names) (mapcar 'upcase names)
-                                       (list (upcase names))))))
-        (:filters-alist (setq filters (pop body)))
-       (:menu-entry (setq menu-entry (pop body)))
-        (:options-alist (setq options (pop body)))
-        (:translate-alist (setq transcoders (pop body)))
-        (t (pop body))))
+      (let ((keyword (pop body)))
+       (pcase keyword
+         (:filters-alist (setq filters (pop body)))
+         (:menu-entry (setq menu-entry (pop body)))
+         (:options-alist (setq options (pop body)))
+         (:translate-alist (setq transcoders (pop body)))
+         (_ (error "Unknown keyword: %s" keyword)))))
     (org-export-register-backend
      (org-export-create-backend :name child
                                :parent parent
                                :transcoders transcoders
                                :options options
                                :filters filters
-                               :blocks blocks
                                :menu menu-entry))))
 
 
@@ -1223,274 +1303,7 @@ The back-end could then be called with, for example:
 ;;    `org-export-options-alist' variable.
 ;;
 ;; 2. Tree properties are extracted directly from the parsed tree,
-;;    just before export, by `org-export-collect-tree-properties'.
-;;
-;; Here is the full list of properties available during transcode
-;; process, with their category and their value type.
-;;
-;; + `:author' :: Author's name.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:back-end' :: Current back-end used for transcoding.
-;;   - category :: tree
-;;   - type :: symbol
-;;
-;; + `:creator' :: String to write as creation information.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:date' :: String to use as date.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:description' :: Description text for the current data.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:email' :: Author's email.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:exclude-tags' :: Tags for exclusion of subtrees from export
-;;      process.
-;;   - category :: option
-;;   - type :: list of strings
-;;
-;; + `:export-options' :: List of export options available for current
-;;      process.
-;;   - category :: none
-;;   - type :: list of symbols, among `subtree', `body-only' and
-;;      `visible-only'.
-;;
-;; + `:exported-data' :: Hash table used for memoizing
-;;     `org-export-data'.
-;;   - category :: tree
-;;   - type :: hash table
-;;
-;; + `:filetags' :: List of global tags for buffer.  Used by
-;;   `org-export-get-tags' to get tags with inheritance.
-;;   - category :: option
-;;   - type :: list of strings
-;;
-;; + `:footnote-definition-alist' :: Alist between footnote labels and
-;;      their definition, as parsed data.  Only non-inlined footnotes
-;;      are represented in this alist.  Also, every definition isn't
-;;      guaranteed to be referenced in the parse tree.  The purpose of
-;;      this property is to preserve definitions from oblivion
-;;      (i.e. when the parse tree comes from a part of the original
-;;      buffer), it isn't meant for direct use in a back-end.  To
-;;      retrieve a definition relative to a reference, use
-;;      `org-export-get-footnote-definition' instead.
-;;   - category :: option
-;;   - type :: alist (STRING . LIST)
-;;
-;; + `:headline-levels' :: Maximum level being exported as an
-;;      headline.  Comparison is done with the relative level of
-;;      headlines in the parse tree, not necessarily with their
-;;      actual level.
-;;   - category :: option
-;;   - type :: integer
-;;
-;; + `:headline-offset' :: Difference between relative and real level
-;;      of headlines in the parse tree.  For example, a value of -1
-;;      means a level 2 headline should be considered as level
-;;      1 (cf. `org-export-get-relative-level').
-;;   - category :: tree
-;;   - type :: integer
-;;
-;; + `:headline-numbering' :: Alist between headlines and their
-;;      numbering, as a list of numbers
-;;      (cf. `org-export-get-headline-number').
-;;   - category :: tree
-;;   - type :: alist (INTEGER . LIST)
-;;
-;; + `:id-alist' :: Alist between ID strings and destination file's
-;;      path, relative to current directory.  It is used by
-;;      `org-export-resolve-id-link' to resolve ID links targeting an
-;;      external file.
-;;   - category :: option
-;;   - type :: alist (STRING . STRING)
-;;
-;; + `:ignore-list' :: List of elements and objects that should be
-;;      ignored during export.
-;;   - category :: tree
-;;   - type :: list of elements and objects
-;;
-;; + `:input-buffer' :: Name of input buffer.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:input-file' :: Full path to input file, if any.
-;;   - category :: option
-;;   - type :: string or nil
-;;
-;; + `:keywords' :: List of keywords attached to data.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:language' :: Default language used for translations.
-;;   - category :: option
-;;   - type :: string
-;;
-;; + `:output-file' :: Full path to output file, if any.
-;;   - category :: option
-;;   - type :: string or nil
-;;
-;; + `:parse-tree' :: Whole parse tree, available at any time during
-;;      transcoding.
-;;   - category :: option
-;;   - type :: list (as returned by `org-element-parse-buffer')
-;;
-;; + `:preserve-breaks' :: Non-nil means transcoding should preserve
-;;      all line breaks.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:section-numbers' :: Non-nil means transcoding should add
-;;      section numbers to headlines.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:select-tags' :: List of tags enforcing inclusion of sub-trees
-;;      in transcoding.  When such a tag is present, subtrees without
-;;      it are de facto excluded from the process.  See
-;;      `use-select-tags'.
-;;   - category :: option
-;;   - type :: list of strings
-;;
-;; + `:time-stamp-file' :: Non-nil means transcoding should insert
-;;      a time stamp in the output.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:translate-alist' :: Alist between element and object types and
-;;      transcoding functions relative to the current back-end.
-;;      Special keys `inner-template', `template' and `plain-text' are
-;;      also possible.
-;;   - category :: option
-;;   - type :: alist (SYMBOL . FUNCTION)
-;;
-;; + `:with-archived-trees' :: Non-nil when archived subtrees should
-;;      also be transcoded.  If it is set to the `headline' symbol,
-;;      only the archived headline's name is retained.
-;;   - category :: option
-;;   - type :: symbol (nil, t, `headline')
-;;
-;; + `:with-author' :: Non-nil means author's name should be included
-;;      in the output.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-clocks' :: Non-nil means clock keywords should be exported.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-creator' :: Non-nil means a creation sentence should be
-;;      inserted at the end of the transcoded string.  If the value
-;;      is `comment', it should be commented.
-;;   - category :: option
-;;   - type :: symbol (`comment', nil, t)
-;;
-;; + `:with-date' :: Non-nil means output should contain a date.
-;;   - category :: option
-;;   - type :. symbol (nil, t)
-;;
-;; + `:with-drawers' :: Non-nil means drawers should be exported.  If
-;;      its value is a list of names, only drawers with such names
-;;      will be transcoded.  If that list starts with `not', drawer
-;;      with these names will be skipped.
-;;   - category :: option
-;;   - type :: symbol (nil, t) or list of strings
-;;
-;; + `:with-email' :: Non-nil means output should contain author's
-;;                   email.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-emphasize' :: Non-nil means emphasized text should be
-;;      interpreted.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-fixed-width' :: Non-nil if transcoder should interpret
-;;      strings starting with a colon as a fixed-with (verbatim) area.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-footnotes' :: Non-nil if transcoder should interpret
-;;      footnotes.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-latex' :: Non-nil means `latex-environment' elements and
-;;    `latex-fragment' objects should appear in export output.  When
-;;    this property is set to `verbatim', they will be left as-is.
-;;   - category :: option
-;;   - type :: symbol (`verbatim', nil, t)
-;;
-;; + `:with-planning' :: Non-nil means transcoding should include
-;;      planning info.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-priority' :: Non-nil means transcoding should include
-;;      priority cookies.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-smart-quotes' :: Non-nil means activate smart quotes in
-;;      plain text.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-special-strings' :: Non-nil means transcoding should
-;;      interpret special strings in plain text.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-sub-superscript' :: Non-nil means transcoding should
-;;      interpret subscript and superscript.  With a value of "{}",
-;;      only interpret those using curly brackets.
-;;   - category :: option
-;;   - type :: symbol (nil, {}, t)
-;;
-;; + `:with-tables' :: Non-nil means transcoding should interpret
-;;      tables.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-;;
-;; + `:with-tags' :: Non-nil means transcoding should keep tags in
-;;      headlines.  A `not-in-toc' value will remove them from the
-;;      table of contents, if any, nonetheless.
-;;   - category :: option
-;;   - type :: symbol (nil, t, `not-in-toc')
-;;
-;; + `:with-tasks' :: Non-nil means transcoding should include
-;;      headlines with a TODO keyword.  A `todo' value will only
-;;      include headlines with a todo type keyword while a `done'
-;;      value will do the contrary.  If a list of strings is provided,
-;;      only tasks with keywords belonging to that list will be kept.
-;;   - category :: option
-;;   - type :: symbol (t, todo, done, nil) or list of strings
-;;
-;; + `:with-timestamps' :: Non-nil means transcoding should include
-;;      time stamps.  Special value `active' (resp. `inactive') ask to
-;;      export only active (resp. inactive) timestamps.  Otherwise,
-;;      completely remove them.
-;;   - category :: option
-;;   - type :: symbol: (`active', `inactive', t, nil)
-;;
-;; + `:with-toc' :: Non-nil means that a table of contents has to be
-;;      added to the output.  An integer value limits its depth.
-;;   - category :: option
-;;   - type :: symbol (nil, t or integer)
-;;
-;; + `:with-todo-keywords' :: Non-nil means transcoding should
-;;      include TODO keywords.
-;;   - category :: option
-;;   - type :: symbol (nil, t)
-
+;;    just before export, by `org-export--collect-tree-properties'.
 
 ;;;; Environment Options
 ;;
@@ -1520,6 +1333,7 @@ The back-end could then be called with, for example:
 ;; along with their value in order to set them as buffer local
 ;; variables later in the process.
 
+;;;###autoload
 (defun org-export-get-environment (&optional backend subtreep ext-plist)
   "Collect export options from the current buffer.
 
@@ -1535,7 +1349,7 @@ inferior to file-local settings."
   ;; First install #+BIND variables since these must be set before
   ;; global options are read.
   (dolist (pair (org-export--list-bound-variables))
-    (org-set-local (car pair) (nth 1 pair)))
+    (set (make-local-variable (car pair)) (nth 1 pair)))
   ;; Get and prioritize export options...
   (org-combine-plists
    ;; ... from global variables...
@@ -1545,69 +1359,31 @@ inferior to file-local settings."
    ;; ... from in-buffer settings...
    (org-export--get-inbuffer-options backend)
    ;; ... and from subtree, when appropriate.
-   (and subtreep (org-export--get-subtree-options backend))
-   ;; Eventually add misc. properties.
-   (list
-    :back-end
-    backend
-    :translate-alist (org-export-get-all-transcoders backend)
-    :footnote-definition-alist
-    ;; Footnotes definitions must be collected in the original
-    ;; buffer, as there's no insurance that they will still be in
-    ;; the parse tree, due to possible narrowing.
-    (let (alist)
-      (org-with-wide-buffer
-       (goto-char (point-min))
-       (while (re-search-forward org-footnote-definition-re nil t)
-        (let ((def (save-match-data (org-element-at-point))))
-          (when (eq (org-element-type def) 'footnote-definition)
-            (push
-             (cons (org-element-property :label def)
-                   (let ((cbeg (org-element-property :contents-begin def)))
-                     (when cbeg
-                       (org-element--parse-elements
-                        cbeg (org-element-property :contents-end def)
-                        nil nil nil nil (list 'org-data nil)))))
-             alist))))
-       alist))
-    :id-alist
-    ;; Collect id references.
-    (let (alist)
-      (org-with-wide-buffer
-       (goto-char (point-min))
-       (while (re-search-forward "\\[\\[id:\\S-+?\\]" nil t)
-        (let ((link (org-element-context)))
-          (when (eq (org-element-type link) 'link)
-            (let* ((id (org-element-property :path link))
-                   (file (org-id-find-id-file id)))
-              (when file
-                (push (cons id (file-relative-name file)) alist)))))))
-      alist))))
+   (and subtreep (org-export--get-subtree-options backend))))
 
 (defun org-export--parse-option-keyword (options &optional backend)
   "Parse an OPTIONS line and return values as a plist.
 Optional argument BACKEND is an export back-end, as returned by,
 e.g., `org-export-create-backend'.  It specifies which back-end
 specific items to read, if any."
-  (let* ((all
-         ;; Priority is given to back-end specific options.
-         (append (and backend (org-export-get-all-options backend))
-                 org-export-options-alist))
-        plist)
-    (dolist (option all)
-      (let ((property (car option))
-           (item (nth 2 option)))
-       (when (and item
-                  (not (plist-member plist property))
-                  (string-match (concat "\\(\\`\\|[ \t]\\)"
-                                        (regexp-quote item)
-                                        ":\\(([^)\n]+)\\|[^ \t\n\r;,.]*\\)")
-                                options))
-         (setq plist (plist-put plist
-                                property
-                                (car (read-from-string
-                                      (match-string 2 options))))))))
-    plist))
+  (let ((line
+        (let ((s 0) alist)
+          (while (string-match "\\(.+?\\):\\((.*?)\\|\\S-*\\)[ \t]*" options s)
+            (setq s (match-end 0))
+            (push (cons (match-string 1 options)
+                        (read (match-string 2 options)))
+                  alist))
+          alist))
+       ;; Priority is given to back-end specific options.
+       (all (append (org-export-get-all-options backend)
+                    org-export-options-alist))
+       (plist))
+    (when line
+      (dolist (entry all plist)
+       (let ((item (nth 2 entry)))
+         (when item
+           (let ((v (assoc-string item line t)))
+             (when v (setq plist (plist-put plist (car entry) (cdr v)))))))))))
 
 (defun org-export--get-subtree-options (&optional backend)
   "Get export options in subtree at point.
@@ -1615,60 +1391,50 @@ Optional argument BACKEND is an export back-end, as 
returned by,
 e.g., `org-export-create-backend'.  It specifies back-end used
 for export.  Return options as a plist."
   ;; For each buffer keyword, create a headline property setting the
-  ;; same property in communication channel. The name for the property
-  ;; is the keyword with "EXPORT_" appended to it.
+  ;; same property in communication channel.  The name for the
+  ;; property is the keyword with "EXPORT_" appended to it.
   (org-with-wide-buffer
-   (let (prop plist)
-     ;; Make sure point is at a heading.
-     (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t))
-     ;; Take care of EXPORT_TITLE. If it isn't defined, use headline's
-     ;; title (with no todo keyword, priority cookie or tag) as its
-     ;; fallback value.
-     (when (setq prop (or (org-entry-get (point) "EXPORT_TITLE")
-                         (progn (looking-at org-complex-heading-regexp)
-                                (org-match-string-no-properties 4))))
-       (setq plist
-            (plist-put
-             plist :title
-             (org-element-parse-secondary-string
-              prop (org-element-restriction 'keyword)))))
-     ;; EXPORT_OPTIONS are parsed in a non-standard way.
-     (when (setq prop (org-entry-get (point) "EXPORT_OPTIONS"))
-       (setq plist
-            (nconc plist (org-export--parse-option-keyword prop backend))))
-     ;; Handle other keywords.  TITLE keyword is excluded as it has
-     ;; been handled already.
-     (let ((seen '("TITLE")))
-       (mapc
-       (lambda (option)
-         (let ((property (car option))
-               (keyword (nth 1 option)))
-           (when (and keyword (not (member keyword seen)))
-             (let* ((subtree-prop (concat "EXPORT_" keyword))
-                    ;; Export properties are not case-sensitive.
-                    (value (let ((case-fold-search t))
-                             (org-entry-get (point) subtree-prop))))
-               (push keyword seen)
-               (when (and value (not (plist-member plist property)))
-                 (setq plist
-                       (plist-put
-                        plist
-                        property
-                        (cond
-                         ;; Parse VALUE if required.
-                         ((member keyword org-element-document-properties)
-                          (org-element-parse-secondary-string
-                           value (org-element-restriction 'keyword)))
-                         ;; If BEHAVIOR is `split' expected value is
-                         ;; a list of strings, not a string.
-                         ((eq (nth 4 option) 'split) (org-split-string value))
-                         (t value)))))))))
-       ;; Look for both general keywords and back-end specific
-       ;; options, with priority given to the latter.
-       (append (and backend (org-export-get-all-options backend))
-               org-export-options-alist)))
-     ;; Return value.
-     plist)))
+   ;; Make sure point is at a heading.
+   (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t))
+   (let ((plist
+         ;; EXPORT_OPTIONS are parsed in a non-standard way.  Take
+         ;; care of them right from the start.
+         (let ((o (org-entry-get (point) "EXPORT_OPTIONS" 'selective)))
+           (and o (org-export--parse-option-keyword o backend))))
+        ;; Take care of EXPORT_TITLE.  If it isn't defined, use
+        ;; headline's title (with no todo keyword, priority cookie or
+        ;; tag) as its fallback value.
+        (cache (list
+                (cons "TITLE"
+                      (or (org-entry-get (point) "EXPORT_TITLE" 'selective)
+                          (let ((case-fold-search nil))
+                            (looking-at org-complex-heading-regexp)
+                            (match-string-no-properties 4))))))
+        ;; Look for both general keywords and back-end specific
+        ;; options, with priority given to the latter.
+        (options (append (org-export-get-all-options backend)
+                         org-export-options-alist)))
+     ;; Handle other keywords.  Then return PLIST.
+     (dolist (option options plist)
+       (let ((property (car option))
+            (keyword (nth 1 option)))
+        (when keyword
+          (let ((value
+                 (or (cdr (assoc keyword cache))
+                     (let ((v (org-entry-get (point)
+                                             (concat "EXPORT_" keyword)
+                                             'selective)))
+                       (push (cons keyword v) cache) v))))
+            (when value
+              (setq plist
+                    (plist-put plist
+                               property
+                               (cl-case (nth 4 option)
+                                 (parse
+                                  (org-element-parse-secondary-string
+                                   value (org-element-restriction 'keyword)))
+                                 (split (org-split-string value))
+                                 (t value))))))))))))
 
 (defun org-export--get-inbuffer-options (&optional backend)
   "Return current buffer export options, as a plist.
@@ -1679,113 +1445,137 @@ which back-end specific options should also be read 
in the
 process.
 
 Assume buffer is in Org mode.  Narrowing, if any, is ignored."
-  (let* (plist
-        get-options                    ; For byte-compiler.
-        (case-fold-search t)
+  (let* ((case-fold-search t)
         (options (append
                   ;; Priority is given to back-end specific options.
-                  (and backend (org-export-get-all-options backend))
+                  (org-export-get-all-options backend)
                   org-export-options-alist))
         (regexp (format "^[ \t]*#\\+%s:"
-                        (regexp-opt (nconc (delq nil (mapcar 'cadr options))
+                        (regexp-opt (nconc (delq nil (mapcar #'cadr options))
                                            org-export-special-keywords))))
-        (find-properties
-         (lambda (keyword)
-           ;; Return all properties associated to KEYWORD.
-           (let (properties)
-             (dolist (option options properties)
-               (when (equal (nth 1 option) keyword)
-                 (pushnew (car option) properties))))))
-        (get-options
-         (lambda (&optional files plist)
-           ;; Recursively read keywords in buffer.  FILES is a list
-           ;; of files read so far.  PLIST is the current property
-           ;; list obtained.
-           (org-with-wide-buffer
-            (goto-char (point-min))
-            (while (re-search-forward regexp nil t)
-              (let ((element (org-element-at-point)))
-                (when (eq (org-element-type element) 'keyword)
-                  (let ((key (org-element-property :key element))
-                        (val (org-element-property :value element)))
-                    (cond
-                     ;; Options in `org-export-special-keywords'.
-                     ((equal key "SETUPFILE")
-                      (let ((file (expand-file-name
-                                   (org-remove-double-quotes (org-trim val)))))
-                        ;; Avoid circular dependencies.
-                        (unless (member file files)
-                          (with-temp-buffer
-                            (insert (org-file-contents file 'noerror))
-                            (let ((org-inhibit-startup t)) (org-mode))
-                            (setq plist (funcall get-options
-                                                 (cons file files) plist))))))
-                     ((equal key "OPTIONS")
-                      (setq plist
-                            (org-combine-plists
-                             plist
-                             (org-export--parse-option-keyword val backend))))
-                     ((equal key "FILETAGS")
-                      (setq plist
-                            (org-combine-plists
-                             plist
-                             (list :filetags
-                                   (org-uniquify
-                                    (append (org-split-string val ":")
-                                            (plist-get plist :filetags)))))))
-                     (t
-                      ;; Options in `org-export-options-alist'.
-                      (dolist (property (funcall find-properties key))
-                        (let ((behavior (nth 4 (assq property options))))
+        plist to-parse)
+    (letrec ((find-properties
+             (lambda (keyword)
+               ;; Return all properties associated to KEYWORD.
+               (let (properties)
+                 (dolist (option options properties)
+                   (when (equal (nth 1 option) keyword)
+                     (cl-pushnew (car option) properties))))))
+            (get-options
+             (lambda (&optional files)
+               ;; Recursively read keywords in buffer.  FILES is
+               ;; a list of files read so far.  PLIST is the current
+               ;; property list obtained.
+               (org-with-wide-buffer
+                (goto-char (point-min))
+                (while (re-search-forward regexp nil t)
+                  (let ((element (org-element-at-point)))
+                    (when (eq (org-element-type element) 'keyword)
+                      (let ((key (org-element-property :key element))
+                            (val (org-element-property :value element)))
+                        (cond
+                         ;; Options in `org-export-special-keywords'.
+                         ((equal key "SETUPFILE")
+                          (let ((file
+                                 (expand-file-name
+                                  (org-unbracket-string "\"" "\"" (org-trim 
val)))))
+                            ;; Avoid circular dependencies.
+                            (unless (member file files)
+                              (with-temp-buffer
+                                (setq default-directory
+                                  (file-name-directory file))
+                                (insert (org-file-contents file 'noerror))
+                                (let ((org-inhibit-startup t)) (org-mode))
+                                (funcall get-options (cons file files))))))
+                         ((equal key "OPTIONS")
                           (setq plist
-                                (plist-put
-                                 plist property
-                                 ;; Handle value depending on specified
-                                 ;; BEHAVIOR.
-                                 (case behavior
-                                   (space
-                                    (if (not (plist-get plist property))
-                                        (org-trim val)
-                                      (concat (plist-get plist property)
-                                              " "
-                                              (org-trim val))))
-                                   (newline
-                                    (org-trim
-                                     (concat (plist-get plist property)
-                                             "\n"
-                                             (org-trim val))))
-                                   (split `(,@(plist-get plist property)
-                                            ,@(org-split-string val)))
-                                   ('t val)
-                                   (otherwise
-                                    (if (not (plist-member plist property)) val
-                                      (plist-get plist property))))))))))))))
-            ;; Return final value.
-            plist))))
-    ;; Read options in the current buffer.
-    (setq plist (funcall get-options
-                        (and buffer-file-name (list buffer-file-name)) nil))
-    ;; Parse keywords specified in `org-element-document-properties'
-    ;; and return PLIST.
-    (dolist (keyword org-element-document-properties plist)
-      (dolist (property (funcall find-properties keyword))
-       (let ((value (plist-get plist property)))
-         (when (stringp value)
-           (setq plist
-                 (plist-put plist property
-                            (or (org-element-parse-secondary-string
-                                 value (org-element-restriction 'keyword))
-                                ;; When TITLE keyword sets an empty
-                                ;; string, make sure it doesn't
-                                ;; appear as nil in the plist.
-                                (and (eq property :title) ""))))))))))
+                                (org-combine-plists
+                                 plist
+                                 (org-export--parse-option-keyword
+                                  val backend))))
+                         ((equal key "FILETAGS")
+                          (setq plist
+                                (org-combine-plists
+                                 plist
+                                 (list :filetags
+                                       (org-uniquify
+                                        (append
+                                         (org-split-string val ":")
+                                         (plist-get plist :filetags)))))))
+                         (t
+                          ;; Options in `org-export-options-alist'.
+                          (dolist (property (funcall find-properties key))
+                            (setq
+                             plist
+                             (plist-put
+                              plist property
+                              ;; Handle value depending on specified
+                              ;; BEHAVIOR.
+                              (cl-case (nth 4 (assq property options))
+                                (parse
+                                 (unless (memq property to-parse)
+                                   (push property to-parse))
+                                 ;; Even if `parse' implies `space'
+                                 ;; behavior, we separate line with
+                                 ;; "\n" so as to preserve
+                                 ;; line-breaks.  However, empty
+                                 ;; lines are forbidden since `parse'
+                                 ;; doesn't allow more than one
+                                 ;; paragraph.
+                                 (let ((old (plist-get plist property)))
+                                   (cond ((not (org-string-nw-p val)) old)
+                                         (old (concat old "\n" val))
+                                         (t val))))
+                                (space
+                                 (if (not (plist-get plist property))
+                                     (org-trim val)
+                                   (concat (plist-get plist property)
+                                           " "
+                                           (org-trim val))))
+                                (newline
+                                 (org-trim
+                                  (concat (plist-get plist property)
+                                          "\n"
+                                          (org-trim val))))
+                                (split `(,@(plist-get plist property)
+                                         ,@(org-split-string val)))
+                                ((t) val)
+                                (otherwise
+                                 (if (not (plist-member plist property)) val
+                                   (plist-get plist property)))))))))))))))))
+      ;; Read options in the current buffer and return value.
+      (funcall get-options (and buffer-file-name (list buffer-file-name)))
+      ;; Parse properties in TO-PARSE.  Remove newline characters not
+      ;; involved in line breaks to simulate `space' behavior.
+      ;; Finally return options.
+      (dolist (p to-parse plist)
+       (let ((value (org-element-parse-secondary-string
+                     (plist-get plist p)
+                     (org-element-restriction 'keyword))))
+         (org-element-map value 'plain-text
+           (lambda (s)
+             (org-element-set-element
+              s (replace-regexp-in-string "\n" " " s))))
+         (setq plist (plist-put plist p value)))))))
+
+(defun org-export--get-export-attributes
+    (&optional backend subtreep visible-only body-only)
+  "Return properties related to export process, as a plist.
+Optional arguments BACKEND, SUBTREEP, VISIBLE-ONLY and BODY-ONLY
+are like the arguments with the same names of function
+`org-export-as'."
+  (list :export-options (delq nil
+                             (list (and subtreep 'subtree)
+                                   (and visible-only 'visible-only)
+                                   (and body-only 'body-only)))
+       :back-end backend
+       :translate-alist (org-export-get-all-transcoders backend)
+       :exported-data (make-hash-table :test #'eq :size 4001)))
 
 (defun org-export--get-buffer-attributes ()
   "Return properties related to buffer attributes, as a plist."
-  ;; Store full path of input file name, or nil.  For internal use.
-  (let ((visited-file (buffer-file-name (buffer-base-buffer))))
-    (list :input-file visited-file
-         :input-buffer (buffer-name (buffer-base-buffer)))))
+  (list :input-buffer (buffer-name (buffer-base-buffer))
+       :input-file (buffer-file-name (buffer-base-buffer))))
 
 (defun org-export--get-global-options (&optional backend)
   "Return global export options as a plist.
@@ -1795,7 +1585,7 @@ which back-end specific export options should also be 
read in the
 process."
   (let (plist
        ;; Priority is given to back-end specific options.
-       (all (append (and backend (org-export-get-all-options backend))
+       (all (append (org-export-get-all-options backend)
                     org-export-options-alist)))
     (dolist (cell all plist)
       (let ((prop (car cell)))
@@ -1804,13 +1594,9 @@ process."
                (plist-put
                 plist
                 prop
-                ;; Evaluate default value provided.  If keyword is
-                ;; a member of `org-element-document-properties',
-                ;; parse it as a secondary string before storing it.
+                ;; Evaluate default value provided.
                 (let ((value (eval (nth 3 cell))))
-                  (if (and (stringp value)
-                           (member (nth 1 cell)
-                                   org-element-document-properties))
+                  (if (eq (nth 4 cell) 'parse)
                       (org-element-parse-secondary-string
                        value (org-element-restriction 'keyword))
                     value)))))))))
@@ -1820,35 +1606,37 @@ process."
 Also look for BIND keywords in setup files.  The return value is
 an alist where associations are (VARIABLE-NAME VALUE)."
   (when org-export-allow-bind-keywords
-    (let* (collect-bind                        ; For byte-compiler.
-          (collect-bind
-           (lambda (files alist)
-             ;; Return an alist between variable names and their
-             ;; value.  FILES is a list of setup files names read so
-             ;; far, used to avoid circular dependencies.  ALIST is
-             ;; the alist collected so far.
-             (let ((case-fold-search t))
-               (org-with-wide-buffer
-                (goto-char (point-min))
-                (while (re-search-forward
-                        "^[ \t]*#\\+\\(BIND\\|SETUPFILE\\):" nil t)
-                  (let ((element (org-element-at-point)))
-                    (when (eq (org-element-type element) 'keyword)
-                      (let ((val (org-element-property :value element)))
-                        (if (equal (org-element-property :key element) "BIND")
-                            (push (read (format "(%s)" val)) alist)
-                          ;; Enter setup file.
-                          (let ((file (expand-file-name
-                                       (org-remove-double-quotes val))))
-                            (unless (member file files)
-                              (with-temp-buffer
-                                (let ((org-inhibit-startup t)) (org-mode))
-                                (insert (org-file-contents file 'noerror))
-                                (setq alist
-                                      (funcall collect-bind
-                                               (cons file files)
-                                               alist))))))))))
-                alist)))))
+    (letrec ((collect-bind
+             (lambda (files alist)
+               ;; Return an alist between variable names and their
+               ;; value.  FILES is a list of setup files names read
+               ;; so far, used to avoid circular dependencies.  ALIST
+               ;; is the alist collected so far.
+               (let ((case-fold-search t))
+                 (org-with-wide-buffer
+                  (goto-char (point-min))
+                  (while (re-search-forward
+                          "^[ \t]*#\\+\\(BIND\\|SETUPFILE\\):" nil t)
+                    (let ((element (org-element-at-point)))
+                      (when (eq (org-element-type element) 'keyword)
+                        (let ((val (org-element-property :value element)))
+                          (if (equal (org-element-property :key element)
+                                     "BIND")
+                              (push (read (format "(%s)" val)) alist)
+                            ;; Enter setup file.
+                            (let ((file (expand-file-name
+                                         (org-unbracket-string "\"" "\"" 
val))))
+                              (unless (member file files)
+                                (with-temp-buffer
+                                  (setq default-directory
+                                        (file-name-directory file))
+                                  (let ((org-inhibit-startup t)) (org-mode))
+                                  (insert (org-file-contents file 'noerror))
+                                  (setq alist
+                                        (funcall collect-bind
+                                                 (cons file files)
+                                                 alist))))))))))
+                  alist)))))
       ;; Return value in appropriate order of appearance.
       (nreverse (funcall collect-bind nil nil)))))
 
@@ -1864,7 +1652,7 @@ BLOB is the element or object considered."
 ;;
 ;; Tree properties are information extracted from parse tree.  They
 ;; are initialized at the beginning of the transcoding process by
-;; `org-export-collect-tree-properties'.
+;; `org-export--collect-tree-properties'.
 ;;
 ;; Dedicated functions focus on computing the value of specific tree
 ;; properties during initialization.  Thus,
@@ -1875,7 +1663,7 @@ BLOB is the element or object considered."
 ;; `org-export--collect-headline-numbering' builds an alist between
 ;; headlines and their numbering.
 
-(defun org-export-collect-tree-properties (data info)
+(defun org-export--collect-tree-properties (data info)
   "Extract tree properties from parse tree.
 
 DATA is the parse tree from which information is retrieved.  INFO
@@ -1883,59 +1671,38 @@ is a list holding export options.
 
 Following tree properties are set or updated:
 
-`:exported-data' Hash table used to memoize results from
-                 `org-export-data'.
-
-`:footnote-definition-alist' List of footnotes definitions in
-                   original buffer and current parse tree.
-
 `:headline-offset' Offset between true level of headlines and
                   local level.  An offset of -1 means a headline
                   of level 2 should be considered as a level
                   1 headline in the context.
 
-`:headline-numbering' Alist of all headlines as key an the
+`:headline-numbering' Alist of all headlines as key and the
                      associated numbering as value.
 
-`:ignore-list'     List of elements that should be ignored during
-                   export.
+`:id-alist' Alist of all ID references as key and associated file
+            as value.
 
 Return updated plist."
-  ;; Install the parse tree in the communication channel, in order to
-  ;; use `org-export-get-genealogy' and al.
+  ;; Install the parse tree in the communication channel.
   (setq info (plist-put info :parse-tree data))
-  ;; Get the list of elements and objects to ignore, and put it into
-  ;; `:ignore-list'.  Do not overwrite any user ignore that might have
-  ;; been done during parse tree filtering.
-  (setq info
-       (plist-put info
-                  :ignore-list
-                  (append (org-export--populate-ignore-list data info)
-                          (plist-get info :ignore-list))))
   ;; Compute `:headline-offset' in order to be able to use
   ;; `org-export-get-relative-level'.
   (setq info
        (plist-put info
                   :headline-offset
                   (- 1 (org-export--get-min-level data info))))
-  ;; Update footnotes definitions list with definitions in parse tree.
-  ;; This is required since buffer expansion might have modified
-  ;; boundaries of footnote definitions contained in the parse tree.
-  ;; This way, definitions in `footnote-definition-alist' are bound to
-  ;; match those in the parse tree.
-  (let ((defs (plist-get info :footnote-definition-alist)))
-    (org-element-map data 'footnote-definition
-      (lambda (fn)
-       (push (cons (org-element-property :label fn)
-                   `(org-data nil ,@(org-element-contents fn)))
-             defs)))
-    (setq info (plist-put info :footnote-definition-alist defs)))
-  ;; Properties order doesn't matter: get the rest of the tree
-  ;; properties.
-  (nconc
-   `(:headline-numbering ,(org-export--collect-headline-numbering data info)
-     :exported-data ,(make-hash-table :test 'eq :size 4001))
-   info))
+  ;; From now on, properties order doesn't matter: get the rest of the
+  ;; tree properties.
+  (org-combine-plists
+   info
+   (list :headline-numbering (org-export--collect-headline-numbering data info)
+        :id-alist
+        (org-element-map data 'link
+          (lambda (l)
+            (and (string= (org-element-property :type l) "id")
+                 (let* ((id (org-element-property :path l))
+                        (file (car (org-id-find id))))
+                   (and file (cons id (file-relative-name file))))))))))
 
 (defun org-export--get-min-level (data options)
   "Return minimum exportable headline's level in DATA.
@@ -1943,20 +1710,18 @@ DATA is parsed tree as returned by 
`org-element-parse-buffer'.
 OPTIONS is a plist holding export options."
   (catch 'exit
     (let ((min-level 10000))
-      (mapc
-       (lambda (blob)
-        (when (and (eq (org-element-type blob) 'headline)
-                   (not (org-element-property :footnote-section-p blob))
-                   (not (memq blob (plist-get options :ignore-list))))
-          (setq min-level (min (org-element-property :level blob) min-level)))
-        (when (= min-level 1) (throw 'exit 1)))
-       (org-element-contents data))
+      (dolist (datum (org-element-contents data))
+       (when (and (eq (org-element-type datum) 'headline)
+                  (not (org-element-property :footnote-section-p datum))
+                  (not (memq datum (plist-get options :ignore-list))))
+         (setq min-level (min (org-element-property :level datum) min-level))
+         (when (= min-level 1) (throw 'exit 1))))
       ;; If no headline was found, for the sake of consistency, set
       ;; minimum level to 1 nonetheless.
       (if (= min-level 10000) 1 min-level))))
 
 (defun org-export--collect-headline-numbering (data options)
-  "Return numbering of all exportable headlines in a parse tree.
+  "Return numbering of all exportable, numbered headlines in a parse tree.
 
 DATA is the parse tree.  OPTIONS is the plist holding export
 options.
@@ -1967,93 +1732,75 @@ for a footnotes section."
   (let ((numbering (make-vector org-export-max-depth 0)))
     (org-element-map data 'headline
       (lambda (headline)
-       (unless (org-element-property :footnote-section-p headline)
+       (when (and (org-export-numbered-headline-p headline options)
+                  (not (org-element-property :footnote-section-p headline)))
          (let ((relative-level
                 (1- (org-export-get-relative-level headline options))))
            (cons
             headline
-            (loop for n across numbering
-                  for idx from 0 to org-export-max-depth
-                  when (< idx relative-level) collect n
-                  when (= idx relative-level) collect (aset numbering idx (1+ 
n))
-                  when (> idx relative-level) do (aset numbering idx 0))))))
+            (cl-loop
+             for n across numbering
+             for idx from 0 to org-export-max-depth
+             when (< idx relative-level) collect n
+             when (= idx relative-level) collect (aset numbering idx (1+ n))
+             when (> idx relative-level) do (aset numbering idx 0))))))
       options)))
 
-(defun org-export--populate-ignore-list (data options)
-  "Return list of elements and objects to ignore during export.
-DATA is the parse tree to traverse.  OPTIONS is the plist holding
-export options."
-  (let* (ignore
-        walk-data
-        ;; First find trees containing a select tag, if any.
-        (selected (org-export--selected-trees data options))
-        (walk-data
-         (lambda (data)
-           ;; Collect ignored elements or objects into IGNORE-LIST.
-           (let ((type (org-element-type data)))
-             (if (org-export--skip-p data options selected) (push data ignore)
-               (if (and (eq type 'headline)
-                        (eq (plist-get options :with-archived-trees) 'headline)
-                        (org-element-property :archivedp data))
-                   ;; If headline is archived but tree below has
-                   ;; to be skipped, add it to ignore list.
-                   (mapc (lambda (e) (push e ignore))
-                         (org-element-contents data))
-                 ;; Move into secondary string, if any.
-                 (let ((sec-prop
-                        (cdr (assq type org-element-secondary-value-alist))))
-                   (when sec-prop
-                     (mapc walk-data (org-element-property sec-prop data))))
-                 ;; Move into recursive objects/elements.
-                 (mapc walk-data (org-element-contents data))))))))
-    ;; Main call.
-    (funcall walk-data data)
-    ;; Return value.
-    ignore))
-
 (defun org-export--selected-trees (data info)
-  "Return list of headlines and inlinetasks with a select tag in their tree.
+  "List headlines and inlinetasks with a select tag in their tree.
 DATA is parsed data as returned by `org-element-parse-buffer'.
 INFO is a plist holding export options."
-  (let* (selected-trees
-        walk-data                      ; For byte-compiler.
-        (walk-data
-         (function
-          (lambda (data genealogy)
-            (let ((type (org-element-type data)))
-              (cond
-               ((memq type '(headline inlinetask))
-                (let ((tags (org-element-property :tags data)))
-                  (if (loop for tag in (plist-get info :select-tags)
-                            thereis (member tag tags))
-                      ;; When a select tag is found, mark full
-                      ;; genealogy and every headline within the tree
-                      ;; as acceptable.
-                      (setq selected-trees
-                            (append
-                             genealogy
-                             (org-element-map data '(headline inlinetask)
-                               'identity)
-                             selected-trees))
-                    ;; If at a headline, continue searching in tree,
-                    ;; recursively.
-                    (when (eq type 'headline)
-                      (mapc (lambda (el)
-                              (funcall walk-data el (cons data genealogy)))
-                            (org-element-contents data))))))
-               ((or (eq type 'org-data)
-                    (memq type org-element-greater-elements))
-                (mapc (lambda (el) (funcall walk-data el genealogy))
-                      (org-element-contents data)))))))))
-    (funcall walk-data data nil)
-    selected-trees))
-
-(defun org-export--skip-p (blob options selected)
-  "Non-nil when element or object BLOB should be skipped during export.
+  (let ((select (plist-get info :select-tags)))
+    (if (cl-some (lambda (tag) (member tag select)) (plist-get info :filetags))
+       ;; If FILETAGS contains a select tag, every headline or
+       ;; inlinetask is returned.
+       (org-element-map data '(headline inlinetask) #'identity)
+      (letrec ((selected-trees nil)
+              (walk-data
+               (lambda (data genealogy)
+                 (let ((type (org-element-type data)))
+                   (cond
+                    ((memq type '(headline inlinetask))
+                     (let ((tags (org-element-property :tags data)))
+                       (if (cl-some (lambda (tag) (member tag select)) tags)
+                           ;; When a select tag is found, mark full
+                           ;; genealogy and every headline within the
+                           ;; tree as acceptable.
+                           (setq selected-trees
+                                 (append
+                                  genealogy
+                                  (org-element-map data '(headline inlinetask)
+                                    #'identity)
+                                  selected-trees))
+                         ;; If at a headline, continue searching in
+                         ;; tree, recursively.
+                         (when (eq type 'headline)
+                           (dolist (el (org-element-contents data))
+                             (funcall walk-data el (cons data genealogy)))))))
+                    ((or (eq type 'org-data)
+                         (memq type org-element-greater-elements))
+                     (dolist (el (org-element-contents data))
+                       (funcall walk-data el genealogy))))))))
+       (funcall walk-data data nil)
+       selected-trees))))
+
+(defun org-export--skip-p (datum options selected)
+  "Non-nil when element or object DATUM should be skipped during export.
 OPTIONS is the plist holding export options.  SELECTED, when
 non-nil, is a list of headlines or inlinetasks belonging to
 a tree with a select tag."
-  (case (org-element-type blob)
+  (cl-case (org-element-type datum)
+    ((comment comment-block)
+     ;; Skip all comments and comment blocks.  Make to keep maximum
+     ;; number of blank lines around the comment so as to preserve
+     ;; local structure of the document upon interpreting it back into
+     ;; Org syntax.
+     (let* ((previous (org-export-get-previous-element datum options))
+           (before (or (org-element-property :post-blank previous) 0))
+           (after (or (org-element-property :post-blank datum) 0)))
+       (when previous
+        (org-element-put-property previous :post-blank (max before after 1))))
+     t)
     (clock (not (plist-get options :with-clocks)))
     (drawer
      (let ((with-drawers-p (plist-get options :with-drawers)))
@@ -2063,31 +1810,32 @@ a tree with a select tag."
                ;; every drawer whose name belong to that list.
                ;; Otherwise, ignore drawers whose name isn't in that
                ;; list.
-               (let ((name (org-element-property :drawer-name blob)))
+               (let ((name (org-element-property :drawer-name datum)))
                  (if (eq (car with-drawers-p) 'not)
                      (member-ignore-case name (cdr with-drawers-p))
                    (not (member-ignore-case name with-drawers-p))))))))
+    (fixed-width (not (plist-get options :with-fixed-width)))
     ((footnote-definition footnote-reference)
      (not (plist-get options :with-footnotes)))
     ((headline inlinetask)
      (let ((with-tasks (plist-get options :with-tasks))
-          (todo (org-element-property :todo-keyword blob))
-          (todo-type (org-element-property :todo-type blob))
+          (todo (org-element-property :todo-keyword datum))
+          (todo-type (org-element-property :todo-type datum))
           (archived (plist-get options :with-archived-trees))
-          (tags (org-element-property :tags blob)))
+          (tags (org-export-get-tags datum options nil t)))
        (or
-       (and (eq (org-element-type blob) 'inlinetask)
+       (and (eq (org-element-type datum) 'inlinetask)
             (not (plist-get options :with-inlinetasks)))
        ;; Ignore subtrees with an exclude tag.
-       (loop for k in (plist-get options :exclude-tags)
-             thereis (member k tags))
+       (cl-loop for k in (plist-get options :exclude-tags)
+                thereis (member k tags))
        ;; When a select tag is present in the buffer, ignore any tree
        ;; without it.
-       (and selected (not (memq blob selected)))
+       (and selected (not (memq datum selected)))
        ;; Ignore commented sub-trees.
-       (org-element-property :commentedp blob)
+       (org-element-property :commentedp datum)
        ;; Ignore archived subtrees if `:with-archived-trees' is nil.
-       (and (not archived) (org-element-property :archivedp blob))
+       (and (not archived) (org-element-property :archivedp datum))
        ;; Ignore tasks, if specified by `:with-tasks' property.
        (and todo
             (or (not with-tasks)
@@ -2095,18 +1843,26 @@ a tree with a select tag."
                      (not (eq todo-type with-tasks)))
                 (and (consp with-tasks) (not (member todo with-tasks))))))))
     ((latex-environment latex-fragment) (not (plist-get options :with-latex)))
+    (node-property
+     (let ((properties-set (plist-get options :with-properties)))
+       (cond ((null properties-set) t)
+            ((consp properties-set)
+             (not (member-ignore-case (org-element-property :key datum)
+                                      properties-set))))))
     (planning (not (plist-get options :with-planning)))
+    (property-drawer (not (plist-get options :with-properties)))
     (statistics-cookie (not (plist-get options :with-statistics-cookies)))
+    (table (not (plist-get options :with-tables)))
     (table-cell
      (and (org-export-table-has-special-column-p
-          (org-export-get-parent-table blob))
-         (not (org-export-get-previous-element blob options))))
-    (table-row (org-export-table-row-is-special-p blob options))
+          (org-export-get-parent-table datum))
+         (org-export-first-sibling-p datum options)))
+    (table-row (org-export-table-row-is-special-p datum options))
     (timestamp
      ;; `:with-timestamps' only applies to isolated timestamps
      ;; objects, i.e. timestamp objects in a paragraph containing only
      ;; timestamps and whitespaces.
-     (when (let ((parent (org-export-get-parent-element blob)))
+     (when (let ((parent (org-export-get-parent-element datum)))
             (and (memq (org-element-type parent) '(paragraph verse-block))
                  (not (org-element-map parent
                           (cons 'plain-text
@@ -2114,12 +1870,12 @@ a tree with a select tag."
                         (lambda (obj)
                           (or (not (stringp obj)) (org-string-nw-p obj)))
                         options t))))
-       (case (plist-get options :with-timestamps)
-        ('nil t)
+       (cl-case (plist-get options :with-timestamps)
+        ((nil) t)
         (active
-         (not (memq (org-element-property :type blob) '(active active-range))))
+         (not (memq (org-element-property :type datum) '(active 
active-range))))
         (inactive
-         (not (memq (org-element-property :type blob)
+         (not (memq (org-element-property :type datum)
                     '(inactive inactive-range)))))))))
 
 
@@ -2136,14 +1892,6 @@ a tree with a select tag."
 ;; `org-export-data' or even use a temporary back-end by using
 ;; `org-export-data-with-backend'.
 ;;
-;; Internally, three functions handle the filtering of objects and
-;; elements during the export.  In particular,
-;; `org-export-ignore-element' marks an element or object so future
-;; parse tree traversals skip it, `org-export--interpret-p' tells which
-;; elements or objects should be seen as real Org syntax and
-;; `org-export-expand' transforms the others back into their original
-;; shape
-;;
 ;; `org-export-transcoder' is an accessor returning appropriate
 ;; translator function for a given element or object.
 
@@ -2152,7 +1900,7 @@ a tree with a select tag."
 INFO is a plist containing export directives."
   (let ((type (org-element-type blob)))
     ;; Return contents only for complete parse trees.
-    (if (eq type 'org-data) (lambda (blob contents info) contents)
+    (if (eq type 'org-data) (lambda (_datum contents _info) contents)
       (let ((transcoder (cdr (assq type (plist-get info :translate-alist)))))
        (and (functionp transcoder) transcoder)))))
 
@@ -2164,101 +1912,103 @@ string.  INFO is a plist holding export options.
 
 Return a string."
   (or (gethash data (plist-get info :exported-data))
-      (let* ((type (org-element-type data))
-            (results
-             (cond
-              ;; Ignored element/object.
-              ((memq data (plist-get info :ignore-list)) nil)
-              ;; Plain text.
-              ((eq type 'plain-text)
-               (org-export-filter-apply-functions
-                (plist-get info :filter-plain-text)
-                (let ((transcoder (org-export-transcoder data info)))
-                  (if transcoder (funcall transcoder data info) data))
-                info))
-              ;; Uninterpreted element/object: change it back to Org
-              ;; syntax and export again resulting raw string.
-              ((not (org-export--interpret-p data info))
-               (org-export-data
-                (org-export-expand
-                 data
-                 (mapconcat (lambda (blob) (org-export-data blob info))
-                            (org-element-contents data)
-                            ""))
-                info))
-              ;; Secondary string.
-              ((not type)
-               (mapconcat (lambda (obj) (org-export-data obj info)) data ""))
-              ;; Element/Object without contents or, as a special
-              ;; case, headline with archive tag and archived trees
-              ;; restricted to title only.
-              ((or (not (org-element-contents data))
-                   (and (eq type 'headline)
-                        (eq (plist-get info :with-archived-trees) 'headline)
-                        (org-element-property :archivedp data)))
-               (let ((transcoder (org-export-transcoder data info)))
-                 (or (and (functionp transcoder)
-                          (funcall transcoder data nil info))
-                     ;; Export snippets never return a nil value so
-                     ;; that white spaces following them are never
-                     ;; ignored.
-                     (and (eq type 'export-snippet) ""))))
-              ;; Element/Object with contents.
-              (t
-               (let ((transcoder (org-export-transcoder data info)))
-                 (when transcoder
-                   (let* ((greaterp (memq type org-element-greater-elements))
-                          (objectp
-                           (and (not greaterp)
-                                (memq type org-element-recursive-objects)))
-                          (contents
-                           (mapconcat
-                            (lambda (element) (org-export-data element info))
-                            (org-element-contents
-                             (if (or greaterp objectp) data
-                               ;; Elements directly containing
-                               ;; objects must have their indentation
-                               ;; normalized first.
-                               (org-element-normalize-contents
-                                data
-                                ;; When normalizing contents of the
-                                ;; first paragraph in an item or
-                                ;; a footnote definition, ignore
-                                ;; first line's indentation: there is
-                                ;; none and it might be misleading.
-                                (when (eq type 'paragraph)
-                                  (let ((parent (org-export-get-parent data)))
+      ;; Handle broken links according to
+      ;; `org-export-with-broken-links'.
+      (cl-macrolet
+         ((broken-link-handler
+           (&rest body)
+           `(condition-case err
+                (progn ,@body)
+              (org-link-broken
+               (pcase (plist-get info :with-broken-links)
+                 (`nil (user-error "Unable to resolve link: %S" (nth 1 err)))
+                 (`mark (org-export-data
+                         (format "[BROKEN LINK: %s]" (nth 1 err)) info))
+                 (_ nil))))))
+       (let* ((type (org-element-type data))
+              (parent (org-export-get-parent data))
+              (results
+               (cond
+                ;; Ignored element/object.
+                ((memq data (plist-get info :ignore-list)) nil)
+                ;; Plain text.
+                ((eq type 'plain-text)
+                 (org-export-filter-apply-functions
+                  (plist-get info :filter-plain-text)
+                  (let ((transcoder (org-export-transcoder data info)))
+                    (if transcoder (funcall transcoder data info) data))
+                  info))
+                ;; Secondary string.
+                ((not type)
+                 (mapconcat (lambda (obj) (org-export-data obj info)) data ""))
+                ;; Element/Object without contents or, as a special
+                ;; case, headline with archive tag and archived trees
+                ;; restricted to title only.
+                ((or (not (org-element-contents data))
+                     (and (eq type 'headline)
+                          (eq (plist-get info :with-archived-trees) 'headline)
+                          (org-element-property :archivedp data)))
+                 (let ((transcoder (org-export-transcoder data info)))
+                   (or (and (functionp transcoder)
+                            (broken-link-handler
+                             (funcall transcoder data nil info)))
+                       ;; Export snippets never return a nil value so
+                       ;; that white spaces following them are never
+                       ;; ignored.
+                       (and (eq type 'export-snippet) ""))))
+                ;; Element/Object with contents.
+                (t
+                 (let ((transcoder (org-export-transcoder data info)))
+                   (when transcoder
+                     (let* ((greaterp (memq type org-element-greater-elements))
+                            (objectp
+                             (and (not greaterp)
+                                  (memq type org-element-recursive-objects)))
+                            (contents
+                             (mapconcat
+                              (lambda (element) (org-export-data element info))
+                              (org-element-contents
+                               (if (or greaterp objectp) data
+                                 ;; Elements directly containing
+                                 ;; objects must have their indentation
+                                 ;; normalized first.
+                                 (org-element-normalize-contents
+                                  data
+                                  ;; When normalizing contents of the
+                                  ;; first paragraph in an item or
+                                  ;; a footnote definition, ignore
+                                  ;; first line's indentation: there is
+                                  ;; none and it might be misleading.
+                                  (when (eq type 'paragraph)
                                     (and
                                      (eq (car (org-element-contents parent))
                                          data)
                                      (memq (org-element-type parent)
-                                           '(footnote-definition item))))))))
-                            "")))
-                     (funcall transcoder data
-                              (if (not greaterp) contents
-                                (org-element-normalize-string contents))
-                              info))))))))
-       ;; Final result will be memoized before being returned.
-       (puthash
-        data
-        (cond
-         ((not results) "")
-         ((memq type '(org-data plain-text nil)) results)
-         ;; Append the same white space between elements or objects
-         ;; as in the original buffer, and call appropriate filters.
-         (t
-          (let ((results
-                 (org-export-filter-apply-functions
-                  (plist-get info (intern (format ":filter-%s" type)))
-                  (let ((post-blank (or (org-element-property :post-blank data)
-                                        0)))
-                    (if (memq type org-element-all-elements)
-                        (concat (org-element-normalize-string results)
-                                (make-string post-blank ?\n))
-                      (concat results (make-string post-blank ?\s))))
-                  info)))
-            results)))
-        (plist-get info :exported-data)))))
+                                           '(footnote-definition item)))))))
+                              "")))
+                       (broken-link-handler
+                        (funcall transcoder data
+                                 (if (not greaterp) contents
+                                   (org-element-normalize-string contents))
+                                 info)))))))))
+         ;; Final result will be memoized before being returned.
+         (puthash
+          data
+          (cond
+           ((not results) "")
+           ((memq type '(org-data plain-text nil)) results)
+           ;; Append the same white space between elements or objects
+           ;; as in the original buffer, and call appropriate filters.
+           (t
+            (org-export-filter-apply-functions
+             (plist-get info (intern (format ":filter-%s" type)))
+             (let ((blank (or (org-element-property :post-blank data) 0)))
+               (if (eq (org-element-class data parent) 'object)
+                   (concat results (make-string blank ?\s))
+                 (concat (org-element-normalize-string results)
+                         (make-string blank ?\n))))
+             info)))
+          (plist-get info :exported-data))))))
 
 (defun org-export-data-with-backend (data backend info)
   "Convert DATA into BACKEND format.
@@ -2270,44 +2020,24 @@ channel.
 Unlike to `org-export-with-backend', this function will
 recursively convert DATA using BACKEND translation table."
   (when (symbolp backend) (setq backend (org-export-get-backend backend)))
-  (org-export-data
-   data
-   ;; Set-up a new communication channel with translations defined in
-   ;; BACKEND as the translate table and a new hash table for
-   ;; memoization.
-   (org-combine-plists
-    info
-    (list :back-end backend
-         :translate-alist (org-export-get-all-transcoders backend)
-         ;; Size of the hash table is reduced since this function
-         ;; will probably be used on small trees.
-         :exported-data (make-hash-table :test 'eq :size 401)))))
-
-(defun org-export--interpret-p (blob info)
-  "Non-nil if element or object BLOB should be interpreted during export.
-If nil, BLOB will appear as raw Org syntax.  Check is done
-according to export options INFO, stored as a plist."
-  (case (org-element-type blob)
-    ;; ... entities...
-    (entity (plist-get info :with-entities))
-    ;; ... emphasis...
-    ((bold italic strike-through underline)
-     (plist-get info :with-emphasize))
-    ;; ... fixed-width areas.
-    (fixed-width (plist-get info :with-fixed-width))
-    ;; ... LaTeX environments and fragments...
-    ((latex-environment latex-fragment)
-     (let ((with-latex-p (plist-get info :with-latex)))
-       (and with-latex-p (not (eq with-latex-p 'verbatim)))))
-    ;; ... sub/superscripts...
-    ((subscript superscript)
-     (let ((sub/super-p (plist-get info :with-sub-superscript)))
-       (if (eq sub/super-p '{})
-          (org-element-property :use-brackets-p blob)
-        sub/super-p)))
-    ;; ... tables...
-    (table (plist-get info :with-tables))
-    (otherwise t)))
+  ;; Set-up a new communication channel with translations defined in
+  ;; BACKEND as the translate table and a new hash table for
+  ;; memoization.
+  (let ((new-info
+        (org-combine-plists
+         info
+         (list :back-end backend
+               :translate-alist (org-export-get-all-transcoders backend)
+               ;; Size of the hash table is reduced since this
+               ;; function will probably be used on small trees.
+               :exported-data (make-hash-table :test 'eq :size 401)))))
+    (prog1 (org-export-data data new-info)
+      ;; Preserve `:internal-references', as those do not depend on
+      ;; the back-end used; we need to make sure that any new
+      ;; reference when the temporary back-end was active gets through
+      ;; the default one.
+      (plist-put info :internal-references
+                (plist-get new-info :internal-references)))))
 
 (defun org-export-expand (blob contents &optional with-affiliated)
   "Expand a parsed element or object to its original state.
@@ -2318,18 +2048,12 @@ contents, as a string or nil.
 When optional argument WITH-AFFILIATED is non-nil, add affiliated
 keywords before output."
   (let ((type (org-element-type blob)))
-    (concat (and with-affiliated (memq type org-element-all-elements)
+    (concat (and with-affiliated
+                (eq (org-element-class blob) 'element)
                 (org-element--interpret-affiliated-keywords blob))
            (funcall (intern (format "org-element-%s-interpreter" type))
                     blob contents))))
 
-(defun org-export-ignore-element (element info)
-  "Add ELEMENT to `:ignore-list' in INFO.
-
-Any element in `:ignore-list' will be skipped when using
-`org-element-map'.  INFO is modified by side effects."
-  (plist-put info :ignore-list (cons element (plist-get info :ignore-list))))
-
 
 
 ;;; The Filter System
@@ -2360,9 +2084,13 @@ Any element in `:ignore-list' will be skipped when using
 ;;   tree.  Users can set it through
 ;;   `org-export-filter-parse-tree-functions' variable.
 ;;
+;; - `:filter-body' applies to the body of the output, before template
+;;   translator chimes in.  Users can set it through
+;;   `org-export-filter-body-functions' variable.
+;;
 ;; - `:filter-final-output' applies to the final transcoded string.
 ;;   Users can set it with `org-export-filter-final-output-functions'
-;;   variable
+;;   variable.
 ;;
 ;; - `:filter-plain-text' applies to any string not recognized as Org
 ;;   syntax.  `org-export-filter-plain-text-functions' allows users to
@@ -2370,7 +2098,7 @@ Any element in `:ignore-list' will be skipped when using
 ;;
 ;; - `:filter-TYPE' applies on the string returned after an element or
 ;;   object of type TYPE has been transcoded.  A user can modify
-;;   `org-export-filter-TYPE-functions'
+;;   `org-export-filter-TYPE-functions' to install these filters.
 ;;
 ;; All filters sets are applied with
 ;; `org-export-filter-apply-functions' function.  Filters in a set are
@@ -2433,6 +2161,13 @@ contains no Org syntax, the back-end, as a symbol, and 
the
 communication channel, as a plist.  It must return a string or
 nil.")
 
+(defvar org-export-filter-body-functions nil
+  "List of functions applied to transcoded body.
+Each filter is called with three arguments: a string which
+contains no Org syntax, the back-end, as a symbol, and the
+communication channel, as a plist.  It must return a string or
+nil.")
+
 (defvar org-export-filter-final-output-functions nil
   "List of functions applied to the transcoded string.
 Each filter is called with three arguments: the full transcoded
@@ -2461,18 +2196,6 @@ Each filter is called with three arguments: the 
transcoded data,
 as a string, the back-end, as a symbol, and the communication
 channel, as a plist.  It must return a string or nil.")
 
-(defvar org-export-filter-comment-functions nil
-  "List of functions applied to a transcoded comment.
-Each filter is called with three arguments: the transcoded data,
-as a string, the back-end, as a symbol, and the communication
-channel, as a plist.  It must return a string or nil.")
-
-(defvar org-export-filter-comment-block-functions nil
-  "List of functions applied to a transcoded comment-block.
-Each filter is called with three arguments: the transcoded data,
-as a string, the back-end, as a symbol, and the communication
-channel, as a plist.  It must return a string or nil.")
-
 (defvar org-export-filter-diary-sexp-functions nil
   "List of functions applied to a transcoded diary-sexp.
 Each filter is called with three arguments: the transcoded data,
@@ -2588,12 +2311,6 @@ data, as a string, the back-end, as a symbol, and the
 communication channel, as a plist.  It must return a string or
 nil.")
 
-(defvar org-export-filter-quote-section-functions nil
-  "List of functions applied to a transcoded quote-section.
-Each filter is called with three arguments: the transcoded data,
-as a string, the back-end, as a symbol, and the communication
-channel, as a plist.  It must return a string or nil.")
-
 (defvar org-export-filter-section-functions nil
   "List of functions applied to a transcoded section.
 Each filter is called with three arguments: the transcoded data,
@@ -2774,20 +2491,24 @@ channel, as a plist.  It must return a string or nil.")
 (defun org-export-filter-apply-functions (filters value info)
   "Call every function in FILTERS.
 
-Functions are called with arguments VALUE, current export
-back-end's name and INFO.  A function returning a nil value will
-be skipped.  If it returns the empty string, the process ends and
-VALUE is ignored.
+Functions are called with three arguments: a value, the export
+back-end name and the communication channel.  First function in
+FILTERS is called with VALUE as its first argument.  Second
+function in FILTERS is called with the previous result as its
+value, etc.
+
+Functions returning nil are skipped.  Any function returning the
+empty string ends the process, which returns the empty string.
 
 Call is done in a LIFO fashion, to be sure that developer
 specified filters, if any, are called first."
-  (catch 'exit
+  (catch :exit
     (let* ((backend (plist-get info :back-end))
           (backend-name (and backend (org-export-backend-name backend))))
       (dolist (filter filters value)
        (let ((result (funcall filter value backend-name info)))
-         (cond ((not result) value)
-               ((equal value "") (throw 'exit nil))
+         (cond ((not result))
+               ((equal result "") (throw :exit ""))
                (t (setq value result))))))))
 
 (defun org-export-install-filters (info)
@@ -2797,29 +2518,27 @@ Return the updated communication channel."
   (let (plist)
     ;; Install user-defined filters with `org-export-filters-alist'
     ;; and filters already in INFO (through ext-plist mechanism).
-    (mapc (lambda (p)
-           (let* ((prop (car p))
-                  (info-value (plist-get info prop))
-                  (default-value (symbol-value (cdr p))))
-             (setq plist
-                   (plist-put plist prop
-                              ;; Filters in INFO will be called
-                              ;; before those user provided.
-                              (append (if (listp info-value) info-value
-                                        (list info-value))
-                                      default-value)))))
-         org-export-filters-alist)
+    (dolist (p org-export-filters-alist)
+      (let* ((prop (car p))
+            (info-value (plist-get info prop))
+            (default-value (symbol-value (cdr p))))
+       (setq plist
+             (plist-put plist prop
+                        ;; Filters in INFO will be called
+                        ;; before those user provided.
+                        (append (if (listp info-value) info-value
+                                  (list info-value))
+                                default-value)))))
     ;; Prepend back-end specific filters to that list.
-    (mapc (lambda (p)
-           ;; Single values get consed, lists are appended.
-           (let ((key (car p)) (value (cdr p)))
-             (when value
-               (setq plist
-                     (plist-put
-                      plist key
-                      (if (atom value) (cons value (plist-get plist key))
-                        (append value (plist-get plist key))))))))
-         (org-export-get-all-filters (plist-get info :back-end)))
+    (dolist (p (org-export-get-all-filters (plist-get info :back-end)))
+      ;; Single values get consed, lists are appended.
+      (let ((key (car p)) (value (cdr p)))
+       (when value
+         (setq plist
+               (plist-put
+                plist key
+                (if (atom value) (cons value (plist-get plist key))
+                  (append value (plist-get plist key))))))))
     ;; Return new communication channel.
     (org-combine-plists info plist)))
 
@@ -2905,7 +2624,7 @@ The function assumes BUFFER's major mode is `org-mode'."
               (when (consp entry)
                 (let ((var (car entry))
                       (val (cdr entry)))
-                  (and (not (eq var 'org-font-lock-keywords))
+                  (and (not (memq var org-export-ignored-local-variables))
                        (or (memq var
                                  '(default-directory
                                     buffer-file-name
@@ -2932,21 +2651,304 @@ The function assumes BUFFER's major mode is 
`org-mode'."
         (goto-char ,(point))
         ;; Overlays with invisible property.
         ,@(let (ov-set)
-            (mapc
-             (lambda (ov)
-               (let ((invis-prop (overlay-get ov 'invisible)))
-                 (when invis-prop
-                   (push `(overlay-put
-                           (make-overlay ,(overlay-start ov)
-                                         ,(overlay-end ov))
-                           'invisible (quote ,invis-prop))
-                         ov-set))))
-             (overlays-in (point-min) (point-max)))
-            ov-set)))))
+            (dolist (ov (overlays-in (point-min) (point-max)) ov-set)
+              (let ((invis-prop (overlay-get ov 'invisible)))
+                (when invis-prop
+                  (push `(overlay-put
+                          (make-overlay ,(overlay-start ov)
+                                        ,(overlay-end ov))
+                          'invisible (quote ,invis-prop))
+                        ov-set)))))))))
+
+(defun org-export--delete-comment-trees ()
+  "Delete commented trees and commented inlinetasks in the buffer.
+Narrowing, if any, is ignored."
+  (org-with-wide-buffer
+   (goto-char (point-min))
+   (let* ((case-fold-search t)
+         (regexp (concat org-outline-regexp-bol ".*" org-comment-string)))
+     (while (re-search-forward regexp nil t)
+       (let ((element (org-element-at-point)))
+        (when (org-element-property :commentedp element)
+          (delete-region (org-element-property :begin element)
+                         (org-element-property :end element))))))))
+
+(defun org-export--prune-tree (data info)
+  "Prune non exportable elements from DATA.
+DATA is the parse tree to traverse.  INFO is the plist holding
+export info.  Also set `:ignore-list' in INFO to a list of
+objects which should be ignored during export, but not removed
+from tree."
+  (letrec ((ignore nil)
+          ;; First find trees containing a select tag, if any.
+          (selected (org-export--selected-trees data info))
+          (walk-data
+           (lambda (data)
+             ;; Prune non-exportable elements and objects from tree.
+             ;; As a special case, special rows and cells from tables
+             ;; are stored in IGNORE, as they still need to be
+             ;; accessed during export.
+             (when data
+               (let ((type (org-element-type data)))
+                 (if (org-export--skip-p data info selected)
+                     (if (memq type '(table-cell table-row)) (push data ignore)
+                       (org-element-extract-element data))
+                   (if (and (eq type 'headline)
+                            (eq (plist-get info :with-archived-trees)
+                                'headline)
+                            (org-element-property :archivedp data))
+                       ;; If headline is archived but tree below has
+                       ;; to be skipped, remove contents.
+                       (org-element-set-contents data)
+                     ;; Move into recursive objects/elements.
+                     (mapc walk-data (org-element-contents data)))
+                   ;; Move into secondary string, if any.
+                   (dolist (p (cdr (assq type
+                                         org-element-secondary-value-alist)))
+                     (mapc walk-data (org-element-property p data))))))))
+          (definitions
+            ;; Collect definitions before possibly pruning them so as
+            ;; to avoid parsing them again if they are required.
+            (org-element-map data '(footnote-definition footnote-reference)
+              (lambda (f)
+                (cond
+                 ((eq (org-element-type f) 'footnote-definition) f)
+                 ((eq (org-element-property :type f) 'standard) nil)
+                 (t (let ((label (org-element-property :label f)))
+                      (when label      ;Skip anonymous references.
+                        (apply
+                         #'org-element-create
+                         'footnote-definition `(:label ,label :post-blank 1)
+                         (org-element-contents f))))))))))
+    ;; If a select tag is active, also ignore the section before the
+    ;; first headline, if any.
+    (when selected
+      (let ((first-element (car (org-element-contents data))))
+       (when (eq (org-element-type first-element) 'section)
+         (org-element-extract-element first-element))))
+    ;; Prune tree and communication channel.
+    (funcall walk-data data)
+    (dolist (entry (append
+                   ;; Priority is given to back-end specific options.
+                   (org-export-get-all-options (plist-get info :back-end))
+                   org-export-options-alist))
+      (when (eq (nth 4 entry) 'parse)
+       (funcall walk-data (plist-get info (car entry)))))
+    (let ((missing (org-export--missing-definitions data definitions)))
+      (funcall walk-data missing)
+      (org-export--install-footnote-definitions missing data))
+    ;; Eventually set `:ignore-list'.
+    (plist-put info :ignore-list ignore)))
+
+(defun org-export--missing-definitions (tree definitions)
+  "List footnote definitions missing from TREE.
+Missing definitions are searched within DEFINITIONS, which is
+a list of footnote definitions or in the widened buffer."
+  (let* ((list-labels
+         (lambda (data)
+           ;; List all footnote labels encountered in DATA.  Inline
+           ;; footnote references are ignored.
+           (org-element-map data 'footnote-reference
+             (lambda (reference)
+               (and (eq (org-element-property :type reference) 'standard)
+                    (org-element-property :label reference))))))
+        defined undefined missing-definitions)
+    ;; Partition DIRECT-REFERENCES between DEFINED and UNDEFINED
+    ;; references.
+    (let ((known-definitions
+          (org-element-map tree '(footnote-reference footnote-definition)
+            (lambda (f)
+              (and (or (eq (org-element-type f) 'footnote-definition)
+                       (eq (org-element-property :type f) 'inline))
+                   (org-element-property :label f)))))
+         seen)
+      (dolist (l (funcall list-labels tree))
+       (cond ((member l seen))
+             ((member l known-definitions) (push l defined))
+             (t (push l undefined)))))
+    ;; Complete MISSING-DEFINITIONS by finding the definition of every
+    ;; undefined label, first by looking into DEFINITIONS, then by
+    ;; searching the widened buffer.  This is a recursive process
+    ;; since definitions found can themselves contain an undefined
+    ;; reference.
+    (while undefined
+      (let* ((label (pop undefined))
+            (definition
+              (cond
+               ((cl-some
+                 (lambda (d) (and (equal (org-element-property :label d) label)
+                             d))
+                 definitions))
+               ((pcase (org-footnote-get-definition label)
+                  (`(,_ ,beg . ,_)
+                   (org-with-wide-buffer
+                    (goto-char beg)
+                    (let ((datum (org-element-context)))
+                      (if (eq (org-element-type datum) 'footnote-reference)
+                          datum
+                        ;; Parse definition with contents.
+                        (save-restriction
+                          (narrow-to-region
+                           (org-element-property :begin datum)
+                           (org-element-property :end datum))
+                          (org-element-map (org-element-parse-buffer)
+                              'footnote-definition #'identity nil t))))))
+                  (_ nil)))
+               (t (user-error "Definition not found for footnote %s" label)))))
+       (push label defined)
+       (push definition missing-definitions)
+       ;; Look for footnote references within DEFINITION, since
+       ;; we may need to also find their definition.
+       (dolist (l (funcall list-labels definition))
+         (unless (or (member l defined)    ;Known label
+                     (member l undefined)) ;Processed later
+           (push l undefined)))))
+    ;; MISSING-DEFINITIONS may contain footnote references with inline
+    ;; definitions.  Make sure those are changed into real footnote
+    ;; definitions.
+    (mapcar (lambda (d)
+             (if (eq (org-element-type d) 'footnote-definition) d
+               (let ((label (org-element-property :label d)))
+                 (apply #'org-element-create
+                        'footnote-definition `(:label ,label :post-blank 1)
+                        (org-element-contents d)))))
+           missing-definitions)))
+
+(defun org-export--install-footnote-definitions (definitions tree)
+  "Install footnote definitions in tree.
+
+DEFINITIONS is the list of footnote definitions to install.  TREE
+is the parse tree.
+
+If there is a footnote section in TREE, definitions found are
+appended to it.  If `org-footnote-section' is non-nil, a new
+footnote section containing all definitions is inserted in TREE.
+Otherwise, definitions are appended at the end of the section
+containing their first reference."
+  (cond
+   ((null definitions))
+   ;; If there is a footnote section, insert definitions there.
+   ((let ((footnote-section
+          (org-element-map tree 'headline
+            (lambda (h) (and (org-element-property :footnote-section-p h) h))
+            nil t)))
+      (and footnote-section
+          (apply #'org-element-adopt-elements
+                 footnote-section
+                 (nreverse definitions)))))
+   ;; If there should be a footnote section, create one containing all
+   ;; the definitions at the end of the tree.
+   (org-footnote-section
+    (org-element-adopt-elements
+     tree
+     (org-element-create 'headline
+                        (list :footnote-section-p t
+                              :level 1
+                              :title org-footnote-section
+                              :raw-value org-footnote-section)
+                        (apply #'org-element-create
+                               'section
+                               nil
+                               (nreverse definitions)))))
+   ;; Otherwise add each definition at the end of the section where it
+   ;; is first referenced.
+   (t
+    (letrec ((seen nil)
+            (insert-definitions
+             (lambda (data)
+               ;; Insert footnote definitions in the same section as
+               ;; their first reference in DATA.
+               (org-element-map data 'footnote-reference
+                 (lambda (reference)
+                   (when (eq (org-element-property :type reference) 'standard)
+                     (let ((label (org-element-property :label reference)))
+                       (unless (member label seen)
+                         (push label seen)
+                         (let ((definition
+                                 (cl-some
+                                  (lambda (d)
+                                    (and (equal (org-element-property :label d)
+                                                label)
+                                         d))
+                                  definitions)))
+                           (org-element-adopt-elements
+                            (org-element-lineage reference '(section))
+                            definition)
+                           ;; Also insert definitions for nested
+                           ;; references, if any.
+                           (funcall insert-definitions definition))))))))))
+      (funcall insert-definitions tree)))))
+
+(defun org-export--remove-uninterpreted-data (data info)
+  "Change uninterpreted elements back into Org syntax.
+DATA is a parse tree or a secondary string.  INFO is a plist
+containing export options.  It is modified by side effect and
+returned by the function."
+  (org-element-map data
+      '(entity bold italic latex-environment latex-fragment strike-through
+              subscript superscript underline)
+    (lambda (datum)
+      (let ((new
+            (cl-case (org-element-type datum)
+              ;; ... entities...
+              (entity
+               (and (not (plist-get info :with-entities))
+                    (list (concat
+                           (org-export-expand datum nil)
+                           (make-string
+                            (or (org-element-property :post-blank datum) 0)
+                            ?\s)))))
+              ;; ... emphasis...
+              ((bold italic strike-through underline)
+               (and (not (plist-get info :with-emphasize))
+                    (let ((marker (cl-case (org-element-type datum)
+                                    (bold "*")
+                                    (italic "/")
+                                    (strike-through "+")
+                                    (underline "_"))))
+                      (append
+                       (list marker)
+                       (org-element-contents datum)
+                       (list (concat
+                              marker
+                              (make-string
+                               (or (org-element-property :post-blank datum)
+                                   0)
+                               ?\s)))))))
+              ;; ... LaTeX environments and fragments...
+              ((latex-environment latex-fragment)
+               (and (eq (plist-get info :with-latex) 'verbatim)
+                    (list (org-export-expand datum nil))))
+              ;; ... sub/superscripts...
+              ((subscript superscript)
+               (let ((sub/super-p (plist-get info :with-sub-superscript))
+                     (bracketp (org-element-property :use-brackets-p datum)))
+                 (and (or (not sub/super-p)
+                          (and (eq sub/super-p '{}) (not bracketp)))
+                      (append
+                       (list (concat
+                              (if (eq (org-element-type datum) 'subscript)
+                                  "_"
+                                "^")
+                              (and bracketp "{")))
+                       (org-element-contents datum)
+                       (list (concat
+                              (and bracketp "}")
+                              (and (org-element-property :post-blank datum)
+                                   (make-string
+                                    (org-element-property :post-blank datum)
+                                    ?\s)))))))))))
+       (when new
+         ;; Splice NEW at DATUM location in parse tree.
+         (dolist (e new (org-element-extract-element datum))
+           (unless (equal e "") (org-element-insert-before e datum))))))
+    info nil nil t)
+  ;; Return modified parse tree.
+  data)
 
 ;;;###autoload
 (defun org-export-as
-  (backend &optional subtreep visible-only body-only ext-plist)
+    (backend &optional subtreep visible-only body-only ext-plist)
   "Transcode current Org buffer into BACKEND code.
 
 BACKEND is either an export back-end, as returned by, e.g.,
@@ -2978,75 +2980,74 @@ Return code as a string."
   (save-excursion
     (save-restriction
       ;; Narrow buffer to an appropriate region or subtree for
-      ;; parsing.  If parsing subtree, be sure to remove main headline
-      ;; too.
+      ;; parsing.  If parsing subtree, be sure to remove main
+      ;; headline, planning data and property drawer.
       (cond ((org-region-active-p)
             (narrow-to-region (region-beginning) (region-end)))
            (subtreep
             (org-narrow-to-subtree)
             (goto-char (point-min))
-            (forward-line)
+            (org-end-of-meta-data)
             (narrow-to-region (point) (point-max))))
       ;; Initialize communication channel with original buffer
       ;; attributes, unavailable in its copy.
       (let* ((org-export-current-backend (org-export-backend-name backend))
             (info (org-combine-plists
-                   (list :export-options
-                         (delq nil
-                               (list (and subtreep 'subtree)
-                                     (and visible-only 'visible-only)
-                                     (and body-only 'body-only))))
+                   (org-export--get-export-attributes
+                    backend subtreep visible-only body-only)
                    (org-export--get-buffer-attributes)))
+            (parsed-keywords
+             (delq nil
+                   (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o)))
+                           (append (org-export-get-all-options backend)
+                                   org-export-options-alist))))
             tree)
        ;; Update communication channel and get parse tree.  Buffer
-       ;; isn't parsed directly.  Instead, a temporary copy is
-       ;; created, where include keywords, macros are expanded and
-       ;; code blocks are evaluated.
+       ;; isn't parsed directly.  Instead, all buffer modifications
+       ;; and consequent parsing are undertaken in a temporary copy.
        (org-export-with-buffer-copy
         ;; Run first hook with current back-end's name as argument.
         (run-hook-with-args 'org-export-before-processing-hook
                             (org-export-backend-name backend))
+        ;; Include files, delete comments and expand macros.
         (org-export-expand-include-keyword)
-        ;; Update macro templates since #+INCLUDE keywords might have
-        ;; added some new ones.
+        (org-export--delete-comment-trees)
         (org-macro-initialize-templates)
-        (org-macro-replace-all org-macro-templates)
-        (org-export-execute-babel-code)
-        ;; Update radio targets since keyword inclusion might have
-        ;; added some more.
+        (org-macro-replace-all org-macro-templates nil parsed-keywords)
+        ;; Refresh buffer properties and radio targets after
+        ;; potentially invasive previous changes.  Likewise, do it
+        ;; again after executing Babel code.
+        (org-set-regexps-and-options)
         (org-update-radio-target-regexp)
+        (when org-export-babel-evaluate
+          (org-babel-exp-process-buffer)
+          (org-set-regexps-and-options)
+          (org-update-radio-target-regexp))
         ;; Run last hook with current back-end's name as argument.
+        ;; Update buffer properties and radio targets one last time
+        ;; before parsing.
         (goto-char (point-min))
         (save-excursion
           (run-hook-with-args 'org-export-before-parsing-hook
                               (org-export-backend-name backend)))
-        ;; Update communication channel with environment.  Also
-        ;; install user's and developer's filters.
+        (org-set-regexps-and-options)
+        (org-update-radio-target-regexp)
+        ;; Update communication channel with environment.
         (setq info
-              (org-export-install-filters
-               (org-combine-plists
-                info (org-export-get-environment backend subtreep ext-plist))))
-        ;; Special case: provide original file name or buffer name as
-        ;; default value for :title property.
-        (unless (plist-get info :title)
-          (plist-put
-           info :title
-           (let ((file (plist-get info :input-file)))
-             (if file (file-name-sans-extension (file-name-nondirectory file))
-               (plist-get info :input-buffer)))))
-        ;; Expand export-specific set of macros: {{{author}}},
-        ;; {{{date}}}, {{{email}}} and {{{title}}}.  It must be done
-        ;; once regular macros have been expanded, since document
-        ;; keywords may contain one of them.
-        (org-macro-replace-all
-         (list (cons "author"
-                     (org-element-interpret-data (plist-get info :author)))
-               (cons "date"
-                     (org-element-interpret-data (plist-get info :date)))
-               ;; EMAIL is not a parsed keyword: store it as-is.
-               (cons "email" (or (plist-get info :email) ""))
-               (cons "title"
-                     (org-element-interpret-data (plist-get info :title)))))
+              (org-combine-plists
+               info (org-export-get-environment backend subtreep ext-plist)))
+        ;; De-activate uninterpreted data from parsed keywords.
+        (dolist (entry (append (org-export-get-all-options backend)
+                               org-export-options-alist))
+          (pcase entry
+            (`(,p ,_ ,_ ,_ parse)
+             (let ((value (plist-get info p)))
+               (plist-put info
+                          p
+                          (org-export--remove-uninterpreted-data value info))))
+            (_ nil)))
+        ;; Install user's and developer's filters.
+        (setq info (org-export-install-filters info))
         ;; Call options filters and update export options.  We do not
         ;; use `org-export-filter-apply-functions' here since the
         ;; arity of such filters is different.
@@ -3054,24 +3055,54 @@ Return code as a string."
           (dolist (filter (plist-get info :filter-options))
             (let ((result (funcall filter info backend-name)))
               (when result (setq info result)))))
-        ;; Parse buffer and call parse-tree filter on it.
+        ;; Expand export-specific set of macros: {{{author}}},
+        ;; {{{date(FORMAT)}}}, {{{email}}} and {{{title}}}.  It must
+        ;; be done once regular macros have been expanded, since
+        ;; parsed keywords may contain one of them.
+        (org-macro-replace-all
+         (list
+          (cons "author" (org-element-interpret-data (plist-get info :author)))
+          (cons "date"
+                (let* ((date (plist-get info :date))
+                       (value (or (org-element-interpret-data date) "")))
+                  (if (and (consp date)
+                           (not (cdr date))
+                           (eq (org-element-type (car date)) 'timestamp))
+                      (format "(eval (if (org-string-nw-p \"$1\") %s %S))"
+                              (format "(org-timestamp-format '%S \"$1\")"
+                                      (org-element-copy (car date)))
+                              value)
+                    value)))
+          (cons "email" (org-element-interpret-data (plist-get info :email)))
+          (cons "title" (org-element-interpret-data (plist-get info :title)))
+          (cons "results" "$1"))
+         'finalize
+         parsed-keywords)
+        ;; Parse buffer.
+        (setq tree (org-element-parse-buffer nil visible-only))
+        ;; Prune tree from non-exported elements and transform
+        ;; uninterpreted elements or objects in both parse tree and
+        ;; communication channel.
+        (org-export--prune-tree tree info)
+        (org-export--remove-uninterpreted-data tree info)
+        ;; Call parse tree filters.
         (setq tree
               (org-export-filter-apply-functions
-               (plist-get info :filter-parse-tree)
-               (org-element-parse-buffer nil visible-only) info))
+               (plist-get info :filter-parse-tree) tree info))
         ;; Now tree is complete, compute its properties and add them
         ;; to communication channel.
-        (setq info
-              (org-combine-plists
-               info (org-export-collect-tree-properties tree info)))
+        (setq info (org-export--collect-tree-properties tree info))
         ;; Eventually transcode TREE.  Wrap the resulting string into
         ;; a template.
         (let* ((body (org-element-normalize-string
                       (or (org-export-data tree info) "")))
                (inner-template (cdr (assq 'inner-template
                                           (plist-get info :translate-alist))))
-               (full-body (if (not (functionp inner-template)) body
-                            (funcall inner-template body info)))
+               (full-body (org-export-filter-apply-functions
+                           (plist-get info :filter-body)
+                           (if (not (functionp inner-template)) body
+                             (funcall inner-template body info))
+                           info))
                (template (cdr (assq 'template
                                     (plist-get info :translate-alist)))))
           ;; Remove all text properties since they cannot be
@@ -3111,14 +3142,10 @@ Return code as a string."
 BACKEND is either an export back-end, as returned by, e.g.,
 `org-export-create-backend', or a symbol referring to
 a registered back-end."
-  (if (not (org-region-active-p))
-      (user-error "No active region to replace")
-    (let* ((beg (region-beginning))
-          (end (region-end))
-          (str (buffer-substring beg end)) rpl)
-      (setq rpl (org-export-string-as str backend t))
-      (delete-region beg end)
-      (insert rpl))))
+  (unless (org-region-active-p) (user-error "No active region to replace"))
+  (insert
+   (org-export-string-as
+    (delete-and-extract-region (region-beginning) (region-end)) backend t)))
 
 ;;;###autoload
 (defun org-export-insert-default-template (&optional backend subtreep)
@@ -3144,7 +3171,8 @@ locally for the subtree through node properties."
               (cons "default"
                     (mapcar (lambda (b)
                               (symbol-name (org-export-backend-name b)))
-                            org-export--registered-backends))))))
+                            org-export-registered-backends))
+              nil t))))
        options keywords)
     ;; Populate OPTIONS and KEYWORDS.
     (dolist (entry (cond ((eq backend 'default) org-export-options-alist)
@@ -3158,43 +3186,14 @@ locally for the subtree through node properties."
          (keyword (unless (assoc keyword keywords)
                     (let ((value
                            (if (eq (nth 4 entry) 'split)
-                               (mapconcat 'identity (eval (nth 3 entry)) " ")
+                               (mapconcat #'identity (eval (nth 3 entry)) " ")
                              (eval (nth 3 entry)))))
                       (push (cons keyword value) keywords))))
          (option (unless (assoc option options)
                    (push (cons option (eval (nth 3 entry))) options))))))
     ;; Move to an appropriate location in order to insert options.
     (unless subtreep (beginning-of-line))
-    ;; First get TITLE, DATE, AUTHOR and EMAIL if they belong to the
-    ;; list of available keywords.
-    (when (assoc "TITLE" keywords)
-      (let ((title
-            (or (let ((visited-file (buffer-file-name (buffer-base-buffer))))
-                  (and visited-file
-                       (file-name-sans-extension
-                        (file-name-nondirectory visited-file))))
-                (buffer-name (buffer-base-buffer)))))
-       (if (not subtreep) (insert (format "#+TITLE: %s\n" title))
-         (org-entry-put node "EXPORT_TITLE" title))))
-    (when (assoc "DATE" keywords)
-      (let ((date (with-temp-buffer (org-insert-time-stamp (current-time)))))
-       (if (not subtreep) (insert "#+DATE: " date "\n")
-         (org-entry-put node "EXPORT_DATE" date))))
-    (when (assoc "AUTHOR" keywords)
-      (let ((author (cdr (assoc "AUTHOR" keywords))))
-       (if subtreep (org-entry-put node "EXPORT_AUTHOR" author)
-         (insert
-          (format "#+AUTHOR:%s\n"
-                  (if (not (org-string-nw-p author)) ""
-                    (concat " " author)))))))
-    (when (assoc "EMAIL" keywords)
-      (let ((email (cdr (assoc "EMAIL" keywords))))
-       (if subtreep (org-entry-put node "EXPORT_EMAIL" email)
-         (insert
-          (format "#+EMAIL:%s\n"
-                  (if (not (org-string-nw-p email)) ""
-                    (concat " " email)))))))
-    ;; Then (multiple) OPTIONS lines.  Never go past fill-column.
+    ;; First (multiple) OPTIONS lines.  Never go past fill-column.
     (when options
       (let ((items
             (mapcar
@@ -3210,50 +3209,93 @@ locally for the subtree through node properties."
                          (< (+ width (length (car items)) 1) fill-column))
                (let ((item (pop items)))
                  (insert " " item)
-                 (incf width (1+ (length item))))))
+                 (cl-incf width (1+ (length item))))))
            (insert "\n")))))
-    ;; And the rest of keywords.
-    (dolist (key (sort keywords (lambda (k1 k2) (string< (car k1) (car k2)))))
-      (unless (member (car key) '("TITLE" "DATE" "AUTHOR" "EMAIL"))
-        (let ((val (cdr key)))
-          (if subtreep (org-entry-put node (concat "EXPORT_" (car key)) val)
-            (insert
-             (format "#+%s:%s\n"
-                     (car key)
-                     (if (org-string-nw-p val) (format " %s" val) "")))))))))
-
-(defun org-export-expand-include-keyword (&optional included dir)
+    ;; Then the rest of keywords, in the order specified in either
+    ;; `org-export-options-alist' or respective export back-ends.
+    (dolist (key (nreverse keywords))
+      (let ((val (cond ((equal (car key) "DATE")
+                       (or (cdr key)
+                           (with-temp-buffer
+                             (org-insert-time-stamp (current-time)))))
+                      ((equal (car key) "TITLE")
+                       (or (let ((visited-file
+                                  (buffer-file-name (buffer-base-buffer))))
+                             (and visited-file
+                                  (file-name-sans-extension
+                                   (file-name-nondirectory visited-file))))
+                           (buffer-name (buffer-base-buffer))))
+                      (t (cdr key)))))
+       (if subtreep (org-entry-put node (concat "EXPORT_" (car key)) val)
+         (insert
+          (format "#+%s:%s\n"
+                  (car key)
+                  (if (org-string-nw-p val) (format " %s" val) ""))))))))
+
+(defun org-export-expand-include-keyword (&optional included dir footnotes)
   "Expand every include keyword in buffer.
 Optional argument INCLUDED is a list of included file names along
 with their line restriction, when appropriate.  It is used to
 avoid infinite recursion.  Optional argument DIR is the current
 working directory.  It is used to properly resolve relative
-paths."
-  (let ((case-fold-search t))
+paths.  Optional argument FOOTNOTES is a hash-table used for
+storing and resolving footnotes.  It is created automatically."
+  (let ((case-fold-search t)
+       (file-prefix (make-hash-table :test #'equal))
+       (current-prefix 0)
+       (footnotes (or footnotes (make-hash-table :test #'equal)))
+       (include-re "^[ \t]*#\\+INCLUDE:"))
+    ;; If :minlevel is not set the text-property
+    ;; `:org-include-induced-level' will be used to determine the
+    ;; relative level when expanding INCLUDE.
+    ;; Only affects included Org documents.
+    (goto-char (point-min))
+    (while (re-search-forward include-re nil t)
+      (put-text-property (line-beginning-position) (line-end-position)
+                        :org-include-induced-level
+                        (1+ (org-reduced-level (or (org-current-level) 0)))))
+    ;; Expand INCLUDE keywords.
     (goto-char (point-min))
-    (while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t)
+    (while (re-search-forward include-re nil t)
       (let ((element (save-match-data (org-element-at-point))))
        (when (eq (org-element-type element) 'keyword)
          (beginning-of-line)
          ;; Extract arguments from keyword's value.
          (let* ((value (org-element-property :value element))
                 (ind (org-get-indentation))
-                (file (and (string-match
-                            "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" value)
-                           (prog1 (expand-file-name
-                                   (org-remove-double-quotes
-                                    (match-string 1 value))
-                                   dir)
-                             (setq value (replace-match "" nil nil value)))))
+                location
+                (file
+                 (and (string-match
+                       "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" value)
+                      (prog1
+                          (save-match-data
+                            (let ((matched (match-string 1 value)))
+                              (when (string-match "\\(::\\(.*?\\)\\)\"?\\'"
+                                                  matched)
+                                (setq location (match-string 2 matched))
+                                (setq matched
+                                      (replace-match "" nil nil matched 1)))
+                              (expand-file-name
+                               (org-unbracket-string "\"" "\"" matched)
+                               dir)))
+                        (setq value (replace-match "" nil nil value)))))
+                (only-contents
+                 (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?"
+                                    value)
+                      (prog1 (org-not-nil (match-string 1 value))
+                        (setq value (replace-match "" nil nil value)))))
                 (lines
                  (and (string-match
                        ":lines +\"\\(\\(?:[0-9]+\\)?-\\(?:[0-9]+\\)?\\)\""
                        value)
                       (prog1 (match-string 1 value)
                         (setq value (replace-match "" nil nil value)))))
-                (env (cond ((string-match "\\<example\\>" value) 'example)
-                           ((string-match "\\<src\\(?: +\\(.*\\)\\)?" value)
-                            (match-string 1 value))))
+                (env (cond
+                      ((string-match "\\<example\\>" value) 'literal)
+                      ((string-match "\\<export\\(?: +\\(.*\\)\\)?" value)
+                       'literal)
+                      ((string-match "\\<src\\(?: +\\(.*\\)\\)?" value)
+                       'literal)))
                 ;; Minimal level of included file defaults to the child
                 ;; level of the current headline, if any, or one.  It
                 ;; only applies is the file is meant to be included as
@@ -3263,10 +3305,13 @@ paths."
                       (if (string-match ":minlevel +\\([0-9]+\\)" value)
                           (prog1 (string-to-number (match-string 1 value))
                             (setq value (replace-match "" nil nil value)))
-                        (let ((cur (org-current-level)))
-                          (if cur (1+ (org-reduced-level cur)) 1))))))
+                        (get-text-property (point)
+                                           :org-include-induced-level))))
+                (args (and (eq env 'literal) (match-string 1 value)))
+                (block (and (string-match "\\<\\(\\S-+\\)\\>" value)
+                            (match-string 1 value))))
            ;; Remove keyword.
-           (delete-region (point) (progn (forward-line) (point)))
+           (delete-region (point) (line-beginning-position 2))
            (cond
             ((not file) nil)
             ((not (file-readable-p file))
@@ -3278,35 +3323,116 @@ paths."
              (error "Recursive file inclusion: %s" file))
             (t
              (cond
-              ((eq env 'example)
+              ((eq env 'literal)
                (insert
-                (let ((ind-str (make-string ind ? ))
+                (let ((ind-str (make-string ind ?\s))
+                      (arg-str (if (stringp args) (format " %s" args) ""))
                       (contents
                        (org-escape-code-in-string
                         (org-export--prepare-file-contents file lines))))
-                  (format "%s#+BEGIN_EXAMPLE\n%s%s#+END_EXAMPLE\n"
-                          ind-str contents ind-str))))
-              ((stringp env)
+                  (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n"
+                          ind-str block arg-str contents ind-str block))))
+              ((stringp block)
                (insert
-                (let ((ind-str (make-string ind ? ))
+                (let ((ind-str (make-string ind ?\s))
                       (contents
-                       (org-escape-code-in-string
-                        (org-export--prepare-file-contents file lines))))
-                  (format "%s#+BEGIN_SRC %s\n%s%s#+END_SRC\n"
-                          ind-str env contents ind-str))))
+                       (org-export--prepare-file-contents file lines)))
+                  (format "%s#+BEGIN_%s\n%s%s#+END_%s\n"
+                          ind-str block contents ind-str block))))
               (t
                (insert
                 (with-temp-buffer
-                  (let ((org-inhibit-startup t)) (org-mode))
-                  (insert
-                   (org-export--prepare-file-contents file lines ind minlevel))
+                  (let ((org-inhibit-startup t)
+                        (lines
+                         (if location
+                             (org-export--inclusion-absolute-lines
+                              file location only-contents lines)
+                           lines)))
+                    (org-mode)
+                     (insert
+                     (org-export--prepare-file-contents
+                      file lines ind minlevel
+                      (or (gethash file file-prefix)
+                          (puthash file (cl-incf current-prefix) file-prefix))
+                      footnotes)))
                   (org-export-expand-include-keyword
                    (cons (list file lines) included)
-                   (file-name-directory file))
-                  (buffer-string)))))))))))))
+                   (file-name-directory file)
+                   footnotes)
+                  (buffer-string)))))
+             ;; Expand footnotes after all files have been included.
+             ;; Footnotes are stored at end of buffer.
+             (unless included
+               (org-with-wide-buffer
+                (goto-char (point-max))
+                (maphash (lambda (k v) (insert (format "\n[fn:%s] %s\n" k v)))
+                         footnotes)))))))))))
+
+(defun org-export--inclusion-absolute-lines (file location only-contents lines)
+  "Resolve absolute lines for an included file with file-link.
 
-(defun org-export--prepare-file-contents (file &optional lines ind minlevel)
-  "Prepare the contents of FILE for inclusion and return them as a string.
+FILE is string file-name of the file to include.  LOCATION is a
+string name within FILE to be included (located via
+`org-link-search').  If ONLY-CONTENTS is non-nil only the
+contents of the named element will be included, as determined
+Org-Element.  If LINES is non-nil only those lines are included.
+
+Return a string of lines to be included in the format expected by
+`org-export--prepare-file-contents'."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (unless (eq major-mode 'org-mode)
+      (let ((org-inhibit-startup t)) (org-mode)))
+    (condition-case err
+       ;; Enforce consistent search.
+       (let ((org-link-search-must-match-exact-headline nil))
+         (org-link-search location))
+      (error
+       (error "%s for %s::%s" (error-message-string err) file location)))
+    (let* ((element (org-element-at-point))
+          (contents-begin
+           (and only-contents (org-element-property :contents-begin element))))
+      (narrow-to-region
+       (or contents-begin (org-element-property :begin element))
+       (org-element-property (if contents-begin :contents-end :end) element))
+      (when (and only-contents
+                (memq (org-element-type element) '(headline inlinetask)))
+       ;; Skip planning line and property-drawer.
+       (goto-char (point-min))
+       (when (looking-at-p org-planning-line-re) (forward-line))
+       (when (looking-at org-property-drawer-re) (goto-char (match-end 0)))
+       (unless (bolp) (forward-line))
+       (narrow-to-region (point) (point-max))))
+    (when lines
+      (org-skip-whitespace)
+      (beginning-of-line)
+      (let* ((lines (split-string lines "-"))
+            (lbeg (string-to-number (car lines)))
+            (lend (string-to-number (cadr lines)))
+            (beg (if (zerop lbeg) (point-min)
+                   (goto-char (point-min))
+                   (forward-line (1- lbeg))
+                   (point)))
+            (end (if (zerop lend) (point-max)
+                   (goto-char beg)
+                   (forward-line (1- lend))
+                   (point))))
+       (narrow-to-region beg end)))
+    (let ((end (point-max)))
+      (goto-char (point-min))
+      (widen)
+      (let ((start-line (line-number-at-pos)))
+       (format "%d-%d"
+               start-line
+               (save-excursion
+                 (+ start-line
+                    (let ((counter 0))
+                      (while (< (point) end) (cl-incf counter) (forward-line))
+                      counter))))))))
+
+(defun org-export--prepare-file-contents
+    (file &optional lines ind minlevel id footnotes)
+  "Prepare contents of FILE for inclusion and return it as a string.
 
 When optional argument LINES is a string specifying a range of
 lines, include only those lines.
@@ -3314,12 +3440,20 @@ lines, include only those lines.
 Optional argument IND, when non-nil, is an integer specifying the
 global indentation of returned contents.  Since its purpose is to
 allow an included file to stay in the same environment it was
-created \(i.e., a list item), it doesn't apply past the first
+created (e.g., a list item), it doesn't apply past the first
 headline encountered.
 
 Optional argument MINLEVEL, when non-nil, is an integer
 specifying the level that any top-level headline in the included
-file should have."
+file should have.
+
+Optional argument ID is an integer that will be inserted before
+each footnote definition and reference if FILE is an Org file.
+This is useful to avoid conflicts when more than one Org file
+with footnotes is included in a document.
+
+Optional argument FOOTNOTES is a hash-table to store footnotes in
+the included document."
   (with-temp-buffer
     (insert-file-contents file)
     (when lines
@@ -3348,11 +3482,11 @@ file should have."
     (delete-region (point) (point-max))
     ;; If IND is set, preserve indentation of include keyword until
     ;; the first headline encountered.
-    (when ind
+    (when (and ind (> ind 0))
       (unless (eq major-mode 'org-mode)
        (let ((org-inhibit-startup t)) (org-mode)))
       (goto-char (point-min))
-      (let ((ind-str (make-string ind ? )))
+      (let ((ind-str (make-string ind ?\s)))
        (while (not (or (eobp) (looking-at org-outline-regexp-bol)))
          ;; Do not move footnote definitions out of column 0.
          (unless (and (looking-at org-footnote-definition-re)
@@ -3370,25 +3504,67 @@ file should have."
        (let ((levels (org-map-entries
                      (lambda () (org-reduced-level (org-current-level))))))
         (when levels
-          (let ((offset (- minlevel (apply 'min levels))))
+          (let ((offset (- minlevel (apply #'min levels))))
             (unless (zerop offset)
               (when org-odd-levels-only (setq offset (* offset 2)))
               ;; Only change stars, don't bother moving whole
               ;; sections.
               (org-map-entries
-               (lambda () (if (< offset 0) (delete-char (abs offset))
-                       (insert (make-string offset ?*)))))))))))
+               (lambda ()
+                 (if (< offset 0) (delete-char (abs offset))
+                   (insert (make-string offset ?*)))))))))))
+    ;; Append ID to all footnote references and definitions, so they
+    ;; become file specific and cannot collide with footnotes in other
+    ;; included files.  Further, collect relevant footnote definitions
+    ;; outside of LINES, in order to reintroduce them later.
+    (when id
+      (let ((marker-min (point-min-marker))
+           (marker-max (point-max-marker))
+           (get-new-label
+            (lambda (label)
+              ;; Generate new label from LABEL by prefixing it with
+              ;; "-ID-".
+              (format "-%d-%s" id label)))
+           (set-new-label
+            (lambda (f old new)
+              ;; Replace OLD label with NEW in footnote F.
+              (save-excursion
+                (goto-char (+ (org-element-property :begin f) 4))
+                (looking-at (regexp-quote old))
+                (replace-match new))))
+           (seen-alist))
+       (goto-char (point-min))
+       (while (re-search-forward org-footnote-re nil t)
+         (let ((footnote (save-excursion
+                           (backward-char)
+                           (org-element-context))))
+           (when (memq (org-element-type footnote)
+                       '(footnote-definition footnote-reference))
+             (let* ((label (org-element-property :label footnote)))
+               ;; Update the footnote-reference at point and collect
+               ;; the new label, which is only used for footnotes
+               ;; outsides LINES.
+               (when label
+                 (let ((seen (cdr (assoc label seen-alist))))
+                   (if seen (funcall set-new-label footnote label seen)
+                     (let ((new (funcall get-new-label label)))
+                       (push (cons label new) seen-alist)
+                       (org-with-wide-buffer
+                        (let* ((def (org-footnote-get-definition label))
+                               (beg (nth 1 def)))
+                          (when (and def
+                                     (or (< beg marker-min)
+                                         (>= beg marker-max)))
+                            ;; Store since footnote-definition is
+                            ;; outside of LINES.
+                            (puthash new
+                                     (org-element-normalize-string (nth 3 def))
+                                     footnotes))))
+                       (funcall set-new-label footnote label new)))))))))
+       (set-marker marker-min nil)
+       (set-marker marker-max nil)))
     (org-element-normalize-string (buffer-string))))
 
-(defun org-export-execute-babel-code ()
-  "Execute every Babel code in the visible part of current buffer."
-  ;; Get a pristine copy of current buffer so Babel references can be
-  ;; properly resolved.
-  (let ((reference (org-export-copy-buffer)))
-    (unwind-protect (let ((org-current-export-file reference))
-                     (org-babel-exp-process-buffer))
-      (kill-buffer reference))))
-
 (defun org-export--copy-to-kill-ring-p ()
   "Return a non-nil value when output should be added to the kill ring.
 See also `org-export-copy-to-kill-ring'."
@@ -3483,17 +3659,20 @@ the communication channel used for export, as a plist."
   (when (symbolp backend) (setq backend (org-export-get-backend backend)))
   (org-export-barf-if-invalid-backend backend)
   (let ((type (org-element-type data)))
-    (if (memq type '(nil org-data)) (error "No foreign transcoder available")
-      (let* ((all-transcoders (org-export-get-all-transcoders backend))
-            (transcoder (cdr (assq type all-transcoders))))
-       (if (not (functionp transcoder))
-           (error "No foreign transcoder available")
-         (funcall
-          transcoder data contents
-          (org-combine-plists
-           info (list :back-end backend
-                      :translate-alist all-transcoders
-                      :exported-data (make-hash-table :test 'eq :size 
401)))))))))
+    (when (memq type '(nil org-data)) (error "No foreign transcoder 
available"))
+    (let* ((all-transcoders (org-export-get-all-transcoders backend))
+          (transcoder (cdr (assq type all-transcoders))))
+      (unless (functionp transcoder) (error "No foreign transcoder available"))
+      (let ((new-info
+            (org-combine-plists
+             info (list
+                   :back-end backend
+                   :translate-alist all-transcoders
+                   :exported-data (make-hash-table :test #'eq :size 401)))))
+       ;; `:internal-references' are shared across back-ends.
+       (prog1 (funcall transcoder data contents new-info)
+         (plist-put info :internal-references
+                    (plist-get new-info :internal-references)))))))
 
 
 ;;;; For Export Snippets
@@ -3529,127 +3708,168 @@ applied."
 ;; `org-export-get-footnote-number' provide easier access to
 ;; additional information relative to a footnote reference.
 
-(defun org-export-collect-footnote-definitions (data info)
+(defun org-export-get-footnote-definition (footnote-reference info)
+  "Return definition of FOOTNOTE-REFERENCE as parsed data.
+INFO is the plist used as a communication channel.  If no such
+definition can be found, raise an error."
+  (let ((label (org-element-property :label footnote-reference)))
+    (if (not label) (org-element-contents footnote-reference)
+      (let ((cache (or (plist-get info :footnote-definition-cache)
+                      (let ((hash (make-hash-table :test #'equal)))
+                        (plist-put info :footnote-definition-cache hash)
+                        hash))))
+       (or
+        (gethash label cache)
+        (puthash label
+                 (org-element-map (plist-get info :parse-tree)
+                     '(footnote-definition footnote-reference)
+                   (lambda (f)
+                     (cond
+                      ;; Skip any footnote with a different label.
+                      ;; Also skip any standard footnote reference
+                      ;; with the same label since those cannot
+                      ;; contain a definition.
+                      ((not (equal (org-element-property :label f) label)) nil)
+                      ((eq (org-element-property :type f) 'standard) nil)
+                      ((org-element-contents f))
+                      ;; Even if the contents are empty, we can not
+                      ;; return nil since that would eventually raise
+                      ;; the error.  Instead, return the equivalent
+                      ;; empty string.
+                      (t "")))
+                   info t)
+                 cache)
+        (error "Definition not found for footnote %s" label))))))
+
+(defun org-export--footnote-reference-map
+    (function data info &optional body-first)
+  "Apply FUNCTION on every footnote reference in DATA.
+INFO is a plist containing export state.  By default, as soon as
+a new footnote reference is encountered, FUNCTION is called onto
+its definition.  However, if BODY-FIRST is non-nil, this step is
+delayed until the end of the process."
+  (letrec ((definitions nil)
+          (seen-refs nil)
+          (search-ref
+           (lambda (data delayp)
+             ;; Search footnote references through DATA, filling
+             ;; SEEN-REFS along the way.  When DELAYP is non-nil,
+             ;; store footnote definitions so they can be entered
+             ;; later.
+             (org-element-map data 'footnote-reference
+               (lambda (f)
+                 (funcall function f)
+                 (let ((--label (org-element-property :label f)))
+                   (unless (and --label (member --label seen-refs))
+                     (when --label (push --label seen-refs))
+                     ;; Search for subsequent references in footnote
+                     ;; definition so numbering follows reading
+                     ;; logic, unless DELAYP in non-nil.
+                     (cond
+                      (delayp
+                       (push (org-export-get-footnote-definition f info)
+                             definitions))
+                      ;; Do not force entering inline definitions,
+                      ;; since `org-element-map' already traverses
+                      ;; them at the right time.
+                      ((eq (org-element-property :type f) 'inline))
+                      (t (funcall search-ref
+                                  (org-export-get-footnote-definition f info)
+                                  nil))))))
+               info nil
+               ;; Don't enter footnote definitions since it will
+               ;; happen when their first reference is found.
+               ;; Moreover, if DELAYP is non-nil, make sure we
+               ;; postpone entering definitions of inline references.
+               (if delayp '(footnote-definition footnote-reference)
+                 'footnote-definition)))))
+    (funcall search-ref data body-first)
+    (funcall search-ref (nreverse definitions) nil)))
+
+(defun org-export-collect-footnote-definitions (info &optional data body-first)
   "Return an alist between footnote numbers, labels and definitions.
 
-DATA is the parse tree from which definitions are collected.
-INFO is the plist used as a communication channel.
-
-Definitions are sorted by order of references.  They either
-appear as Org data or as a secondary string for inlined
-footnotes.  Unreferenced definitions are ignored."
-  (let* (num-alist
-        collect-fn                     ; for byte-compiler.
-        (collect-fn
-         (function
-          (lambda (data)
-            ;; Collect footnote number, label and definition in DATA.
-            (org-element-map data 'footnote-reference
-              (lambda (fn)
-                (when (org-export-footnote-first-reference-p fn info)
-                  (let ((def (org-export-get-footnote-definition fn info)))
-                    (push
-                     (list (org-export-get-footnote-number fn info)
-                           (org-element-property :label fn)
-                           def)
-                     num-alist)
-                    ;; Also search in definition for nested footnotes.
-                    (when (eq (org-element-property :type fn) 'standard)
-                      (funcall collect-fn def)))))
-              ;; Don't enter footnote definitions since it will happen
-              ;; when their first reference is found.
-              info nil 'footnote-definition)))))
-    (funcall collect-fn (plist-get info :parse-tree))
-    (reverse num-alist)))
-
-(defun org-export-footnote-first-reference-p (footnote-reference info)
+INFO is the current export state, as a plist.
+
+Definitions are collected throughout the whole parse tree, or
+DATA when non-nil.
+
+Sorting is done by order of references.  As soon as a new
+reference is encountered, other references are searched within
+its definition.  However, if BODY-FIRST is non-nil, this step is
+delayed after the whole tree is checked.  This alters results
+when references are found in footnote definitions.
+
+Definitions either appear as Org data or as a secondary string
+for inlined footnotes.  Unreferenced definitions are ignored."
+  (let ((n 0) labels alist)
+    (org-export--footnote-reference-map
+     (lambda (f)
+       ;; Collect footnote number, label and definition.
+       (let ((l (org-element-property :label f)))
+        (unless (and l (member l labels))
+          (cl-incf n)
+          (push (list n l (org-export-get-footnote-definition f info)) alist))
+        (when l (push l labels))))
+     (or data (plist-get info :parse-tree)) info body-first)
+    (nreverse alist)))
+
+(defun org-export-footnote-first-reference-p
+    (footnote-reference info &optional data body-first)
   "Non-nil when a footnote reference is the first one for its label.
 
 FOOTNOTE-REFERENCE is the footnote reference being considered.
-INFO is the plist used as a communication channel."
-  (let ((label (org-element-property :label footnote-reference)))
-    ;; Anonymous footnotes are always a first reference.
-    (if (not label) t
-      ;; Otherwise, return the first footnote with the same LABEL and
-      ;; test if it is equal to FOOTNOTE-REFERENCE.
-      (let* (search-refs               ; for byte-compiler.
-            (search-refs
-             (function
-              (lambda (data)
-                (org-element-map data 'footnote-reference
-                  (lambda (fn)
-                    (cond
-                     ((string= (org-element-property :label fn) label)
-                      (throw 'exit fn))
-                     ;; If FN isn't inlined, be sure to traverse its
-                     ;; definition before resuming search.  See
-                     ;; comments in `org-export-get-footnote-number'
-                     ;; for more information.
-                     ((eq (org-element-property :type fn) 'standard)
-                      (funcall search-refs
-                               (org-export-get-footnote-definition fn info)))))
-                  ;; Don't enter footnote definitions since it will
-                  ;; happen when their first reference is found.
-                  info 'first-match 'footnote-definition)))))
-       (eq (catch 'exit (funcall search-refs (plist-get info :parse-tree)))
-           footnote-reference)))))
+INFO is a plist containing current export state.
 
-(defun org-export-get-footnote-definition (footnote-reference info)
-  "Return definition of FOOTNOTE-REFERENCE as parsed data.
-INFO is the plist used as a communication channel.  If no such
-definition can be found, return the \"DEFINITION NOT FOUND\"
-string."
-  (let ((label (org-element-property :label footnote-reference)))
-    (or (org-element-property :inline-definition footnote-reference)
-        (cdr (assoc label (plist-get info :footnote-definition-alist)))
-       "DEFINITION NOT FOUND.")))
+Search is done throughout the whole parse tree, or DATA when
+non-nil.
 
-(defun org-export-get-footnote-number (footnote info)
+By default, as soon as a new footnote reference is encountered,
+other references are searched within its definition.  However, if
+BODY-FIRST is non-nil, this step is delayed after the whole tree
+is checked.  This alters results when references are found in
+footnote definitions."
+  (let ((label (org-element-property :label footnote-reference)))
+    ;; Anonymous footnotes are always a first reference.
+    (or (not label)
+       (catch 'exit
+         (org-export--footnote-reference-map
+          (lambda (f)
+            (let ((l (org-element-property :label f)))
+              (when (and l label (string= label l))
+                (throw 'exit (eq footnote-reference f)))))
+          (or data (plist-get info :parse-tree)) info body-first)))))
+
+(defun org-export-get-footnote-number (footnote info &optional data body-first)
   "Return number associated to a footnote.
 
 FOOTNOTE is either a footnote reference or a footnote definition.
-INFO is the plist used as a communication channel."
-  (let* ((label (org-element-property :label footnote))
-        seen-refs
-        search-ref                     ; For byte-compiler.
-        (search-ref
-         (function
-          (lambda (data)
-            ;; Search footnote references through DATA, filling
-            ;; SEEN-REFS along the way.
-            (org-element-map data 'footnote-reference
-              (lambda (fn)
-                (let ((fn-lbl (org-element-property :label fn)))
-                  (cond
-                   ;; Anonymous footnote match: return number.
-                   ((and (not fn-lbl) (eq fn footnote))
-                    (throw 'exit (1+ (length seen-refs))))
-                   ;; Labels match: return number.
-                   ((and label (string= label fn-lbl))
-                    (throw 'exit (1+ (length seen-refs))))
-                   ;; Anonymous footnote: it's always a new one.
-                   ;; Also, be sure to return nil from the `cond' so
-                   ;; `first-match' doesn't get us out of the loop.
-                   ((not fn-lbl) (push 'inline seen-refs) nil)
-                   ;; Label not seen so far: add it so SEEN-REFS.
-                   ;;
-                   ;; Also search for subsequent references in
-                   ;; footnote definition so numbering follows
-                   ;; reading logic.  Note that we don't have to care
-                   ;; about inline definitions, since
-                   ;; `org-element-map' already traverses them at the
-                   ;; right time.
-                   ;;
-                   ;; Once again, return nil to stay in the loop.
-                   ((not (member fn-lbl seen-refs))
-                    (push fn-lbl seen-refs)
-                    (funcall search-ref
-                             (org-export-get-footnote-definition fn info))
-                    nil))))
-              ;; Don't enter footnote definitions since it will
-              ;; happen when their first reference is found.
-              info 'first-match 'footnote-definition)))))
-    (catch 'exit (funcall search-ref (plist-get info :parse-tree)))))
+INFO is the plist containing export state.
+
+Number is unique throughout the whole parse tree, or DATA, when
+non-nil.
+
+By default, as soon as a new footnote reference is encountered,
+counting process moves into its definition.  However, if
+BODY-FIRST is non-nil, this step is delayed until the end of the
+process, leading to a different order when footnotes are nested."
+  (let ((count 0)
+       (seen)
+       (label (org-element-property :label footnote)))
+    (catch 'exit
+      (org-export--footnote-reference-map
+       (lambda (f)
+        (let ((l (org-element-property :label f)))
+          (cond
+           ;; Anonymous footnote match: return number.
+           ((and (not l) (not label) (eq footnote f)) (throw 'exit (1+ count)))
+           ;; Labels match: return number.
+           ((and label l (string= label l)) (throw 'exit (1+ count)))
+           ;; Otherwise store label and increase counter if label
+           ;; wasn't encountered yet.
+           ((not l) (cl-incf count))
+           ((not (member l seen)) (push l seen) (cl-incf count)))))
+       (or data (plist-get info :parse-tree)) info body-first))))
 
 
 ;;;; For Headlines
@@ -3657,9 +3877,11 @@ INFO is the plist used as a communication channel."
 ;; `org-export-get-relative-level' is a shortcut to get headline
 ;; level, relatively to the lower headline level in the parsed tree.
 ;;
-;; `org-export-get-headline-number' returns the section number of a
+;; `org-export-get-headline-number' returns the section number of an
 ;; headline, while `org-export-number-to-roman' allows it to be
-;; converted to roman numbers.
+;; converted to roman numbers.  With an optional argument,
+;; `org-export-get-headline-number' returns a number to unnumbered
+;; headlines (used for internal id).
 ;;
 ;; `org-export-low-level-p', `org-export-first-sibling-p' and
 ;; `org-export-last-sibling-p' are three useful predicates when it
@@ -3695,16 +3917,20 @@ and the last level being considered as high enough, or 
nil."
         (and (> level limit) (- level limit))))))
 
 (defun org-export-get-headline-number (headline info)
-  "Return HEADLINE numbering as a list of numbers.
+  "Return numbered HEADLINE numbering as a list of numbers.
 INFO is a plist holding contextual information."
-  (cdr (assoc headline (plist-get info :headline-numbering))))
+  (and (org-export-numbered-headline-p headline info)
+       (cdr (assq headline (plist-get info :headline-numbering)))))
 
 (defun org-export-numbered-headline-p (headline info)
   "Return a non-nil value if HEADLINE element should be numbered.
 INFO is a plist used as a communication channel."
-  (let ((sec-num (plist-get info :section-numbers))
-       (level (org-export-get-relative-level headline info)))
-    (if (wholenump sec-num) (<= level sec-num) sec-num)))
+  (unless (cl-some
+          (lambda (head) (org-not-nil (org-element-property :UNNUMBERED head)))
+          (org-element-lineage headline nil t))
+    (let ((sec-num (plist-get info :section-numbers))
+         (level (org-export-get-relative-level headline info)))
+      (if (wholenump sec-num) (<= level sec-num) sec-num))))
 
 (defun org-export-number-to-roman (n)
   "Convert integer N into a roman numeral."
@@ -3728,30 +3954,21 @@ INFO is a plist used as a communication channel."
 ELEMENT has either an `headline' or an `inlinetask' type.  INFO
 is a plist used as a communication channel.
 
-Select tags (see `org-export-select-tags') and exclude tags (see
-`org-export-exclude-tags') are removed from the list.
-
 When non-nil, optional argument TAGS should be a list of strings.
 Any tag belonging to this list will also be removed.
 
 When optional argument INHERITED is non-nil, tags can also be
 inherited from parent headlines and FILETAGS keywords."
-  (org-remove-if
-   (lambda (tag) (or (member tag (plist-get info :select-tags))
-               (member tag (plist-get info :exclude-tags))
-               (member tag tags)))
+  (cl-remove-if
+   (lambda (tag) (member tag tags))
    (if (not inherited) (org-element-property :tags element)
      ;; Build complete list of inherited tags.
      (let ((current-tag-list (org-element-property :tags element)))
-       (mapc
-       (lambda (parent)
-         (mapc
-          (lambda (tag)
-            (when (and (memq (org-element-type parent) '(headline inlinetask))
-                       (not (member tag current-tag-list)))
-              (push tag current-tag-list)))
-          (org-element-property :tags parent)))
-       (org-export-get-genealogy element))
+       (dolist (parent (org-element-lineage element))
+        (dolist (tag (org-element-property :tags parent))
+          (when (and (memq (org-element-type parent) '(headline inlinetask))
+                     (not (member tag current-tag-list)))
+            (push tag current-tag-list))))
        ;; Add FILETAGS keywords and return results.
        (org-uniquify (append (plist-get info :filetags) current-tag-list))))))
 
@@ -3768,7 +3985,7 @@ Return value is a string or nil."
   (let ((headline (if (eq (org-element-type blob) 'headline) blob
                    (org-export-get-parent-headline blob))))
     (if (not inherited) (org-element-property property blob)
-      (let ((parent headline) value)
+      (let ((parent headline))
        (catch 'found
          (while parent
            (when (plist-member (nth 1 parent) property)
@@ -3783,19 +4000,7 @@ INFO is a plist used as a communication channel.
 CATEGORY is automatically inherited from a parent headline, from
 #+CATEGORY: keyword or created out of original file name.  If all
 fail, the fall-back value is \"???\"."
-  (or (let ((headline (if (eq (org-element-type blob) 'headline) blob
-                       (org-export-get-parent-headline blob))))
-       ;; Almost like `org-export-node-property', but we cannot trust
-       ;; `plist-member' as every headline has a `:CATEGORY'
-       ;; property, would it be nil or equal to "???" (which has the
-       ;; same meaning).
-       (let ((parent headline) value)
-         (catch 'found
-           (while parent
-             (let ((category (org-element-property :CATEGORY parent)))
-               (and category (not (equal "???" category))
-                    (throw 'found category)))
-             (setq parent (org-element-property :parent parent))))))
+  (or (org-export-get-node-property :CATEGORY blob t)
       (org-element-map (plist-get info :parse-tree) 'keyword
        (lambda (kwd)
          (when (equal (org-element-property :key kwd) "CATEGORY")
@@ -3805,23 +4010,27 @@ fail, the fall-back value is \"???\"."
        (and file (file-name-sans-extension (file-name-nondirectory file))))
       "???"))
 
-(defun org-export-get-alt-title (headline info)
+(defun org-export-get-alt-title (headline _)
   "Return alternative title for HEADLINE, as a secondary string.
-INFO is a plist used as a communication channel.  If no optional
-title is defined, fall-back to the regular title."
-  (or (org-element-property :alt-title headline)
-      (org-element-property :title headline)))
-
-(defun org-export-first-sibling-p (headline info)
-  "Non-nil when HEADLINE is the first sibling in its sub-tree.
-INFO is a plist used as a communication channel."
-  (not (eq (org-element-type (org-export-get-previous-element headline info))
-          'headline)))
-
-(defun org-export-last-sibling-p (headline info)
-  "Non-nil when HEADLINE is the last sibling in its sub-tree.
-INFO is a plist used as a communication channel."
-  (not (org-export-get-next-element headline info)))
+If no optional title is defined, fall-back to the regular title."
+  (let ((alt (org-element-property :ALT_TITLE headline)))
+    (if alt (org-element-parse-secondary-string
+            alt (org-element-restriction 'headline) headline)
+      (org-element-property :title headline))))
+
+(defun org-export-first-sibling-p (blob info)
+  "Non-nil when BLOB is the first sibling in its parent.
+BLOB is an element or an object.  If BLOB is a headline, non-nil
+means it is the first sibling in the sub-tree.  INFO is a plist
+used as a communication channel."
+  (memq (org-element-type (org-export-get-previous-element blob info))
+       '(nil section)))
+
+(defun org-export-last-sibling-p (blob info)
+  "Non-nil when BLOB is the last sibling in its parent.
+BLOB is an element or an object.  INFO is a plist used as
+a communication channel."
+  (not (org-export-get-next-element blob info)))
 
 
 ;;;; For Keywords
@@ -3852,8 +4061,8 @@ meant to be translated with `org-export-data' or alike."
 
 ;;;; For Links
 ;;
-;; `org-export-solidify-link-text' turns a string into a safer version
-;; for links, replacing most non-standard characters with hyphens.
+;; `org-export-custom-protocol-maybe' handles custom protocol defined
+;; in `org-link-parameters'.
 ;;
 ;; `org-export-get-coderef-format' returns an appropriate format
 ;; string for coderefs.
@@ -3863,20 +4072,45 @@ meant to be translated with `org-export-data' or alike."
 ;;
 ;; `org-export-resolve-fuzzy-link' searches destination of fuzzy links
 ;; (i.e. links with "fuzzy" as type) within the parsed tree, and
-;; returns an appropriate unique identifier when found, or nil.
+;; returns an appropriate unique identifier.
 ;;
 ;; `org-export-resolve-id-link' returns the first headline with
 ;; specified id or custom-id in parse tree, the path to the external
-;; file with the id or nil when neither was found.
+;; file with the id.
 ;;
 ;; `org-export-resolve-coderef' associates a reference to a line
 ;; number in the element it belongs, or returns the reference itself
 ;; when the element isn't numbered.
+;;
+;; `org-export-file-uri' expands a filename as stored in :path value
+;;  of a "file" link into a file URI.
+;;
+;; Broken links raise a `org-link-broken' error, which is caught by
+;; `org-export-data' for further processing, depending on
+;; `org-export-with-broken-links' value.
 
-(defun org-export-solidify-link-text (s)
-  "Take link text S and make a safe target out of it."
-  (save-match-data
-    (mapconcat 'identity (org-split-string s "[^a-zA-Z0-9_.-:]+") "-")))
+(org-define-error 'org-link-broken "Unable to resolve link; aborting")
+
+(defun org-export-custom-protocol-maybe (link desc backend)
+  "Try exporting LINK with a dedicated function.
+
+DESC is its description, as a string, or nil.  BACKEND is the
+back-end used for export, as a symbol.
+
+Return output as a string, or nil if no protocol handles LINK.
+
+A custom protocol has precedence over regular back-end export.
+The function ignores links with an implicit type (e.g.,
+\"custom-id\")."
+  (let ((type (org-element-property :type link)))
+    (unless (or (member type '("coderef" "custom-id" "fuzzy" "radio"))
+               (not backend))
+      (let ((protocol (org-link-get-parameter type :export)))
+       (and (functionp protocol)
+            (funcall protocol
+                     (org-link-unescape (org-element-property :path link))
+                     desc
+                     backend))))))
 
 (defun org-export-get-coderef-format (path desc)
   "Return format string for code reference link.
@@ -3902,18 +4136,13 @@ the provided rules is non-nil.  The default rule is
 
 This only applies to links without a description."
   (and (not (org-element-contents link))
-       (let ((case-fold-search t)
-            (rules (or rules org-export-default-inline-image-rule)))
+       (let ((case-fold-search t))
         (catch 'exit
-          (mapc
-           (lambda (rule)
-             (and (string= (org-element-property :type link) (car rule))
-                  (string-match (cdr rule)
-                                (org-element-property :path link))
-                  (throw 'exit t)))
-           rules)
-          ;; Return nil if no rule matched.
-          nil))))
+          (dolist (rule (or rules org-export-default-inline-image-rule))
+            (and (string= (org-element-property :type link) (car rule))
+                 (string-match-p (cdr rule)
+                                 (org-element-property :path link))
+                 (throw 'exit t)))))))
 
 (defun org-export-resolve-coderef (ref info)
   "Resolve a code reference REF.
@@ -3921,33 +4150,90 @@ This only applies to links without a description."
 INFO is a plist used as a communication channel.
 
 Return associated line number in source code, or REF itself,
-depending on src-block or example element's switches."
-  (org-element-map (plist-get info :parse-tree) '(example-block src-block)
-    (lambda (el)
-      (with-temp-buffer
-       (insert (org-trim (org-element-property :value el)))
-       (let* ((label-fmt (regexp-quote
-                          (or (org-element-property :label-fmt el)
-                              org-coderef-label-format)))
-              (ref-re
-               (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)\\)[ \t]*$"
-                       (replace-regexp-in-string "%s" ref label-fmt nil t))))
-         ;; Element containing REF is found.  Resolve it to either
-         ;; a label or a line number, as needed.
-         (when (re-search-backward ref-re nil t)
-           (cond
-            ((org-element-property :use-labels el) ref)
-            ((eq (org-element-property :number-lines el) 'continued)
-             (+ (org-export-get-loc el info) (line-number-at-pos)))
-            (t (line-number-at-pos)))))))
-    info 'first-match))
+depending on src-block or example element's switches.  Throw an
+error if no block contains REF."
+  (or (org-element-map (plist-get info :parse-tree) '(example-block src-block)
+       (lambda (el)
+         (with-temp-buffer
+           (insert (org-trim (org-element-property :value el)))
+           (let* ((label-fmt (or (org-element-property :label-fmt el)
+                                 org-coderef-label-format))
+                  (ref-re (org-src-coderef-regexp label-fmt ref)))
+             ;; Element containing REF is found.  Resolve it to
+             ;; either a label or a line number, as needed.
+             (when (re-search-backward ref-re nil t)
+               (if (org-element-property :use-labels el) ref
+                 (+ (or (org-export-get-loc el info) 0)
+                    (line-number-at-pos)))))))
+       info 'first-match)
+      (signal 'org-link-broken (list ref))))
+
+(defun org-export-search-cells (datum)
+  "List search cells for element or object DATUM.
+
+A search cell follows the pattern (TYPE . SEARCH) where
+
+  TYPE is a symbol among `headline', `custom-id', `target' and
+  `other'.
+
+  SEARCH is the string a link is expected to match.  More
+  accurately, it is
+
+    - headline's title, as a list of strings, if TYPE is
+      `headline'.
+
+    - CUSTOM_ID value, as a string, if TYPE is `custom-id'.
+
+    - target's or radio-target's name as a list of strings if
+      TYPE is `target'.
+
+    - NAME affiliated keyword is TYPE is `other'.
+
+A search cell is the internal representation of a fuzzy link.  It
+ignores white spaces and statistics cookies, if applicable."
+  (pcase (org-element-type datum)
+    (`headline
+     (let ((title (split-string
+                  (replace-regexp-in-string
+                   "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" ""
+                   (org-element-property :raw-value datum)))))
+       (delq nil
+            (list
+             (cons 'headline title)
+             (cons 'other title)
+             (let ((custom-id (org-element-property :custom-id datum)))
+               (and custom-id (cons 'custom-id custom-id)))))))
+    (`target
+     (list (cons 'target (split-string (org-element-property :value datum)))))
+    ((and (let name (org-element-property :name datum))
+         (guard name))
+     (list (cons 'other (split-string name))))
+    (_ nil)))
+
+(defun org-export-string-to-search-cell (s)
+  "Return search cells associated to string S.
+S is either the path of a fuzzy link or a search option, i.e., it
+tries to match either a headline (through custom ID or title),
+a target or a named element."
+  (pcase (string-to-char s)
+    (?* (list (cons 'headline (split-string (substring s 1)))))
+    (?# (list (cons 'custom-id (substring s 1))))
+    ((let search (split-string s))
+     (list (cons 'target search) (cons 'other search)))))
+
+(defun org-export-match-search-cell-p (datum cells)
+  "Non-nil when DATUM matches search cells CELLS.
+DATUM is an element or object.  CELLS is a list of search cells,
+as returned by `org-export-search-cells'."
+  (let ((targets (org-export-search-cells datum)))
+    (and targets (cl-some (lambda (cell) (member cell targets)) cells))))
 
 (defun org-export-resolve-fuzzy-link (link info)
   "Return LINK destination.
 
 INFO is a plist holding contextual information.
 
-Return value can be an object, an element, or nil:
+Return value can be an object or an element:
 
 - If LINK path matches a target object (i.e. <<path>>) return it.
 
@@ -3955,86 +4241,43 @@ Return value can be an object, an element, or nil:
   (i.e. #+NAME: path) of an element, return that element.
 
 - If LINK path exactly matches any headline name, return that
-  element.  If more than one headline share that name, priority
-  will be given to the one with the closest common ancestor, if
-  any, or the first one in the parse tree otherwise.
+  element.
 
-- Otherwise, return nil.
+- Otherwise, throw an error.
 
 Assume LINK type is \"fuzzy\".  White spaces are not
 significant."
-  (let* ((raw-path (org-element-property :path link))
-        (match-title-p (eq (aref raw-path 0) ?*))
-        ;; Split PATH at white spaces so matches are space
-        ;; insensitive.
-        (path (org-split-string
-               (if match-title-p (substring raw-path 1) raw-path)))
-        ;; Cache for destinations that are not position dependent.
+  (let* ((search-cells (org-export-string-to-search-cell
+                       (org-link-unescape (org-element-property :path link))))
         (link-cache
          (or (plist-get info :resolve-fuzzy-link-cache)
-             (plist-get (setq info (plist-put info :resolve-fuzzy-link-cache
-                                              (make-hash-table :test 'equal)))
+             (plist-get (plist-put info
+                                   :resolve-fuzzy-link-cache
+                                   (make-hash-table :test #'equal))
                         :resolve-fuzzy-link-cache)))
-        (cached (gethash path link-cache 'not-found)))
-    (cond
-     ;; Destination is not position dependent: use cached value.
-     ((and (not match-title-p) (not (eq cached 'not-found))) cached)
-     ;; First try to find a matching "<<path>>" unless user specified
-     ;; he was looking for a headline (path starts with a "*"
-     ;; character).
-     ((and (not match-title-p)
-          (let ((match (org-element-map (plist-get info :parse-tree) 'target
-                         (lambda (blob)
-                           (and (equal (org-split-string
-                                        (org-element-property :value blob))
-                                       path)
-                                blob))
-                         info 'first-match)))
-            (and match (puthash path match link-cache)))))
-     ;; Then try to find an element with a matching "#+NAME: path"
-     ;; affiliated keyword.
-     ((and (not match-title-p)
-          (let ((match (org-element-map (plist-get info :parse-tree)
-                           org-element-all-elements
-                         (lambda (el)
-                           (let ((name (org-element-property :name el)))
-                             (when (and name
-                                        (equal (org-split-string name) path))
-                               el)))
-                         info 'first-match)))
-            (and match (puthash path match link-cache)))))
-     ;; Last case: link either points to a headline or to nothingness.
-     ;; Try to find the source, with priority given to headlines with
-     ;; the closest common ancestor.  If such candidate is found,
-     ;; return it, otherwise return nil.
-     (t
-      (let ((find-headline
-            (function
-             ;; Return first headline whose `:raw-value' property is
-             ;; NAME in parse tree DATA, or nil.  Statistics cookies
-             ;; are ignored.
-             (lambda (name data)
-               (org-element-map data 'headline
-                 (lambda (headline)
-                   (when (equal (org-split-string
-                                 (replace-regexp-in-string
-                                  "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
-                                  (org-element-property :raw-value headline)))
-                                name)
-                     headline))
-                 info 'first-match)))))
-       ;; Search among headlines sharing an ancestor with link, from
-       ;; closest to farthest.
-       (catch 'exit
-         (mapc
-          (lambda (parent)
-            (let ((foundp (funcall find-headline path parent)))
-              (when foundp (throw 'exit foundp))))
-          (let ((parent-hl (org-export-get-parent-headline link)))
-            (if (not parent-hl) (list (plist-get info :parse-tree))
-              (cons parent-hl (org-export-get-genealogy parent-hl)))))
-         ;; No destination found: return nil.
-         (and (not match-title-p) (puthash path nil link-cache))))))))
+        (cached (gethash search-cells link-cache 'not-found)))
+    (if (not (eq cached 'not-found)) cached
+      (let ((matches
+            (org-element-map (plist-get info :parse-tree)
+                (cons 'target org-element-all-elements)
+              (lambda (datum)
+                (and (org-export-match-search-cell-p datum search-cells)
+                     datum)))))
+       (unless matches
+         (signal 'org-link-broken (list (org-element-property :path link))))
+       (puthash
+        search-cells
+        ;; There can be multiple matches for un-typed searches, i.e.,
+        ;; for searches not starting with # or *.  In this case,
+        ;; prioritize targets and names over headline titles.
+        ;; Matching both a name and a target is not valid, and
+        ;; therefore undefined.
+        (or (cl-some (lambda (datum)
+                       (and (not (eq (org-element-type datum) 'headline))
+                            datum))
+                     matches)
+            (car matches))
+        link-cache)))))
 
 (defun org-export-resolve-id-link (link info)
   "Return headline referenced as LINK destination.
@@ -4042,18 +4285,19 @@ significant."
 INFO is a plist used as a communication channel.
 
 Return value can be the headline element matched in current parse
-tree, a file name or nil.  Assume LINK type is either \"id\" or
-\"custom-id\"."
+tree or a file name.  Assume LINK type is either \"id\" or
+\"custom-id\".  Throw an error if no match is found."
   (let ((id (org-element-property :path link)))
     ;; First check if id is within the current parse tree.
     (or (org-element-map (plist-get info :parse-tree) 'headline
          (lambda (headline)
-           (when (or (string= (org-element-property :ID headline) id)
-                     (string= (org-element-property :CUSTOM_ID headline) id))
+           (when (or (equal (org-element-property :ID headline) id)
+                     (equal (org-element-property :CUSTOM_ID headline) id))
              headline))
          info 'first-match)
        ;; Otherwise, look for external files.
-       (cdr (assoc id (plist-get info :id-alist))))))
+       (cdr (assoc id (plist-get info :id-alist)))
+       (signal 'org-link-broken (list id)))))
 
 (defun org-export-resolve-radio-link (link info)
   "Return radio-target object referenced as LINK destination.
@@ -4074,12 +4318,93 @@ has type \"radio\"."
             radio))
       info 'first-match)))
 
+(defun org-export-file-uri (filename)
+  "Return file URI associated to FILENAME."
+  (cond ((string-prefix-p "//" filename) (concat "file:" filename))
+       ((not (file-name-absolute-p filename)) filename)
+       ((org-file-remote-p filename) (concat "file:/" filename))
+       (t
+        (let ((fullname (expand-file-name filename)))
+          (concat (if (string-prefix-p "/" fullname) "file://" "file:///")
+                  fullname)))))
 
 ;;;; For References
 ;;
+;; `org-export-get-reference' associate a unique reference for any
+;; object or element.  It uses `org-export-new-reference' and
+;; `org-export-format-reference' to, respectively, generate new
+;; internal references and turn them into a string suitable for
+;; output.
+;;
 ;; `org-export-get-ordinal' associates a sequence number to any object
 ;; or element.
 
+(defun org-export-new-reference (references)
+  "Return a unique reference, among REFERENCES.
+REFERENCES is an alist whose values are in-use references, as
+numbers.  Returns a number, which is the internal representation
+of a reference.  See also `org-export-format-reference'."
+  ;; Generate random 7 digits hexadecimal numbers.  Collisions
+  ;; increase exponentially with the numbers of references.  However,
+  ;; the odds for encountering at least one collision with 1000 active
+  ;; references in the same document are roughly 0.2%, so this
+  ;; shouldn't be the bottleneck.
+  (let ((new (random #x10000000)))
+    (while (rassq new references) (setq new (random #x10000000)))
+    new))
+
+(defun org-export-format-reference (reference)
+  "Format REFERENCE into a string.
+REFERENCE is a number representing a reference, as returned by
+`org-export-new-reference', which see."
+  (format "org%07x" reference))
+
+(defun org-export-get-reference (datum info)
+  "Return a unique reference for DATUM, as a string.
+
+DATUM is either an element or an object.  INFO is the current
+export state, as a plist.
+
+This function checks `:crossrefs' property in INFO for search
+cells matching DATUM before creating a new reference.  Returned
+reference consists of alphanumeric characters only."
+  (let ((cache (plist-get info :internal-references)))
+    (or (car (rassq datum cache))
+       (let* ((crossrefs (plist-get info :crossrefs))
+              (cells (org-export-search-cells datum))
+              ;; Preserve any pre-existing association between
+              ;; a search cell and a reference, i.e., when some
+              ;; previously published document referenced a location
+              ;; within current file (see
+              ;; `org-publish-resolve-external-link').
+              ;;
+              ;; However, there is no guarantee that search cells are
+              ;; unique, e.g., there might be duplicate custom ID or
+              ;; two headings with the same title in the file.
+              ;;
+              ;; As a consequence, before re-using any reference to
+              ;; an element or object, we check that it doesn't refer
+              ;; to a previous element or object.
+              (new (or (cl-some
+                        (lambda (cell)
+                          (let ((stored (cdr (assoc cell crossrefs))))
+                            (when stored
+                              (let ((old (org-export-format-reference stored)))
+                                (and (not (assoc old cache)) stored)))))
+                        cells)
+                       (org-export-new-reference cache)))
+              (reference-string (org-export-format-reference new)))
+         ;; Cache contains both data already associated to
+         ;; a reference and in-use internal references, so as to make
+         ;; unique references.
+         (dolist (cell cells) (push (cons cell new) cache))
+         ;; Retain a direct association between reference string and
+         ;; DATUM since (1) not every object or element can be given
+         ;; a search cell (2) it permits quick lookup.
+         (push (cons reference-string datum) cache)
+         (plist-put info :internal-references cache)
+         reference-string))))
+
 (defun org-export-get-ordinal (element info &optional types predicate)
   "Return ordinal number of an element or object.
 
@@ -4107,14 +4432,10 @@ objects of the same type."
   ;; table, item, or headline containing the object.
   (when (eq (org-element-type element) 'target)
     (setq element
-         (loop for parent in (org-export-get-genealogy element)
-               when
-               (memq
-                (org-element-type parent)
-                '(footnote-definition footnote-reference headline item
-                                      table))
-               return parent)))
-  (case (org-element-type element)
+         (org-element-lineage
+          element
+          '(footnote-definition footnote-reference headline item table))))
+  (cl-case (org-element-type element)
     ;; Special case 1: A headline returns its number as a list.
     (headline (org-export-get-headline-number element info))
     ;; Special case 2: An item returns its number as a list.
@@ -4134,8 +4455,8 @@ objects of the same type."
         (lambda (el)
           (cond
            ((eq element el) (1+ counter))
-           ((not predicate) (incf counter) nil)
-           ((funcall predicate el info) (incf counter) nil)))
+           ((not predicate) (cl-incf counter) nil)
+           ((funcall predicate el info) (cl-incf counter) nil)))
         info 'first-match)))))
 
 
@@ -4162,32 +4483,34 @@ objects of the same type."
 ;; code in a format suitable for plain text or verbatim output.
 
 (defun org-export-get-loc (element info)
-  "Return accumulated lines of code up to ELEMENT.
-
-INFO is the plist used as a communication channel.
-
-ELEMENT is excluded from count."
-  (let ((loc 0))
-    (org-element-map (plist-get info :parse-tree)
-       `(src-block example-block ,(org-element-type element))
-      (lambda (el)
-       (cond
-        ;; ELEMENT is reached: Quit the loop.
-        ((eq el element))
-        ;; Only count lines from src-block and example-block elements
-        ;; with a "+n" or "-n" switch.  A "-n" switch resets counter.
-        ((not (memq (org-element-type el) '(src-block example-block))) nil)
-        ((let ((linums (org-element-property :number-lines el)))
-           (when linums
-             ;; Accumulate locs or reset them.
-             (let ((lines (org-count-lines
-                           (org-trim (org-element-property :value el)))))
-               (setq loc (if (eq linums 'new) lines (+ loc lines))))))
-         ;; Return nil to stay in the loop.
-         nil)))
-      info 'first-match)
-    ;; Return value.
-    loc))
+  "Return count of lines of code before ELEMENT.
+
+ELEMENT is an example-block or src-block element.  INFO is the
+plist used as a communication channel.
+
+Count includes every line of code in example-block or src-block
+with a \"+n\" or \"-n\" switch before block.  Return nil if
+ELEMENT doesn't allow line numbering."
+  (pcase (org-element-property :number-lines element)
+    (`(new . ,n) n)
+    (`(continued . ,n)
+     (let ((loc 0))
+       (org-element-map (plist-get info :parse-tree) '(src-block example-block)
+        (lambda (el)
+          ;; ELEMENT is reached: Quit loop and return locs.
+          (if (eq el element) (+ loc n)
+            ;; Only count lines from src-block and example-block
+            ;; elements with a "+n" or "-n" switch.
+            (let ((linum (org-element-property :number-lines el)))
+              (when linum
+                (let ((lines (org-count-lines
+                              (org-element-property :value el))))
+                  ;; Accumulate locs or reset them.
+                  (pcase linum
+                    (`(new . ,n) (setq loc (+ n lines)))
+                    (`(continued . ,n) (cl-incf loc (+ n lines)))))))
+            nil))                    ;Return nil to stay in the loop.
+        info 'first-match)))))
 
 (defun org-export-unravel-code (element)
   "Clean source code and extract references out of it.
@@ -4195,38 +4518,33 @@ ELEMENT is excluded from count."
 ELEMENT has either a `src-block' an `example-block' type.
 
 Return a cons cell whose CAR is the source code, cleaned from any
-reference and protective comma and CDR is an alist between
-relative line number (integer) and name of code reference on that
-line (string)."
+reference, protective commas and spurious indentation, and CDR is
+an alist between relative line number (integer) and name of code
+reference on that line (string)."
   (let* ((line 0) refs
-        ;; Get code and clean it.  Remove blank lines at its
-        ;; beginning and end.
+        (value (org-element-property :value element))
+        ;; Remove global indentation from code, if necessary.  Also
+        ;; remove final newline character, since it doesn't belongs
+        ;; to the code proper.
         (code (replace-regexp-in-string
-               "\\`\\([ \t]*\n\\)+" ""
-               (replace-regexp-in-string
-                "\\([ \t]*\n\\)*[ \t]*\\'" "\n"
-                (org-element-property :value element))))
-        ;; Get format used for references.
-        (label-fmt (regexp-quote
-                    (or (org-element-property :label-fmt element)
-                        org-coderef-label-format)))
+               "\n\\'" ""
+               (if (or org-src-preserve-indentation
+                       (org-element-property :preserve-indent element))
+                   value
+                 (org-remove-indentation value))))
         ;; Build a regexp matching a loc with a reference.
-        (with-ref-re
-         (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)[ \t]*\\)$"
-                 (replace-regexp-in-string
-                  "%s" "\\([-a-zA-Z0-9_ ]+\\)" label-fmt nil t))))
+        (ref-re (org-src-coderef-regexp (org-src-coderef-format element))))
     ;; Return value.
     (cons
      ;; Code with references removed.
-     (org-element-normalize-string
-      (mapconcat
-       (lambda (loc)
-        (incf line)
-        (if (not (string-match with-ref-re loc)) loc
-          ;; Ref line: remove ref, and signal its position in REFS.
-          (push (cons line (match-string 3 loc)) refs)
-          (replace-match "" nil nil loc 1)))
-       (org-split-string code "\n") "\n"))
+     (mapconcat
+      (lambda (loc)
+       (cl-incf line)
+       (if (not (string-match ref-re loc)) loc
+         ;; Ref line: remove ref, and add its position in REFS.
+         (push (cons line (match-string 3 loc)) refs)
+         (replace-match "" nil nil loc 1)))
+      (split-string code "\n") "\n")
      ;; Reference alist.
      refs)))
 
@@ -4249,15 +4567,16 @@ number (i.e. ignoring NUM-LINES) and the name of the 
code
 reference on it.  If it is nil, FUN's third argument will always
 be nil.  It can be obtained through the use of
 `org-export-unravel-code' function."
-  (let ((--locs (org-split-string code "\n"))
+  (let ((--locs (split-string code "\n"))
        (--line 0))
-    (org-element-normalize-string
+    (concat
      (mapconcat
       (lambda (--loc)
-       (incf --line)
+       (cl-incf --line)
        (let ((--ref (cdr (assq --line ref-alist))))
          (funcall fun --loc (and num-lines (+ num-lines --line)) --ref)))
-      --locs "\n"))))
+      --locs "\n")
+     "\n")))
 
 (defun org-export-format-code-default (element info)
   "Return source code from ELEMENT, formatted in a standard way.
@@ -4274,14 +4593,12 @@ code."
   ;; Extract code and references.
   (let* ((code-info (org-export-unravel-code element))
          (code (car code-info))
-        (code-lines (org-split-string code "\n")))
+        (code-lines (split-string code "\n")))
     (if (null code-lines) ""
       (let* ((refs (and (org-element-property :retain-labels element)
                        (cdr code-info)))
             ;; Handle line numbering.
-            (num-start (case (org-element-property :number-lines element)
-                         (continued (org-export-get-loc element info))
-                         (new 0)))
+            (num-start (org-export-get-loc element info))
             (num-fmt
              (and num-start
                   (format "%%%ds  "
@@ -4301,9 +4618,9 @@ code."
              number-str
              loc
              (and ref
-                  (concat (make-string
-                           (- (+ 6 max-width)
-                              (+ (length loc) (length number-str))) ? )
+                  (concat (make-string (- (+ 6 max-width)
+                                          (+ (length loc) (length number-str)))
+                                       ?\s)
                           (format "(%s)" ref))))))
         num-start refs)))))
 
@@ -4331,9 +4648,10 @@ code."
 ;; `org-export-table-cell-ends-colgroup-p',
 ;; `org-export-table-row-starts-rowgroup-p',
 ;; `org-export-table-row-ends-rowgroup-p',
-;; `org-export-table-row-starts-header-p' and
-;; `org-export-table-row-ends-header-p' indicate position of current
-;; row or cell within the table.
+;; `org-export-table-row-starts-header-p',
+;; `org-export-table-row-ends-header-p' and
+;; `org-export-table-row-in-header-p' indicate position of current row
+;; or cell within the table.
 
 (defun org-export-table-has-special-column-p (table)
   "Non-nil when TABLE has a special column.
@@ -4344,16 +4662,14 @@ All special columns will be ignored during export."
   ;; only empty cells as special.
   (let ((special-column-p 'empty))
     (catch 'exit
-      (mapc
-       (lambda (row)
-        (when (eq (org-element-property :type row) 'standard)
-          (let ((value (org-element-contents
-                        (car (org-element-contents row)))))
-            (cond ((member value '(("/") ("#") ("!") ("$") ("*") ("_") ("^")))
-                   (setq special-column-p 'special))
-                  ((not value))
-                  (t (throw 'exit nil))))))
-       (org-element-contents table))
+      (dolist (row (org-element-contents table))
+       (when (eq (org-element-property :type row) 'standard)
+         (let ((value (org-element-contents
+                       (car (org-element-contents row)))))
+           (cond ((member value '(("/") ("#") ("!") ("$") ("*") ("_") ("^")))
+                  (setq special-column-p 'special))
+                 ((not value))
+                 (t (throw 'exit nil))))))
       (eq special-column-p 'special))))
 
 (defun org-export-table-has-header-p (table info)
@@ -4376,18 +4692,15 @@ A table has a header when it contains at least two row 
groups."
               (cond
                ((> rowgroup 1) t)
                ((and row-flag (eq (org-element-property :type row) 'rule))
-                (incf rowgroup) (setq row-flag nil))
+                (cl-incf rowgroup) (setq row-flag nil))
                ((and (not row-flag) (eq (org-element-property :type row)
                                         'standard))
                 (setq row-flag t) nil)))
             info 'first-match)
           cache)))))
 
-(defun org-export-table-row-is-special-p (table-row info)
+(defun org-export-table-row-is-special-p (table-row _)
   "Non-nil if TABLE-ROW is considered special.
-
-INFO is a plist used as the communication channel.
-
 All special rows will be ignored during export."
   (when (eq (org-element-property :type table-row) 'standard)
     (let ((first-cell (org-element-contents
@@ -4404,19 +4717,17 @@ All special rows will be ignored during export."
        ;; ... it contains only alignment cookies and empty cells.
        (let ((special-row-p 'empty))
         (catch 'exit
-          (mapc
-           (lambda (cell)
-             (let ((value (org-element-contents cell)))
-               ;; Since VALUE is a secondary string, the following
-               ;; checks avoid expanding it with `org-export-data'.
-               (cond ((not value))
-                     ((and (not (cdr value))
-                           (stringp (car value))
-                           (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'"
-                                         (car value)))
-                      (setq special-row-p 'cookie))
-                     (t (throw 'exit nil)))))
-           (org-element-contents table-row))
+          (dolist (cell (org-element-contents table-row))
+            (let ((value (org-element-contents cell)))
+              ;; Since VALUE is a secondary string, the following
+              ;; checks avoid expanding it with `org-export-data'.
+              (cond ((not value))
+                    ((and (not (cdr value))
+                          (stringp (car value))
+                          (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'"
+                                        (car value)))
+                     (setq special-row-p 'cookie))
+                    (t (throw 'exit nil)))))
           (eq special-row-p 'cookie)))))))
 
 (defun org-export-table-row-group (table-row info)
@@ -4439,7 +4750,7 @@ header."
                 (lambda (row)
                   (if (eq (org-element-property :type row) 'rule)
                       (setq row-flag nil)
-                    (unless row-flag (incf group) (setq row-flag t)))
+                    (unless row-flag (cl-incf group) (setq row-flag t)))
                   (when (eq table-row row) (puthash table-row group cache)))
                 info 'first-match))))))
 
@@ -4539,14 +4850,14 @@ Possible values are `left', `right' and `center'."
                            (org-element-contents
                             (elt (org-element-contents row) column))
                            info)))
-               (incf total-cells)
+               (cl-incf total-cells)
                ;; Treat an empty cell as a number if it follows
                ;; a number.
                (if (not (or (string-match org-table-number-regexp value)
                             (and (string= value "") previous-cell-number-p)))
                    (setq previous-cell-number-p nil)
                  (setq previous-cell-number-p t)
-                 (incf number-cells))))))
+                 (cl-incf number-cells))))))
          ;; Return value.  Alignment specified by cookies has
          ;; precedence over alignment deduced from cell's contents.
          (aset align-vector
@@ -4579,14 +4890,13 @@ Returned borders ignore special rows."
     ;; another regular row has to be found above that rule.
     (let (rule-flag)
       (catch 'exit
-       (mapc (lambda (row)
-               (cond ((eq (org-element-property :type row) 'rule)
-                      (setq rule-flag t))
-                     ((not (org-export-table-row-is-special-p row info))
-                      (if rule-flag (throw 'exit (push 'above borders))
-                        (throw 'exit nil)))))
-             ;; Look at every row before the current one.
-             (cdr (memq row (reverse (org-element-contents table)))))
+       ;; Look at every row before the current one.
+       (dolist (row (cdr (memq row (reverse (org-element-contents table)))))
+         (cond ((eq (org-element-property :type row) 'rule)
+                (setq rule-flag t))
+               ((not (org-export-table-row-is-special-p row info))
+                (if rule-flag (throw 'exit (push 'above borders))
+                  (throw 'exit nil)))))
        ;; No rule above, or rule found starts the table (ignoring any
        ;; special row): TABLE-CELL is at the top of the table.
        (when rule-flag (push 'above borders))
@@ -4595,14 +4905,13 @@ Returned borders ignore special rows."
     ;; non-regular row below is a rule.
     (let (rule-flag)
       (catch 'exit
-       (mapc (lambda (row)
-               (cond ((eq (org-element-property :type row) 'rule)
-                      (setq rule-flag t))
-                     ((not (org-export-table-row-is-special-p row info))
-                      (if rule-flag (throw 'exit (push 'below borders))
-                        (throw 'exit nil)))))
-             ;; Look at every row after the current one.
-             (cdr (memq row (org-element-contents table))))
+       ;; Look at every row after the current one.
+       (dolist (row (cdr (memq row (org-element-contents table))))
+         (cond ((eq (org-element-property :type row) 'rule)
+                (setq rule-flag t))
+               ((not (org-export-table-row-is-special-p row info))
+                (if rule-flag (throw 'exit (push 'below borders))
+                  (throw 'exit nil)))))
        ;; No rule below, or rule found ends the table (modulo some
        ;; special row): TABLE-CELL is at the bottom of the table.
        (when rule-flag (push 'below borders))
@@ -4614,42 +4923,40 @@ Returned borders ignore special rows."
     (catch 'exit
       (let ((column (let ((cells (org-element-contents row)))
                      (- (length cells) (length (memq table-cell cells))))))
-       (mapc
-        (lambda (row)
-          (unless (eq (org-element-property :type row) 'rule)
-            (when (equal (org-element-contents
-                          (car (org-element-contents row)))
-                         '("/"))
-              (let ((column-groups
-                     (mapcar
-                      (lambda (cell)
-                        (let ((value (org-element-contents cell)))
-                          (when (member value '(("<") ("<>") (">") nil))
-                            (car value))))
-                      (org-element-contents row))))
-                ;; There's a left border when previous cell, if
-                ;; any, ends a group, or current one starts one.
-                (when (or (and (not (zerop column))
-                               (member (elt column-groups (1- column))
-                                       '(">" "<>")))
-                          (member (elt column-groups column) '("<" "<>")))
-                  (push 'left borders))
-                ;; There's a right border when next cell, if any,
-                ;; starts a group, or current one ends one.
-                (when (or (and (/= (1+ column) (length column-groups))
-                               (member (elt column-groups (1+ column))
-                                       '("<" "<>")))
-                          (member (elt column-groups column) '(">" "<>")))
-                  (push 'right borders))
-                (throw 'exit nil)))))
-        ;; Table rows are read in reverse order so last column groups
-        ;; row has precedence over any previous one.
-        (reverse (org-element-contents table)))))
+       ;; Table rows are read in reverse order so last column groups
+       ;; row has precedence over any previous one.
+       (dolist (row (reverse (org-element-contents table)))
+         (unless (eq (org-element-property :type row) 'rule)
+           (when (equal (org-element-contents
+                         (car (org-element-contents row)))
+                        '("/"))
+             (let ((column-groups
+                    (mapcar
+                     (lambda (cell)
+                       (let ((value (org-element-contents cell)))
+                         (when (member value '(("<") ("<>") (">") nil))
+                           (car value))))
+                     (org-element-contents row))))
+               ;; There's a left border when previous cell, if
+               ;; any, ends a group, or current one starts one.
+               (when (or (and (not (zerop column))
+                              (member (elt column-groups (1- column))
+                                      '(">" "<>")))
+                         (member (elt column-groups column) '("<" "<>")))
+                 (push 'left borders))
+               ;; There's a right border when next cell, if any,
+               ;; starts a group, or current one ends one.
+               (when (or (and (/= (1+ column) (length column-groups))
+                              (member (elt column-groups (1+ column))
+                                      '("<" "<>")))
+                         (member (elt column-groups column) '(">" "<>")))
+                 (push 'right borders))
+               (throw 'exit nil)))))))
     ;; Return value.
     borders))
 
 (defun org-export-table-cell-starts-colgroup-p (table-cell info)
-  "Non-nil when TABLE-CELL is at the beginning of a row group.
+  "Non-nil when TABLE-CELL is at the beginning of a column group.
 INFO is a plist used as a communication channel."
   ;; A cell starts a column group either when it is at the beginning
   ;; of a row (or after the special column, if any) or when it has
@@ -4660,7 +4967,7 @@ INFO is a plist used as a communication channel."
       (memq 'left (org-export-table-cell-borders table-cell info))))
 
 (defun org-export-table-cell-ends-colgroup-p (table-cell info)
-  "Non-nil when TABLE-CELL is at the end of a row group.
+  "Non-nil when TABLE-CELL is at the end of a column group.
 INFO is a plist used as a communication channel."
   ;; A cell ends a column group either when it is at the end of a row
   ;; or when it has a right border.
@@ -4670,7 +4977,7 @@ INFO is a plist used as a communication channel."
       (memq 'right (org-export-table-cell-borders table-cell info))))
 
 (defun org-export-table-row-starts-rowgroup-p (table-row info)
-  "Non-nil when TABLE-ROW is at the beginning of a column group.
+  "Non-nil when TABLE-ROW is at the beginning of a row group.
 INFO is a plist used as a communication channel."
   (unless (or (eq (org-element-property :type table-row) 'rule)
              (org-export-table-row-is-special-p table-row info))
@@ -4679,7 +4986,7 @@ INFO is a plist used as a communication channel."
       (or (memq 'top borders) (memq 'above borders)))))
 
 (defun org-export-table-row-ends-rowgroup-p (table-row info)
-  "Non-nil when TABLE-ROW is at the end of a column group.
+  "Non-nil when TABLE-ROW is at the end of a row group.
 INFO is a plist used as a communication channel."
   (unless (or (eq (org-element-property :type table-row) 'rule)
              (org-export-table-row-is-special-p table-row info))
@@ -4687,21 +4994,25 @@ INFO is a plist used as a communication channel."
                    (car (org-element-contents table-row)) info)))
       (or (memq 'bottom borders) (memq 'below borders)))))
 
+(defun org-export-table-row-in-header-p (table-row info)
+  "Non-nil when TABLE-ROW is located within table's header.
+INFO is a plist used as a communication channel.  Always return
+nil for special rows and rows separators."
+  (and (org-export-table-has-header-p
+       (org-export-get-parent-table table-row) info)
+       (eql (org-export-table-row-group table-row info) 1)))
+
 (defun org-export-table-row-starts-header-p (table-row info)
   "Non-nil when TABLE-ROW is the first table header's row.
 INFO is a plist used as a communication channel."
-  (and (org-export-table-has-header-p
-       (org-export-get-parent-table table-row) info)
-       (org-export-table-row-starts-rowgroup-p table-row info)
-       (= (org-export-table-row-group table-row info) 1)))
+  (and (org-export-table-row-in-header-p table-row info)
+       (org-export-table-row-starts-rowgroup-p table-row info)))
 
 (defun org-export-table-row-ends-header-p (table-row info)
   "Non-nil when TABLE-ROW is the last table header's row.
 INFO is a plist used as a communication channel."
-  (and (org-export-table-has-header-p
-       (org-export-get-parent-table table-row) info)
-       (org-export-table-row-ends-rowgroup-p table-row info)
-       (= (org-export-table-row-group table-row info) 1)))
+  (and (org-export-table-row-in-header-p table-row info)
+       (org-export-table-row-ends-rowgroup-p table-row info)))
 
 (defun org-export-table-row-number (table-row info)
   "Return TABLE-ROW number.
@@ -4715,7 +5026,7 @@ special columns and separators."
        (lambda (row)
          (cond ((eq row table-row) number)
                ((eq (org-element-property :type row) 'standard)
-                (incf number) nil)))
+                (cl-incf number) nil)))
        info 'first-match))))
 
 (defun org-export-table-dimensions (table info)
@@ -4731,10 +5042,10 @@ rows (resp. columns)."
     (org-element-map table 'table-row
       (lambda (row)
        (when (eq (org-element-property :type row) 'standard)
-         (incf rows)
+         (cl-incf rows)
          (unless first-row (setq first-row row)))) info)
     ;; Set number of columns.
-    (org-element-map first-row 'table-cell (lambda (cell) (incf columns)) info)
+    (org-element-map first-row 'table-cell (lambda (_) (cl-incf columns)) info)
     ;; Return value.
     (cons rows columns)))
 
@@ -4754,7 +5065,7 @@ function returns nil for other cells."
            (let ((col-count 0))
              (org-element-map table-row 'table-cell
                (lambda (cell)
-                 (if (eq cell table-cell) col-count (incf col-count) nil))
+                 (if (eq cell table-cell) col-count (cl-incf col-count) nil))
                info 'first-match))))))
 
 (defun org-export-get-table-cell-at (address table info)
@@ -4774,12 +5085,12 @@ return nil."
            (lambda (row)
              (cond ((eq (org-element-property :type row) 'rule) nil)
                    ((= row-count row-pos) row)
-                   (t (incf row-count) nil)))
+                   (t (cl-incf row-count) nil)))
            info 'first-match))
        'table-cell
       (lambda (cell)
        (if (= column-count column-pos) cell
-         (incf column-count) nil))
+         (cl-incf column-count) nil))
       info 'first-match)))
 
 
@@ -4794,7 +5105,7 @@ return nil."
 ;; `org-export-collect-tables', `org-export-collect-figures' and
 ;; `org-export-collect-listings' can be derived from it.
 
-(defun org-export-collect-headlines (info &optional n)
+(defun org-export-collect-headlines (info &optional n scope)
   "Collect headlines in order to build a table of contents.
 
 INFO is a plist used as a communication channel.
@@ -4804,15 +5115,28 @@ the table of contents.  Otherwise, it is set to the 
value of the
 last headline level.  See `org-export-headline-levels' for more
 information.
 
+Optional argument SCOPE, when non-nil, is an element.  If it is
+a headline, only children of SCOPE are collected.  Otherwise,
+collect children of the headline containing provided element.  If
+there is no such headline, collect all headlines.  In any case,
+argument N becomes relative to the level of that headline.
+
 Return a list of all exportable headlines as parsed elements.
-Footnote sections, if any, will be ignored."
-  (let ((limit (plist-get info :headline-levels)))
-    (setq n (if (wholenump n) (min n limit) limit))
-    (org-element-map (plist-get info :parse-tree) 'headline
-      #'(lambda (headline)
-         (unless (org-element-property :footnote-section-p headline)
-           (let ((level (org-export-get-relative-level headline info)))
-             (and (<= level n) headline))))
+Footnote sections are ignored."
+  (let* ((scope (cond ((not scope) (plist-get info :parse-tree))
+                     ((eq (org-element-type scope) 'headline) scope)
+                     ((org-export-get-parent-headline scope))
+                     (t (plist-get info :parse-tree))))
+        (limit (plist-get info :headline-levels))
+        (n (if (not (wholenump n)) limit
+             (min (if (eq (org-element-type scope) 'org-data) n
+                    (+ (org-export-get-relative-level scope info) n))
+                  limit))))
+    (org-element-map (org-element-contents scope) 'headline
+      (lambda (headline)
+       (unless (org-element-property :footnote-section-p headline)
+         (let ((level (org-export-get-relative-level headline info)))
+           (and (<= level n) headline))))
       info)))
 
 (defun org-export-collect-elements (type info &optional predicate)
@@ -4874,131 +5198,215 @@ Return a list of src-block elements with a caption."
 ;;
 ;; Dictionary for smart quotes is stored in
 ;; `org-export-smart-quotes-alist'.
-;;
-;; Internally, regexps matching potential smart quotes (checks at
-;; string boundaries are also necessary) are defined in
-;; `org-export-smart-quotes-regexps'.
 
 (defconst org-export-smart-quotes-alist
   '(("da"
      ;; one may use: »...«, "...", ›...‹, or '...'.
      ;; 
http://sproget.dk/raad-og-regler/retskrivningsregler/retskrivningsregler/a7-40-60/a7-58-anforselstegn/
      ;; LaTeX quotes require Babel!
-     (opening-double-quote :utf-8 "»" :html "&raquo;" :latex ">>"
-                          :texinfo "@guillemetright{}")
-     (closing-double-quote :utf-8 "«" :html "&laquo;" :latex "<<"
-                          :texinfo "@guillemetleft{}")
-     (opening-single-quote :utf-8 "›" :html "&rsaquo;" :latex "\\frq{}"
-                          :texinfo "@guilsinglright{}")
-     (closing-single-quote :utf-8 "‹" :html "&lsaquo;" :latex "\\flq{}"
-                          :texinfo "@guilsingleft{}")
+     (primary-opening
+      :utf-8 "»" :html "&raquo;" :latex ">>" :texinfo "@guillemetright{}")
+     (primary-closing
+      :utf-8 "«" :html "&laquo;" :latex "<<" :texinfo "@guillemetleft{}")
+     (secondary-opening
+      :utf-8 "›" :html "&rsaquo;" :latex "\\frq{}" :texinfo 
"@guilsinglright{}")
+     (secondary-closing
+      :utf-8 "‹" :html "&lsaquo;" :latex "\\flq{}" :texinfo "@guilsingleft{}")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("de"
-     (opening-double-quote :utf-8 "„" :html "&bdquo;" :latex "\"`"
-                          :texinfo "@quotedblbase{}")
-     (closing-double-quote :utf-8 "“" :html "&ldquo;" :latex "\"'"
-                          :texinfo "@quotedblleft{}")
-     (opening-single-quote :utf-8 "‚" :html "&sbquo;" :latex "\\glq{}"
-                          :texinfo "@quotesinglbase{}")
-     (closing-single-quote :utf-8 "‘" :html "&lsquo;" :latex "\\grq{}"
-                          :texinfo "@quoteleft{}")
+     (primary-opening
+      :utf-8 "„" :html "&bdquo;" :latex "\"`" :texinfo "@quotedblbase{}")
+     (primary-closing
+      :utf-8 "“" :html "&ldquo;" :latex "\"'" :texinfo "@quotedblleft{}")
+     (secondary-opening
+      :utf-8 "‚" :html "&sbquo;" :latex "\\glq{}" :texinfo "@quotesinglbase{}")
+     (secondary-closing
+      :utf-8 "‘" :html "&lsquo;" :latex "\\grq{}" :texinfo "@quoteleft{}")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("en"
-     (opening-double-quote :utf-8 "“" :html "&ldquo;" :latex "``" :texinfo 
"``")
-     (closing-double-quote :utf-8 "”" :html "&rdquo;" :latex "''" :texinfo 
"''")
-     (opening-single-quote :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
-     (closing-single-quote :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
+     (primary-opening :utf-8 "“" :html "&ldquo;" :latex "``" :texinfo "``")
+     (primary-closing :utf-8 "”" :html "&rdquo;" :latex "''" :texinfo "''")
+     (secondary-opening :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
+     (secondary-closing :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("es"
-     (opening-double-quote :utf-8 "«" :html "&laquo;" :latex 
"\\guillemotleft{}"
-                          :texinfo "@guillemetleft{}")
-     (closing-double-quote :utf-8 "»" :html "&raquo;" :latex 
"\\guillemotright{}"
-                          :texinfo "@guillemetright{}")
-     (opening-single-quote :utf-8 "“" :html "&ldquo;" :latex "``" :texinfo 
"``")
-     (closing-single-quote :utf-8 "”" :html "&rdquo;" :latex "''" :texinfo 
"''")
+     (primary-opening
+      :utf-8 "«" :html "&laquo;" :latex "\\guillemotleft{}"
+      :texinfo "@guillemetleft{}")
+     (primary-closing
+      :utf-8 "»" :html "&raquo;" :latex "\\guillemotright{}"
+      :texinfo "@guillemetright{}")
+     (secondary-opening :utf-8 "“" :html "&ldquo;" :latex "``" :texinfo "``")
+     (secondary-closing :utf-8 "”" :html "&rdquo;" :latex "''" :texinfo "''")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("fr"
-     (opening-double-quote :utf-8 "« " :html "&laquo;&nbsp;" :latex "\\og "
-                          :texinfo "@address@hidden")
-     (closing-double-quote :utf-8 " »" :html "&nbsp;&raquo;" :latex "\\fg{}"
-                          :texinfo "@address@hidden")
-     (opening-single-quote :utf-8 "« " :html "&laquo;&nbsp;" :latex "\\og "
-                          :texinfo "@address@hidden")
-     (closing-single-quote :utf-8 " »" :html "&nbsp;&raquo;" :latex "\\fg{}"
-                          :texinfo "@address@hidden")
+     (primary-opening
+      :utf-8 "« " :html "&laquo;&nbsp;" :latex "\\og "
+      :texinfo "@address@hidden")
+     (primary-closing
+      :utf-8 " »" :html "&nbsp;&raquo;" :latex "\\fg{}"
+      :texinfo "@address@hidden")
+     (secondary-opening
+      :utf-8 "« " :html "&laquo;&nbsp;" :latex "\\og "
+      :texinfo "@address@hidden")
+     (secondary-closing :utf-8 " »" :html "&nbsp;&raquo;" :latex "\\fg{}"
+                       :texinfo "@address@hidden")
+     (apostrophe :utf-8 "’" :html "&rsquo;"))
+    ("is"
+     (primary-opening
+      :utf-8 "„" :html "&bdquo;" :latex "\"`" :texinfo "@quotedblbase{}")
+     (primary-closing
+      :utf-8 "“" :html "&ldquo;" :latex "\"'" :texinfo "@quotedblleft{}")
+     (secondary-opening
+      :utf-8 "‚" :html "&sbquo;" :latex "\\glq{}" :texinfo "@quotesinglbase{}")
+     (secondary-closing
+      :utf-8 "‘" :html "&lsquo;" :latex "\\grq{}" :texinfo "@quoteleft{}")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("no"
      ;; https://nn.wikipedia.org/wiki/Sitatteikn
-     (opening-double-quote :utf-8 "«" :html "&laquo;" :latex 
"\\guillemotleft{}"
-                          :texinfo "@guillemetleft{}")
-     (closing-double-quote :utf-8 "»" :html "&raquo;" :latex 
"\\guillemotright{}"
-                          :texinfo "@guillemetright{}")
-     (opening-single-quote :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
-     (closing-single-quote :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
+     (primary-opening
+      :utf-8 "«" :html "&laquo;" :latex "\\guillemotleft{}"
+      :texinfo "@guillemetleft{}")
+     (primary-closing
+      :utf-8 "»" :html "&raquo;" :latex "\\guillemotright{}"
+      :texinfo "@guillemetright{}")
+     (secondary-opening :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
+     (secondary-closing :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("nb"
      ;; https://nn.wikipedia.org/wiki/Sitatteikn
-     (opening-double-quote :utf-8 "«" :html "&laquo;" :latex 
"\\guillemotleft{}"
-                          :texinfo "@guillemetleft{}")
-     (closing-double-quote :utf-8 "»" :html "&raquo;" :latex 
"\\guillemotright{}"
-                          :texinfo "@guillemetright{}")
-     (opening-single-quote :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
-     (closing-single-quote :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
+     (primary-opening
+      :utf-8 "«" :html "&laquo;" :latex "\\guillemotleft{}"
+      :texinfo "@guillemetleft{}")
+     (primary-closing
+      :utf-8 "»" :html "&raquo;" :latex "\\guillemotright{}"
+      :texinfo "@guillemetright{}")
+     (secondary-opening :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
+     (secondary-closing :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
     ("nn"
      ;; https://nn.wikipedia.org/wiki/Sitatteikn
-     (opening-double-quote :utf-8 "«" :html "&laquo;" :latex 
"\\guillemotleft{}"
-                          :texinfo "@guillemetleft{}")
-     (closing-double-quote :utf-8 "»" :html "&raquo;" :latex 
"\\guillemotright{}"
-                          :texinfo "@guillemetright{}")
-     (opening-single-quote :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
-     (closing-single-quote :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
+     (primary-opening
+      :utf-8 "«" :html "&laquo;" :latex "\\guillemotleft{}"
+      :texinfo "@guillemetleft{}")
+     (primary-closing
+      :utf-8 "»" :html "&raquo;" :latex "\\guillemotright{}"
+      :texinfo "@guillemetright{}")
+     (secondary-opening :utf-8 "‘" :html "&lsquo;" :latex "`" :texinfo "`")
+     (secondary-closing :utf-8 "’" :html "&rsquo;" :latex "'" :texinfo "'")
      (apostrophe :utf-8 "’" :html "&rsquo;"))
+    ("ru"
+     ;; 
http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%B2%D1%8B%D1%87%D0%BA%D0%B8#.D0.9A.D0.B0.D0.B2.D1.8B.D1.87.D0.BA.D0.B8.2C_.D0.B8.D1.81.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D1.83.D0.B5.D0.BC.D1.8B.D0.B5_.D0.B2_.D1.80.D1.83.D1.81.D1.81.D0.BA.D0.BE.D0.BC_.D1.8F.D0.B7.D1.8B.D0.BA.D0.B5
+     ;; http://www.artlebedev.ru/kovodstvo/sections/104/
+     (primary-opening :utf-8 "«" :html "&laquo;" :latex "{}<<"
+                     :texinfo "@guillemetleft{}")
+     (primary-closing :utf-8 "»" :html "&raquo;" :latex ">>{}"
+                     :texinfo "@guillemetright{}")
+     (secondary-opening
+      :utf-8 "„" :html "&bdquo;" :latex "\\glqq{}" :texinfo "@quotedblbase{}")
+     (secondary-closing
+      :utf-8 "“" :html "&ldquo;" :latex "\\grqq{}" :texinfo "@quotedblleft{}")
+     (apostrophe :utf-8 "’" :html: "&#39;"))
     ("sv"
      ;; based on https://sv.wikipedia.org/wiki/Citattecken
-     (opening-double-quote :utf-8 "”" :html "&rdquo;" :latex "’’" :texinfo 
"’’")
-     (closing-double-quote :utf-8 "”" :html "&rdquo;" :latex "’’" :texinfo 
"’’")
-     (opening-single-quote :utf-8 "’" :html "&rsquo;" :latex "’" :texinfo "`")
-     (closing-single-quote :utf-8 "’" :html "&rsquo;" :latex "’" :texinfo "'")
-     (apostrophe :utf-8 "’" :html "&rsquo;"))
-    )
+     (primary-opening :utf-8 "”" :html "&rdquo;" :latex "’’" :texinfo "’’")
+     (primary-closing :utf-8 "”" :html "&rdquo;" :latex "’’" :texinfo "’’")
+     (secondary-opening :utf-8 "’" :html "&rsquo;" :latex "’" :texinfo "`")
+     (secondary-closing :utf-8 "’" :html "&rsquo;" :latex "’" :texinfo "'")
+     (apostrophe :utf-8 "’" :html "&rsquo;")))
   "Smart quotes translations.
 
 Alist whose CAR is a language string and CDR is an alist with
 quote type as key and a plist associating various encodings to
 their translation as value.
 
-A quote type can be any symbol among `opening-double-quote',
-`closing-double-quote', `opening-single-quote',
-`closing-single-quote' and `apostrophe'.
+A quote type can be any symbol among `primary-opening',
+`primary-closing', `secondary-opening', `secondary-closing' and
+`apostrophe'.
 
 Valid encodings include `:utf-8', `:html', `:latex' and
 `:texinfo'.
 
 If no translation is found, the quote character is left as-is.")
 
-(defconst org-export-smart-quotes-regexps
-  (list
-   ;; Possible opening quote at beginning of string.
-   "\\`\\([\"']\\)\\(\\w\\|\\s.\\|\\s_\\|\\s(\\)"
-   ;; Possible closing quote at beginning of string.
-   "\\`\\([\"']\\)\\(\\s-\\|\\s)\\|\\s.\\)"
-   ;; Possible apostrophe at beginning of string.
-   "\\`\\('\\)\\S-"
-   ;; Opening single and double quotes.
-   "\\(?:\\s-\\|\\s(\\)\\([\"']\\)\\(?:\\w\\|\\s.\\|\\s_\\)"
-   ;; Closing single and double quotes.
-   "\\(?:\\w\\|\\s.\\|\\s_\\)\\([\"']\\)\\(?:\\s-\\|\\s)\\|\\s.\\)"
-   ;; Apostrophe.
-   "\\S-\\('\\)\\S-"
-   ;; Possible opening quote at end of string.
-   "\\(?:\\s-\\|\\s(\\)\\([\"']\\)\\'"
-   ;; Possible closing quote at end of string.
-   "\\(?:\\w\\|\\s.\\|\\s_\\)\\([\"']\\)\\'"
-   ;; Possible apostrophe at end of string.
-   "\\S-\\('\\)\\'")
-  "List of regexps matching a quote or an apostrophe.
-In every regexp, quote or apostrophe matched is put in group 1.")
+(defun org-export--smart-quote-status (s info)
+  "Return smart quote status at the beginning of string S.
+INFO is the current export state, as a plist."
+  (let* ((parent (org-element-property :parent s))
+        (cache (or (plist-get info :smart-quote-cache)
+                   (let ((table (make-hash-table :test #'eq)))
+                     (plist-put info :smart-quote-cache table)
+                     table)))
+        (value (gethash parent cache 'missing-data)))
+    (if (not (eq value 'missing-data)) (cdr (assq s value))
+      (let (level1-open full-status)
+       (org-element-map
+           (let ((secondary (org-element-secondary-p s)))
+             (if secondary (org-element-property secondary parent)
+               (org-element-contents parent)))
+           'plain-text
+         (lambda (text)
+           (let ((start 0) current-status)
+             (while (setq start (string-match "['\"]" text start))
+               (push
+                (cond
+                 ((equal (match-string 0 text) "\"")
+                  (setf level1-open (not level1-open))
+                  (if level1-open 'primary-opening 'primary-closing))
+                 ;; Not already in a level 1 quote: this is an
+                 ;; apostrophe.
+                 ((not level1-open) 'apostrophe)
+                 ;; Extract previous char and next char.  As
+                 ;; a special case, they can also be set to `blank',
+                 ;; `no-blank' or nil.  Then determine if current
+                 ;; match is allowed as an opening quote or a closing
+                 ;; quote.
+                 (t
+                  (let* ((previous
+                          (if (> start 0) (substring text (1- start) start)
+                            (let ((p (org-export-get-previous-element
+                                      text info)))
+                              (cond ((not p) nil)
+                                    ((stringp p) (substring p -1))
+                                    ((memq (org-element-property :post-blank p)
+                                           '(0 nil))
+                                     'no-blank)
+                                    (t 'blank)))))
+                         (next
+                          (if (< (1+ start) (length text))
+                              (substring text (1+ start) (+ start 2))
+                            (let ((n (org-export-get-next-element text info)))
+                              (cond ((not n) nil)
+                                    ((stringp n) (substring n 0 1))
+                                    (t 'no-blank)))))
+                         (allow-open
+                          (and (if (stringp previous)
+                                   (string-match "\\s\"\\|\\s-\\|\\s("
+                                                 previous)
+                                 (memq previous '(blank nil)))
+                               (if (stringp next)
+                                   (string-match "\\w\\|\\s.\\|\\s_" next)
+                                 (eq next 'no-blank))))
+                         (allow-close
+                          (and (if (stringp previous)
+                                   (string-match "\\w\\|\\s.\\|\\s_" previous)
+                                 (eq previous 'no-blank))
+                               (if (stringp next)
+                                   (string-match "\\s-\\|\\s)\\|\\s.\\|\\s\""
+                                                 next)
+                                 (memq next '(blank nil))))))
+                    (cond
+                     ((and allow-open allow-close) (error "Should not happen"))
+                     (allow-open 'secondary-opening)
+                     (allow-close 'secondary-closing)
+                     (t 'apostrophe)))))
+                current-status)
+               (cl-incf start))
+             (when current-status
+               (push (cons text (nreverse current-status)) full-status))))
+         info nil org-element-recursive-objects)
+       (puthash parent full-status cache)
+       (cdr (assq s full-status))))))
 
 (defun org-export-activate-smart-quotes (s encoding info &optional original)
   "Replace regular quotes with \"smart\" quotes in string S.
@@ -5013,107 +5421,18 @@ process, a non-nil ORIGINAL optional argument will 
provide that
 original string.
 
 Return the new string."
-  (if (equal s "") ""
-    (let* ((prev (org-export-get-previous-element (or original s) info))
-          ;; Try to be flexible when computing number of blanks
-          ;; before object.  The previous object may be a string
-          ;; introduced by the back-end and not completely parsed.
-          (pre-blank (and prev
-                          (or (org-element-property :post-blank prev)
-                              ;; A string with missing `:post-blank'
-                              ;; property.
-                              (and (stringp prev)
-                                   (string-match " *\\'" prev)
-                                   (length (match-string 0 prev)))
-                              ;; Fallback value.
-                              0)))
-          (next (org-export-get-next-element (or original s) info))
-          (get-smart-quote
-           (lambda (q type)
-             ;; Return smart quote associated to a give quote Q, as
-             ;; a string.  TYPE is a symbol among `open', `close' and
-             ;; `apostrophe'.
-             (let ((key (case type
-                          (apostrophe 'apostrophe)
-                          (open (if (equal "'" q) 'opening-single-quote
-                                  'opening-double-quote))
-                          (otherwise (if (equal "'" q) 'closing-single-quote
-                                       'closing-double-quote)))))
-               (or (plist-get
-                    (cdr (assq key
-                               (cdr (assoc (plist-get info :language)
-                                           org-export-smart-quotes-alist))))
-                    encoding)
-                   q)))))
-      (if (or (equal "\"" s) (equal "'" s))
-         ;; Only a quote: no regexp can match.  We have to check both
-         ;; sides and decide what to do.
-         (cond ((and (not prev) (not next)) s)
-               ((not prev) (funcall get-smart-quote s 'open))
-               ((and (not next) (zerop pre-blank))
-                (funcall get-smart-quote s 'close))
-               ((not next) s)
-               ((zerop pre-blank) (funcall get-smart-quote s 'apostrophe))
-               (t (funcall get-smart-quote 'open)))
-       ;; 1. Replace quote character at the beginning of S.
-       (cond
-        ;; Apostrophe?
-        ((and prev (zerop pre-blank)
-              (string-match (nth 2 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'apostrophe)
-                  nil t s 1)))
-        ;; Closing quote?
-        ((and prev (zerop pre-blank)
-              (string-match (nth 1 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'close)
-                  nil t s 1)))
-        ;; Opening quote?
-        ((and (or (not prev) (> pre-blank 0))
-              (string-match (nth 0 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'open)
-                  nil t s 1))))
-       ;; 2. Replace quotes in the middle of the string.
-       (setq s (replace-regexp-in-string
-                ;; Opening quotes.
-                (nth 3 org-export-smart-quotes-regexps)
-                (lambda (text)
-                  (funcall get-smart-quote (match-string 1 text) 'open))
-                s nil t 1))
-       (setq s (replace-regexp-in-string
-                ;; Closing quotes.
-                (nth 4 org-export-smart-quotes-regexps)
-                (lambda (text)
-                  (funcall get-smart-quote (match-string 1 text) 'close))
-                s nil t 1))
-       (setq s (replace-regexp-in-string
-                ;; Apostrophes.
-                (nth 5 org-export-smart-quotes-regexps)
-                (lambda (text)
-                  (funcall get-smart-quote (match-string 1 text) 'apostrophe))
-                s nil t 1))
-       ;; 3. Replace quote character at the end of S.
-       (cond
-        ;; Apostrophe?
-        ((and next (string-match (nth 8 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'apostrophe)
-                  nil t s 1)))
-        ;; Closing quote?
-        ((and (not next)
-              (string-match (nth 7 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'close)
-                  nil t s 1)))
-        ;; Opening quote?
-        ((and next (string-match (nth 6 org-export-smart-quotes-regexps) s))
-         (setq s (replace-match
-                  (funcall get-smart-quote (match-string 1 s) 'open)
-                  nil t s 1))))
-       ;; Return string with smart quotes.
-       s))))
+  (let ((quote-status
+        (copy-sequence (org-export--smart-quote-status (or original s) info))))
+    (replace-regexp-in-string
+     "['\"]"
+     (lambda (match)
+       (or (plist-get
+           (cdr (assq (pop quote-status)
+                      (cdr (assoc (plist-get info :language)
+                                  org-export-smart-quotes-alist))))
+           encoding)
+          match))
+     s nil t)))
 
 ;;;; Topology
 ;;
@@ -5125,46 +5444,23 @@ Return the new string."
 ;; (`org-export-get-parent-table'), previous element or object
 ;; (`org-export-get-previous-element') and next element or object
 ;; (`org-export-get-next-element').
-;;
-;; `org-export-get-genealogy' returns the full genealogy of a given
-;; element or object, from closest parent to full parse tree.
 
 ;; defsubst org-export-get-parent must be defined before first use
-(defun org-export-get-genealogy (blob)
-  "Return full genealogy relative to a given element or object.
-
-BLOB is the element or object being considered.
-
-Ancestors are returned from closest to farthest, the last one
-being the full parse tree."
-  (let (genealogy (parent blob))
-    (while (setq parent (org-element-property :parent parent))
-      (push parent genealogy))
-    (nreverse genealogy)))
 
 (defun org-export-get-parent-headline (blob)
   "Return BLOB parent headline or nil.
 BLOB is the element or object being considered."
-  (let ((parent blob))
-    (while (and (setq parent (org-element-property :parent parent))
-               (not (eq (org-element-type parent) 'headline))))
-    parent))
+  (org-element-lineage blob '(headline)))
 
 (defun org-export-get-parent-element (object)
   "Return first element containing OBJECT or nil.
 OBJECT is the object to consider."
-  (let ((parent object))
-    (while (and (setq parent (org-element-property :parent parent))
-               (memq (org-element-type parent) org-element-all-objects)))
-    parent))
+  (org-element-lineage object org-element-all-elements))
 
 (defun org-export-get-parent-table (object)
   "Return OBJECT parent table or nil.
 OBJECT is either a `table-cell' or `table-element' type object."
-  (let ((parent object))
-    (while (and (setq parent (org-element-property :parent parent))
-               (not (eq (org-element-type parent) 'table))))
-    parent))
+  (org-element-lineage object '(table)))
 
 (defun org-export-get-previous-element (blob info &optional n)
   "Return previous element or object.
@@ -5177,27 +5473,19 @@ When optional argument N is a positive integer, return 
a list
 containing up to N siblings before BLOB, from farthest to
 closest.  With any other non-nil value, return a list containing
 all of them."
-  (let ((siblings
-        ;; An object can belong to the contents of its parent or
-        ;; to a secondary string.  We check the latter option
-        ;; first.
-        (let ((parent (org-export-get-parent blob)))
-          (or (let ((sec-value (org-element-property
-                                (cdr (assq (org-element-type parent)
-                                           org-element-secondary-value-alist))
-                                parent)))
-                (and (memq blob sec-value) sec-value))
-              (org-element-contents parent))))
-       prev)
+  (let* ((secondary (org-element-secondary-p blob))
+        (parent (org-export-get-parent blob))
+        (siblings
+         (if secondary (org-element-property secondary parent)
+           (org-element-contents parent)))
+        prev)
     (catch 'exit
-      (mapc (lambda (obj)
-             (cond ((memq obj (plist-get info :ignore-list)))
-                   ((null n) (throw 'exit obj))
-                   ((not (wholenump n)) (push obj prev))
-                   ((zerop n) (throw 'exit prev))
-                   (t (decf n) (push obj prev))))
-           (cdr (memq blob (reverse siblings))))
-      prev)))
+      (dolist (obj (cdr (memq blob (reverse siblings))) prev)
+       (cond ((memq obj (plist-get info :ignore-list)))
+             ((null n) (throw 'exit obj))
+             ((not (wholenump n)) (push obj prev))
+             ((zerop n) (throw 'exit prev))
+             (t (cl-decf n) (push obj prev)))))))
 
 (defun org-export-get-next-element (blob info &optional n)
   "Return next element or object.
@@ -5210,26 +5498,20 @@ When optional argument N is a positive integer, return 
a list
 containing up to N siblings after BLOB, from closest to farthest.
 With any other non-nil value, return a list containing all of
 them."
-  (let ((siblings
-        ;; An object can belong to the contents of its parent or to
-        ;; a secondary string.  We check the latter option first.
-        (let ((parent (org-export-get-parent blob)))
-          (or (let ((sec-value (org-element-property
-                                (cdr (assq (org-element-type parent)
-                                           org-element-secondary-value-alist))
-                                parent)))
-                (cdr (memq blob sec-value)))
-              (cdr (memq blob (org-element-contents parent))))))
-       next)
+  (let* ((secondary (org-element-secondary-p blob))
+        (parent (org-export-get-parent blob))
+        (siblings
+         (cdr (memq blob
+                    (if secondary (org-element-property secondary parent)
+                      (org-element-contents parent)))))
+        next)
     (catch 'exit
-      (mapc (lambda (obj)
-             (cond ((memq obj (plist-get info :ignore-list)))
-                   ((null n) (throw 'exit obj))
-                   ((not (wholenump n)) (push obj next))
-                   ((zerop n) (throw 'exit (nreverse next)))
-                   (t (decf n) (push obj next))))
-           siblings)
-      (nreverse next))))
+      (dolist (obj siblings (nreverse next))
+       (cond ((memq obj (plist-get info :ignore-list)))
+             ((null n) (throw 'exit obj))
+             ((not (wholenump n)) (push obj next))
+             ((zerop n) (throw 'exit (nreverse next)))
+             (t (cl-decf n) (push obj next)))))))
 
 
 ;;;; Translation
@@ -5248,22 +5530,44 @@ them."
      ("de" :default "Autor")
      ("eo" :html "A&#365;toro")
      ("es" :default "Autor")
+     ("et" :default "Autor")
      ("fi" :html "Tekij&auml;")
      ("fr" :default "Auteur")
      ("hu" :default "Szerz&otilde;")
      ("is" :html "H&ouml;fundur")
      ("it" :default "Autore")
-     ("ja" :html "&#33879;&#32773;" :utf-8 "著者")
+     ("ja" :default "著者" :html "&#33879;&#32773;")
      ("nl" :default "Auteur")
      ("no" :default "Forfatter")
      ("nb" :default "Forfatter")
      ("nn" :default "Forfattar")
      ("pl" :default "Autor")
+     ("pt_BR" :default "Autor")
      ("ru" :html "&#1040;&#1074;&#1090;&#1086;&#1088;" :utf-8 "Автор")
      ("sv" :html "F&ouml;rfattare")
      ("uk" :html "&#1040;&#1074;&#1090;&#1086;&#1088;" :utf-8 "Автор")
      ("zh-CN" :html "&#20316;&#32773;" :utf-8 "作者")
      ("zh-TW" :html "&#20316;&#32773;" :utf-8 "作者"))
+    ("Continued from previous page"
+     ("de" :default "Fortsetzung von vorheriger Seite")
+     ("es" :html "Contin&uacute;a de la p&aacute;gina anterior" :ascii 
"Continua de la pagina anterior" :default "Continúa de la página anterior")
+     ("fr" :default "Suite de la page précédente")
+     ("it" :default "Continua da pagina precedente")
+     ("ja" :default "前ページからの続き")
+     ("nl" :default "Vervolg van vorige pagina")
+     ("pt" :default "Continuação da página anterior")
+     ("ru" :html 
"(&#1055;&#1088;&#1086;&#1076;&#1086;&#1083;&#1078;&#1077;&#1085;&#1080;&#1077;)"
+      :utf-8 "(Продолжение)"))
+    ("Continued on next page"
+     ("de" :default "Fortsetzung nächste Seite")
+     ("es" :html "Contin&uacute;a en la siguiente p&aacute;gina" :ascii 
"Continua en la siguiente pagina" :default "Continúa en la siguiente página")
+     ("fr" :default "Suite page suivante")
+     ("it" :default "Continua alla pagina successiva")
+     ("ja" :default "次ページに続く")
+     ("nl" :default "Vervolg op volgende pagina")
+     ("pt" :default "Continua na página seguinte")
+     ("ru" :html 
"(&#1055;&#1088;&#1086;&#1076;&#1086;&#1083;&#1078;&#1077;&#1085;&#1080;&#1077; 
&#1089;&#1083;&#1077;&#1076;&#1091;&#1077;&#1090;)"
+      :utf-8 "(Продолжение следует)"))
     ("Date"
      ("ca" :default "Data")
      ("cs" :default "Datum")
@@ -5271,16 +5575,18 @@ them."
      ("de" :default "Datum")
      ("eo" :default "Dato")
      ("es" :default "Fecha")
+     ("et" :html "Kuup&#228;ev" :utf-8 "Kuupäev")
      ("fi" :html "P&auml;iv&auml;m&auml;&auml;r&auml;")
      ("hu" :html "D&aacute;tum")
      ("is" :default "Dagsetning")
      ("it" :default "Data")
-     ("ja" :html "&#26085;&#20184;" :utf-8 "日付")
+     ("ja" :default "日付" :html "&#26085;&#20184;")
      ("nl" :default "Datum")
      ("no" :default "Dato")
      ("nb" :default "Dato")
      ("nn" :default "Dato")
      ("pl" :default "Data")
+     ("pt_BR" :default "Data")
      ("ru" :html "&#1044;&#1072;&#1090;&#1072;" :utf-8 "Дата")
      ("sv" :default "Datum")
      ("uk" :html "&#1044;&#1072;&#1090;&#1072;" :utf-8 "Дата")
@@ -5289,32 +5595,46 @@ them."
     ("Equation"
      ("da" :default "Ligning")
      ("de" :default "Gleichung")
-     ("es" :html "Ecuaci&oacute;n" :default "Ecuación")
+     ("es" :ascii "Ecuacion" :html "Ecuaci&oacute;n" :default "Ecuación")
+     ("et" :html "V&#245;rrand" :utf-8 "Võrrand")
      ("fr" :ascii "Equation" :default "Équation")
+     ("is" :default "Jafna")
+     ("ja" :default "方程式")
      ("no" :default "Ligning")
      ("nb" :default "Ligning")
      ("nn" :default "Likning")
+     ("pt_BR" :html "Equa&ccedil;&atilde;o" :default "Equação" :ascii 
"Equacao")
+     ("ru" :html 
"&#1059;&#1088;&#1072;&#1074;&#1085;&#1077;&#1085;&#1080;&#1077;"
+      :utf-8 "Уравнение")
      ("sv" :default "Ekvation")
      ("zh-CN" :html "&#26041;&#31243;" :utf-8 "方程"))
     ("Figure"
      ("da" :default "Figur")
      ("de" :default "Abbildung")
      ("es" :default "Figura")
-     ("ja" :html "&#22259;" :utf-8 "図")
+     ("et" :default "Joonis")
+     ("is" :default "Mynd")
+     ("ja" :default "図" :html "&#22259;")
      ("no" :default "Illustrasjon")
      ("nb" :default "Illustrasjon")
      ("nn" :default "Illustrasjon")
+     ("pt_BR" :default "Figura")
+     ("ru" :html "&#1056;&#1080;&#1089;&#1091;&#1085;&#1086;&#1082;" :utf-8 
"Рисунок")
      ("sv" :default "Illustration")
      ("zh-CN" :html "&#22270;" :utf-8 "图"))
     ("Figure %d:"
      ("da" :default "Figur %d")
      ("de" :default "Abbildung %d:")
      ("es" :default "Figura %d:")
+     ("et" :default "Joonis %d:")
      ("fr" :default "Figure %d :" :html "Figure&nbsp;%d&nbsp;:")
-     ("ja" :html "&#22259;%d: " :utf-8 "図%d: ")
+     ("is" :default "Mynd %d")
+     ("ja" :default "図%d: " :html "&#22259;%d: ")
      ("no" :default "Illustrasjon %d")
      ("nb" :default "Illustrasjon %d")
      ("nn" :default "Illustrasjon %d")
+     ("pt_BR" :default "Figura %d:")
+     ("ru" :html "&#1056;&#1080;&#1089;. %d.:" :utf-8 "Рис. %d.:")
      ("sv" :default "Illustration %d")
      ("zh-CN" :html "&#22270;%d&nbsp;" :utf-8 "图%d "))
     ("Footnotes"
@@ -5323,18 +5643,20 @@ them."
      ("da" :default "Fodnoter")
      ("de" :html "Fu&szlig;noten" :default "Fußnoten")
      ("eo" :default "Piednotoj")
-     ("es" :html "Nota al pie de p&aacute;gina" :default "Nota al pie de 
página")
+     ("es" :ascii "Nota al pie de pagina" :html "Nota al pie de p&aacute;gina" 
:default "Nota al pie de página")
+     ("et" :html "Allm&#228;rkused" :utf-8 "Allmärkused")
      ("fi" :default "Alaviitteet")
      ("fr" :default "Notes de bas de page")
      ("hu" :html "L&aacute;bjegyzet")
      ("is" :html "Aftanm&aacute;lsgreinar")
      ("it" :html "Note a pi&egrave; di pagina")
-     ("ja" :html "&#33050;&#27880;" :utf-8 "脚注")
+     ("ja" :default "脚注" :html "&#33050;&#27880;")
      ("nl" :default "Voetnoten")
      ("no" :default "Fotnoter")
      ("nb" :default "Fotnoter")
      ("nn" :default "Fotnotar")
      ("pl" :default "Przypis")
+     ("pt_BR" :html "Notas de Rodap&eacute;" :default "Notas de Rodapé" :ascii 
"Notas de Rodape")
      ("ru" :html "&#1057;&#1085;&#1086;&#1089;&#1082;&#1080;" :utf-8 "Сноски")
      ("sv" :default "Fotnoter")
      ("uk" :html "&#1055;&#1088;&#1080;&#1084;&#1110;&#1090;&#1082;&#1080;"
@@ -5344,50 +5666,107 @@ them."
     ("List of Listings"
      ("da" :default "Programmer")
      ("de" :default "Programmauflistungsverzeichnis")
-     ("es" :default "Indice de Listados de programas")
+     ("es" :ascii "Indice de Listados de programas" :html "&Iacute;ndice de 
Listados de programas" :default "Índice de Listados de programas")
+     ("et" :default "Loendite nimekiri")
      ("fr" :default "Liste des programmes")
+     ("ja" :default "ソースコード目次")
      ("no" :default "Dataprogrammer")
      ("nb" :default "Dataprogrammer")
+     ("ru" :html "&#1057;&#1087;&#1080;&#1089;&#1086;&#1082; 
&#1088;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1086;&#1082;"
+      :utf-8 "Список распечаток")
      ("zh-CN" :html "&#20195;&#30721;&#30446;&#24405;" :utf-8 "代码目录"))
     ("List of Tables"
      ("da" :default "Tabeller")
      ("de" :default "Tabellenverzeichnis")
-     ("es" :default "Indice de tablas")
+     ("es" :ascii "Indice de tablas" :html "&Iacute;ndice de tablas" :default 
"Índice de tablas")
+     ("et" :default "Tabelite nimekiri")
      ("fr" :default "Liste des tableaux")
+     ("is" :default "Töfluskrá" :html "T&ouml;fluskr&aacute;")
+     ("ja" :default "表目次")
      ("no" :default "Tabeller")
      ("nb" :default "Tabeller")
      ("nn" :default "Tabeller")
+     ("pt_BR" :default "Índice de Tabelas" :ascii "Indice de Tabelas")
+     ("ru" :html "&#1057;&#1087;&#1080;&#1089;&#1086;&#1082; 
&#1090;&#1072;&#1073;&#1083;&#1080;&#1094;"
+      :utf-8 "Список таблиц")
      ("sv" :default "Tabeller")
      ("zh-CN" :html "&#34920;&#26684;&#30446;&#24405;" :utf-8 "表格目录"))
+    ("Listing"
+     ("da" :default "Program")
+     ("de" :default "Programmlisting")
+     ("es" :default "Listado de programa")
+     ("et" :default "Loend")
+     ("fr" :default "Programme" :html "Programme")
+     ("ja" :default "ソースコード")
+     ("no" :default "Dataprogram")
+     ("nb" :default "Dataprogram")
+     ("pt_BR" :default "Listagem")
+     ("ru" :html 
"&#1056;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1082;&#1072;"
+      :utf-8 "Распечатка")
+     ("zh-CN" :html "&#20195;&#30721;" :utf-8 "代码"))
     ("Listing %d:"
      ("da" :default "Program %d")
      ("de" :default "Programmlisting %d")
      ("es" :default "Listado de programa %d")
+     ("et" :default "Loend %d")
      ("fr" :default "Programme %d :" :html "Programme&nbsp;%d&nbsp;:")
-     ("no" :default "Dataprogram")
-     ("nb" :default "Dataprogram")
+     ("ja" :default "ソースコード%d:")
+     ("no" :default "Dataprogram %d")
+     ("nb" :default "Dataprogram %d")
+     ("pt_BR" :default "Listagem %d")
+     ("ru" :html 
"&#1056;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1082;&#1072; %d.:"
+      :utf-8 "Распечатка %d.:")
      ("zh-CN" :html "&#20195;&#30721;%d&nbsp;" :utf-8 "代码%d "))
+    ("References"
+     ("fr" :ascii "References" :default "Références")
+     ("de" :default "Quellen")
+     ("es" :default "Referencias"))
+    ("See figure %s"
+     ("fr" :default "cf. figure %s"
+      :html "cf.&nbsp;figure&nbsp;%s" :latex "cf.~figure~%s"))
+    ("See listing %s"
+     ("fr" :default "cf. programme %s"
+      :html "cf.&nbsp;programme&nbsp;%s" :latex "cf.~programme~%s"))
     ("See section %s"
      ("da" :default "jævnfør afsnit %s")
      ("de" :default "siehe Abschnitt %s")
-     ("es" :default "vea seccion %s")
+     ("es" :ascii "Vea seccion %s" :html "Vea secci&oacute;n %s" :default "Vea 
sección %s")
+     ("et" :html "Vaata peat&#252;kki %s" :utf-8 "Vaata peatükki %s")
      ("fr" :default "cf. section %s")
-     ("zh-CN" :html "&#21442;&#35265;&#31532;%d&#33410;" :utf-8 "参见第%s节"))
+     ("ja" :default "セクション %s を参照")
+     ("pt_BR" :html "Veja a se&ccedil;&atilde;o %s" :default "Veja a seção %s"
+      :ascii "Veja a secao %s")
+     ("ru" :html "&#1057;&#1084;. &#1088;&#1072;&#1079;&#1076;&#1077;&#1083; 
%s"
+      :utf-8 "См. раздел %s")
+     ("zh-CN" :html "&#21442;&#35265;&#31532;%s&#33410;" :utf-8 "参见第%s节"))
+    ("See table %s"
+     ("fr" :default "cf. tableau %s"
+      :html "cf.&nbsp;tableau&nbsp;%s" :latex "cf.~tableau~%s"))
     ("Table"
      ("de" :default "Tabelle")
      ("es" :default "Tabla")
+     ("et" :default "Tabel")
      ("fr" :default "Tableau")
-     ("ja" :html "&#34920;" :utf-8 "表")
+     ("is" :default "Tafla")
+     ("ja" :default "表" :html "&#34920;")
+     ("pt_BR" :default "Tabela")
+     ("ru" :html "&#1058;&#1072;&#1073;&#1083;&#1080;&#1094;&#1072;"
+      :utf-8 "Таблица")
      ("zh-CN" :html "&#34920;" :utf-8 "表"))
     ("Table %d:"
      ("da" :default "Tabel %d")
      ("de" :default "Tabelle %d")
      ("es" :default "Tabla %d")
+     ("et" :default "Tabel %d")
      ("fr" :default "Tableau %d :")
-     ("ja" :html "&#34920;%d:" :utf-8 "表%d:")
+     ("is" :default "Tafla %d")
+     ("ja" :default "表%d:" :html "&#34920;%d:")
      ("no" :default "Tabell %d")
      ("nb" :default "Tabell %d")
      ("nn" :default "Tabell %d")
+     ("pt_BR" :default "Tabela %d")
+     ("ru" :html "&#1058;&#1072;&#1073;&#1083;&#1080;&#1094;&#1072; %d.:"
+      :utf-8 "Таблица %d.:")
      ("sv" :default "Tabell %d")
      ("zh-CN" :html "&#34920;%d&nbsp;" :utf-8 "表%d "))
     ("Table of Contents"
@@ -5396,18 +5775,20 @@ them."
      ("da" :default "Indhold")
      ("de" :default "Inhaltsverzeichnis")
      ("eo" :default "Enhavo")
-     ("es" :html "&Iacute;ndice")
+     ("es" :ascii "Indice" :html "&Iacute;ndice" :default "Índice")
+     ("et" :default "Sisukord")
      ("fi" :html "Sis&auml;llysluettelo")
      ("fr" :ascii "Sommaire" :default "Table des matières")
      ("hu" :html "Tartalomjegyz&eacute;k")
      ("is" :default "Efnisyfirlit")
      ("it" :default "Indice")
-     ("ja" :html "&#30446;&#27425;" :utf-8 "目次")
+     ("ja" :default "目次" :html "&#30446;&#27425;")
      ("nl" :default "Inhoudsopgave")
      ("no" :default "Innhold")
      ("nb" :default "Innhold")
      ("nn" :default "Innhald")
      ("pl" :html "Spis tre&#x015b;ci")
+     ("pt_BR" :html "&Iacute;ndice" :utf8 "Índice" :ascii "Indice")
      ("ru" :html 
"&#1057;&#1086;&#1076;&#1077;&#1088;&#1078;&#1072;&#1085;&#1080;&#1077;"
       :utf-8 "Содержание")
      ("sv" :html "Inneh&aring;ll")
@@ -5417,16 +5798,22 @@ them."
     ("Unknown reference"
      ("da" :default "ukendt reference")
      ("de" :default "Unbekannter Verweis")
-     ("es" :default "referencia desconocida")
+     ("es" :default "Referencia desconocida")
+     ("et" :default "Tundmatu viide")
      ("fr" :ascii "Destination inconnue" :default "Référence inconnue")
+     ("ja" :default "不明な参照先")
+     ("pt_BR" :default "Referência desconhecida"
+      :ascii "Referencia desconhecida")
+     ("ru" :html 
"&#1053;&#1077;&#1080;&#1079;&#1074;&#1077;&#1089;&#1090;&#1085;&#1072;&#1103; 
&#1089;&#1089;&#1099;&#1083;&#1082;&#1072;"
+      :utf-8 "Неизвестная ссылка")
      ("zh-CN" :html "&#26410;&#30693;&#24341;&#29992;" :utf-8 "未知引用")))
   "Dictionary for export engine.
 
-Alist whose CAR is the string to translate and CDR is an alist
-whose CAR is the language string and CDR is a plist whose
+Alist whose car is the string to translate and cdr is an alist
+whose car is the language string and cdr is a plist whose
 properties are possible charsets and values translated terms.
 
-It is used as a database for `org-export-translate'. Since this
+It is used as a database for `org-export-translate'.  Since this
 function returns the string as-is if no translation was found,
 the variable only needs to record values different from the
 entry.")
@@ -5437,9 +5824,9 @@ entry.")
 ENCODING is a symbol among `:ascii', `:html', `:latex', `:latin1'
 and `:utf-8'.  INFO is a plist used as a communication channel.
 
-Translation depends on `:language' property. Return the
-translated string. If no translation is found, try to fall back
-to `:default' encoding. If it fails, return S."
+Translation depends on `:language' property.  Return the
+translated string.  If no translation is found, try to fall back
+to `:default' encoding.  If it fails, return S."
   (let* ((lang (plist-get info :language))
         (translations (cdr (assoc lang
                                   (cdr (assoc s org-export-dictionary))))))
@@ -5524,12 +5911,17 @@ and `org-export-to-file' for more specialized 
functions."
          (let* ((process-connection-type nil)
                 (,proc-buffer (generate-new-buffer-name "*Org Export 
Process*"))
                 (,process
-                 (start-process
-                  "org-export-process" ,proc-buffer
-                  (expand-file-name invocation-name invocation-directory)
-                  "-Q" "--batch"
-                  "-l" org-export-async-init-file
-                  "-l" ,temp-file)))
+                (apply
+                 #'start-process
+                 (append
+                  (list "org-export-process"
+                        ,proc-buffer
+                        (expand-file-name invocation-name invocation-directory)
+                        "--batch")
+                  (if org-export-async-init-file
+                      (list "-Q" "-l" org-export-async-init-file)
+                    (list "-l" user-init-file))
+                  (list "-l" ,temp-file)))))
            ;; Register running process in stack.
            (org-export-add-to-stack (get-buffer ,proc-buffer) nil ,process)
            ;; Set-up sentinel in order to catch results.
@@ -5698,31 +6090,21 @@ of subtree at point.
 When optional argument PUB-DIR is set, use it as the publishing
 directory.
 
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
 Return file name as a string."
   (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
         (base-name
          ;; File name may come from EXPORT_FILE_NAME subtree
-         ;; property, assuming point is at beginning of said
-         ;; sub-tree.
+         ;; property.
          (file-name-sans-extension
-          (or (and subtreep
-                   (org-entry-get
-                    (save-excursion
-                      (ignore-errors (org-back-to-heading) (point)))
-                    "EXPORT_FILE_NAME" t))
+          (or (and subtreep (org-entry-get nil "EXPORT_FILE_NAME" 'selective))
               ;; File name may be extracted from buffer's associated
               ;; file, if any.
               (and visited-file (file-name-nondirectory visited-file))
               ;; Can't determine file name on our own: Ask user.
-              (let ((read-file-name-function
-                     (and org-completion-use-ido 'ido-read-file-name)))
-                (read-file-name
-                 "Output file: " pub-dir nil nil nil
-                 (lambda (name)
-                   (string= (file-name-extension name t) extension)))))))
+              (read-file-name
+               "Output file: " pub-dir nil nil nil
+               (lambda (name)
+                 (string= (file-name-extension name t) extension))))))
         (output-file
          ;; Build file name.  Enforce EXTENSION over whatever user
          ;; may have come up with.  PUB-DIR, if defined, always has
@@ -5736,7 +6118,7 @@ Return file name as a string."
           (t (concat (file-name-as-directory ".") base-name extension)))))
     ;; If writing to OUTPUT-FILE would overwrite original file, append
     ;; EXTENSION another time to final name.
-    (if (and visited-file (org-file-equal-p visited-file output-file))
+    (if (and visited-file (file-equal-p visited-file output-file))
        (concat output-file extension)
       output-file)))
 
@@ -5757,68 +6139,21 @@ removed beforehand.  Return the new stack."
   "Menu for asynchronous export results and running processes."
   (interactive)
   (let ((buffer (get-buffer-create "*Org Export Stack*")))
-    (set-buffer buffer)
-    (when (zerop (buffer-size)) (org-export-stack-mode))
-    (org-export-stack-refresh)
+    (with-current-buffer buffer
+      (org-export-stack-mode)
+      (tabulated-list-print t))
     (pop-to-buffer buffer))
   (message "Type \"q\" to quit, \"?\" for help"))
 
-(defun org-export--stack-source-at-point ()
-  "Return source from export results at point in stack."
-  (let ((source (car (nth (1- (org-current-line)) org-export-stack-contents))))
-    (if (not source) (error "Source unavailable, please refresh buffer")
-      (let ((source-name (if (stringp source) source (buffer-name source))))
-       (if (save-excursion
-             (beginning-of-line)
-             (looking-at (concat ".* +" (regexp-quote source-name) "$")))
-           source
-         ;; SOURCE is not consistent with current line.  The stack
-         ;; view is outdated.
-         (error "Source unavailable; type `g' to update buffer"))))))
-
 (defun org-export-stack-clear ()
   "Remove all entries from export stack."
   (interactive)
   (setq org-export-stack-contents nil))
 
-(defun org-export-stack-refresh (&rest dummy)
-  "Refresh the asynchronous export stack.
-DUMMY is ignored.  Unavailable sources are removed from the list.
-Return the new stack."
-  (let ((inhibit-read-only t))
-    (org-preserve-lc
-     (erase-buffer)
-     (insert (concat
-             (let ((counter 0))
-               (mapconcat
-                (lambda (entry)
-                  (let ((proc-p (processp (nth 2 entry))))
-                    (concat
-                     ;; Back-end.
-                     (format " %-12s  " (or (nth 1 entry) ""))
-                     ;; Age.
-                     (let ((data (nth 2 entry)))
-                       (if proc-p (format " %6s  " (process-status data))
-                         ;; Compute age of the results.
-                         (org-format-seconds
-                          "%4h:%.2m  "
-                          (float-time (time-since data)))))
-                     ;; Source.
-                     (format " %s"
-                             (let ((source (car entry)))
-                               (if (stringp source) source
-                                 (buffer-name source)))))))
-                ;; Clear stack from exited processes, dead buffers or
-                ;; non-existent files.
-                (setq org-export-stack-contents
-                      (org-remove-if-not
-                       (lambda (el)
-                         (if (processp (nth 2 el))
-                             (buffer-live-p (process-buffer (nth 2 el)))
-                           (let ((source (car el)))
-                             (if (bufferp source) (buffer-live-p source)
-                               (file-exists-p source)))))
-                       org-export-stack-contents)) "\n")))))))
+(defun org-export-stack-refresh ()
+  "Refresh the export stack."
+  (interactive)
+  (tabulated-list-print t))
 
 (defun org-export-stack-remove (&optional source)
   "Remove export results at point from stack.
@@ -5826,7 +6161,7 @@ If optional argument SOURCE is non-nil, remove it 
instead."
   (interactive)
   (let ((source (or source (org-export--stack-source-at-point))))
     (setq org-export-stack-contents
-         (org-remove-if (lambda (el) (equal (car el) source))
+         (cl-remove-if (lambda (el) (equal (car el) source))
                         org-export-stack-contents))))
 
 (defun org-export-stack-view (&optional in-emacs)
@@ -5842,11 +6177,10 @@ within Emacs."
 
 (defvar org-export-stack-mode-map
   (let ((km (make-sparse-keymap)))
+    (set-keymap-parent km tabulated-list-mode-map)
     (define-key km " " 'next-line)
-    (define-key km "n" 'next-line)
     (define-key km "\C-n" 'next-line)
     (define-key km [down] 'next-line)
-    (define-key km "p" 'previous-line)
     (define-key km "\C-p" 'previous-line)
     (define-key km "\C-?" 'previous-line)
     (define-key km [up] 'previous-line)
@@ -5857,31 +6191,85 @@ within Emacs."
     km)
   "Keymap for Org Export Stack.")
 
-(define-derived-mode org-export-stack-mode special-mode "Org-Stack"
+(define-derived-mode org-export-stack-mode tabulated-list-mode "Org-Stack"
   "Mode for displaying asynchronous export stack.
 
-Type \\[org-export-stack] to visualize the asynchronous export
+Type `\\[org-export-stack]' to visualize the asynchronous export
 stack.
 
-In an Org Export Stack buffer, use 
\\<org-export-stack-mode-map>\\[org-export-stack-view] to view export output
-on current line, \\[org-export-stack-remove] to remove it from the stack and 
\\[org-export-stack-clear] to clear
+In an Org Export Stack buffer, use \
+\\<org-export-stack-mode-map>`\\[org-export-stack-view]' to view export output
+on current line, `\\[org-export-stack-remove]' to remove it from the stack and 
\
+`\\[org-export-stack-clear]' to clear
 stack completely.
 
-Removing entries in an Org Export Stack buffer doesn't affect
-files or buffers, only the display.
+Removing entries in a stack buffer does not affect files
+or buffers, only display.
 
 \\{org-export-stack-mode-map}"
-  (abbrev-mode 0)
-  (auto-fill-mode 0)
-  (setq buffer-read-only t
-       buffer-undo-list t
-       truncate-lines t
-       header-line-format
-       '(:eval
-         (format "  %-12s | %6s | %s" "Back-End" "Age" "Source")))
-  (org-add-hook 'post-command-hook 'org-export-stack-refresh nil t)
-  (set (make-local-variable 'revert-buffer-function)
-       'org-export-stack-refresh))
+  (setq tabulated-list-format
+       (vector (list "#" 4 #'org-export--stack-num-predicate)
+               (list "Back-End" 12 t)
+               (list "Age" 6 nil)
+               (list "Source" 0 nil)))
+  (setq tabulated-list-sort-key (cons "#" nil))
+  (setq tabulated-list-entries #'org-export--stack-generate)
+  (add-hook 'tabulated-list-revert-hook #'org-export--stack-generate nil t)
+  (add-hook 'post-command-hook #'org-export-stack-refresh nil t)
+  (tabulated-list-init-header))
+
+(defun org-export--stack-generate ()
+  "Generate the asynchronous export stack for display.
+Unavailable sources are removed from the list.  Return a list
+appropriate for `tabulated-list-print'."
+  ;; Clear stack from exited processes, dead buffers or non-existent
+  ;; files.
+  (setq org-export-stack-contents
+       (cl-remove-if-not
+        (lambda (el)
+          (if (processp (nth 2 el))
+              (buffer-live-p (process-buffer (nth 2 el)))
+            (let ((source (car el)))
+              (if (bufferp source) (buffer-live-p source)
+                (file-exists-p source)))))
+        org-export-stack-contents))
+  ;; Update `tabulated-list-entries'.
+  (let ((counter 0))
+    (mapcar
+     (lambda (entry)
+       (let ((source (car entry)))
+        (list source
+              (vector
+               ;; Counter.
+               (number-to-string (cl-incf counter))
+               ;; Back-End.
+               (if (nth 1 entry) (symbol-name (nth 1 entry)) "")
+               ;; Age.
+               (let ((info (nth 2 entry)))
+                 (if (processp info) (symbol-name (process-status info))
+                   (format-seconds "%h:%.2m" (float-time (time-since info)))))
+               ;; Source.
+               (if (stringp source) source (buffer-name source))))))
+     org-export-stack-contents)))
+
+(defun org-export--stack-num-predicate (a b)
+  (< (string-to-number (aref (nth 1 a) 0))
+     (string-to-number (aref (nth 1 b) 0))))
+
+(defun org-export--stack-source-at-point ()
+  "Return source from export results at point in stack."
+  (let ((source (car (nth (1- (org-current-line)) org-export-stack-contents))))
+    (if (not source) (error "Source unavailable, please refresh buffer")
+      (let ((source-name (if (stringp source) source (buffer-name source))))
+       (if (save-excursion
+             (beginning-of-line)
+             (looking-at-p (concat ".* +" (regexp-quote source-name) "$")))
+           source
+         ;; SOURCE is not consistent with current line.  The stack
+         ;; view is outdated.
+         (error (substitute-command-keys
+                 "Source unavailable; type `\\[org-export-stack-refresh]' \
+to refresh buffer")))))))
 
 
 
@@ -5907,10 +6295,12 @@ SPC and DEL (resp. C-n and C-p) keys.
 Set variable `org-export-dispatch-use-expert-ui' to switch to one
 flavor or the other.
 
-When ARG is \\[universal-argument], repeat the last export action, with the 
same set
-of options used back then, on the current buffer.
+When ARG is `\\[universal-argument]', repeat the last export action, with the\
+ same
+set of options used back then, on the current buffer.
 
-When ARG is \\[universal-argument] \\[universal-argument], display the 
asynchronous export stack."
+When ARG is `\\[universal-argument] \\[universal-argument]', display the \
+asynchronous export stack."
   (interactive "P")
   (let* ((input
          (cond ((equal arg '(16)) '(stack))
@@ -5935,7 +6325,7 @@ When ARG is \\[universal-argument] 
\\[universal-argument], display the asynchron
         (optns (cdr input)))
     (unless (memq 'subtree optns)
       (move-marker org-export-dispatch-last-position nil))
-    (case action
+    (cl-case action
       ;; First handle special hard-coded actions.
       (template (org-export-insert-default-template nil optns))
       (stack (org-export-stack))
@@ -5944,7 +6334,7 @@ When ARG is \\[universal-argument] 
\\[universal-argument], display the asynchron
       (publish-current-project
        (org-publish-current-project (memq 'force optns) (memq 'async optns)))
       (publish-choose-project
-       (org-publish (assoc (org-icompleting-read
+       (org-publish (assoc (completing-read
                            "Publish project: "
                            org-publish-project-alist nil t)
                           org-publish-project-alist)
@@ -5995,19 +6385,19 @@ back to standard interface."
            ;; on the first key, if any.  A nil value means KEY will
            ;; only be activated at first level.
            (if (or (eq access-key t) (eq access-key first-key))
-               (org-propertize key 'face 'org-warning)
+               (propertize key 'face 'org-warning)
              key)))
         (fontify-value
          (lambda (value)
            ;; Fontify VALUE string.
-           (org-propertize value 'face 'font-lock-variable-name-face)))
+           (propertize value 'face 'font-lock-variable-name-face)))
         ;; Prepare menu entries by extracting them from registered
         ;; back-ends and sorting them by access key and by ordinal,
         ;; if any.
         (entries
          (sort (sort (delq nil
-                           (mapcar 'org-export-backend-menu
-                                   org-export--registered-backends))
+                           (mapcar #'org-export-backend-menu
+                                   org-export-registered-backends))
                      (lambda (a b)
                        (let ((key-a (nth 1 a))
                              (key-b (nth 1 b)))
@@ -6037,8 +6427,8 @@ back to standard interface."
            (concat
             ;; Options are hard-coded.
             (format "[%s] Body only:    %s           [%s] Visible only:     %s
-[%s] Export scope: %s       [%s] Force publishing: %s
-[%s] Async export: %s\n\n"
+\[%s] Export scope: %s       [%s] Force publishing: %s
+\[%s] Async export: %s\n\n"
                     (funcall fontify-key "C-b" t)
                     (funcall fontify-value
                              (if (memq 'body options) "On " "Off"))
@@ -6074,7 +6464,7 @@ back to standard interface."
                           (concat
                            (mapconcat
                             (lambda (sub-entry)
-                              (incf index)
+                              (cl-incf index)
                               (format
                                (if (zerop (mod index 2)) "    [%s] %-26s"
                                  "[%s] %s\n")
@@ -6145,7 +6535,7 @@ back to standard interface."
        standard-prompt allowed-keys entries options first-key expertp))))
 
 (defun org-export--dispatch-action
-  (prompt allowed-keys entries options first-key expertp)
+    (prompt allowed-keys entries options first-key expertp)
   "Read a character from command input and act accordingly.
 
 PROMPT is the displayed prompt, as a string.  ALLOWED-KEYS is
@@ -6163,7 +6553,7 @@ options as CDR."
     (while (and (setq key (read-char-exclusive prompt))
                (not expertp)
                (memq key '(14 16 ?\s ?\d)))
-      (case key
+      (cl-case key
        (14 (if (not (pos-visible-in-window-p (point-max)))
                (ignore-errors (scroll-up 1))
              (message "End of buffer")
@@ -6200,8 +6590,8 @@ options as CDR."
      ;; Toggle options: C-b (2) C-v (22) C-s (19) C-f (6) C-a (1).
      ((memq key '(2 22 19 6 1))
       (org-export--dispatch-ui
-       (let ((option (case key (2 'body) (22 'visible) (19 'subtree)
-                          (6 'force) (1 'async))))
+       (let ((option (cl-case key (2 'body) (22 'visible) (19 'subtree)
+                             (6 'force) (1 'async))))
         (if (memq option options) (remq option options)
           (cons option options)))
        first-key expertp))
@@ -6213,7 +6603,7 @@ options as CDR."
             ;; Publishing actions are hard-coded.  Send a special
             ;; signal to `org-export-dispatch'.
             ((eq first-key ?P)
-             (case key
+             (cl-case key
                (?f 'publish-current-file)
                (?p 'publish-current-project)
                (?x 'publish-choose-project)
@@ -6222,10 +6612,9 @@ options as CDR."
             ;; path. Indeed, derived backends can share the same
             ;; FIRST-KEY.
             (t (catch 'found
-                 (mapc (lambda (entry)
-                         (let ((match (assq key (nth 2 entry))))
-                           (when match (throw 'found (nth 2 match)))))
-                       (member (assq first-key entries) entries)))))
+                 (dolist (entry (member (assq first-key entries) entries))
+                   (let ((match (assq key (nth 2 entry))))
+                     (when match (throw 'found (nth 2 match))))))))
            options))
      ;; Otherwise, enter sub-menu.
      (t (org-export--dispatch-ui options key expertp)))))



reply via email to

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